View Javadoc
1   /*
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 2002 (C) Intalio, Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  package org.exolab.castor.xml;
36  
37  import java.util.Collections;
38  import java.util.HashSet;
39  import java.util.Set;
40  
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  import org.castor.xml.InternalContext;
44  
45  /**
46   * A class which can be used to hold validation information, used by the TypeValidator interface.
47   *
48   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
49   * @version $Revision$ $Date: 2004-10-06 02:10:17 -0600 (Wed, 06 Oct 2004) $
50   */
51  public class ValidationContext {
52    /** Logger for debugging and error information. */
53    private static final Log LOG = LogFactory.getLog(ValidationContext.class);
54  
55    /** The Castor internal context - mother of all dwelling. */
56    private InternalContext _internalContext = null;
57  
58    /**
59     * A flag to indicate fail-fast validation. When true, the first error encounted will cause a
60     * Validation Exception. When false, the validator should attempt to validate as much as possible,
61     * collecting as many errors as possible before throwing a validation exception.
62     */
63    private boolean _failFast = true;
64  
65    /** The List of objects marked as validated. */
66    private final Set<Object> _validated = new HashSet<>();
67  
68    /** The Set of already encountered IDs (of type &lt;xsd:ID>). */
69    private final Set<String> _ids = new HashSet<>();
70  
71    /** The Set of temporary unresolved IDREFS. */
72    private final Set<String> _unresolvedIdrefs = new HashSet<>();
73  
74    /**
75     * To get the {@link AbstractInternalContext} to use.
76     * 
77     * @return the {@link AbstractInternalContext}?to use
78     */
79    public InternalContext getInternalContext() {
80      return _internalContext;
81    }
82  
83    /**
84     * To set which {@link AbstractInternalContext} should be used.
85     * 
86     * @param internalContext the {@link AbstractInternalContext} to use
87     */
88    public void setInternalContext(final InternalContext internalContext) {
89      _internalContext = internalContext;
90    }
91  
92    /**
93     * Returns the ClassDescriptorResolver to use during validation.
94     *
95     * @return the ClassDescriptorResolver to use. May be null.
96     */
97    public XMLClassDescriptorResolver getClassDescriptorResolver() {
98      return _internalContext.getXMLClassDescriptorResolver();
99    }
100 
101   /**
102    * Returns true if the validation process should fail upon first error encountered, otherwise the
103    * validation processs will attempt to validate as much as possible (even after the first error is
104    * encountered) and collect as many errors before either returning (no errors) or throwing a
105    * validationException containing the list of errors.
106    * <p>
107    * <b>NOTE: DISABLING OF FAIL-FAST IS NOT YET ENABLED.</b>
108    *
109    * @return true if fail-fast processing is enabled.
110    */
111   public boolean isFailFast() {
112     return _failFast;
113   }
114 
115   /**
116    * Sets the fail-fast flag. Fail-fast is enabled by default. When fail-fast is enabled (default or
117    * by setting the flag to true) the validation process will throw an exception upon the first
118    * error encountered. When fail-fast is disabled (by setting the flag to false) the validation
119    * processs will attempt to validate even after the first error is encountered and collect as many
120    * errors before either returning (no errors) or throwing a validationException containing the
121    * list of errors.
122    * <p>
123    * <b>NOTE: DISABLING FAIL-FAST IS NOT YET ENABLED.</b>
124    *
125    * @param failFast a boolean that when true enables fail-fast validation, otherwise the validator
126    *        will attempt to validate as much as it can reporting as many errors as possible before
127    *        returning.
128    */
129   public void setFailFast(final boolean failFast) {
130     _failFast = failFast;
131   }
132 
133   /**
134    * Checks whether an object has already been validated.
135    * 
136    * @param object The object for which the check should be performed
137    * @return True if the object specified has already been validated.
138    */
139   protected boolean isValidated(final Object object) {
140     if (LOG.isTraceEnabled()) {
141       LOG.trace("Called isValidated(" + object + ")");
142     }
143     return _validated.contains(object);
144   }
145 
146   /**
147    * Adds the specified object to the cache of already validated objects.
148    * 
149    * @param object Object about to be validated.
150    */
151   protected void addValidated(final Object object) {
152     if (LOG.isTraceEnabled()) {
153       LOG.trace("Called addValidated(" + object + ")");
154     }
155     _validated.add(object);
156   }
157 
158   /**
159    * Removes the specified object from the cache of already validated objects.
160    * 
161    * @param object The object to be removed from the cache.
162    */
163   protected void removeValidated(final Object object) {
164     if (LOG.isTraceEnabled()) {
165       LOG.trace("Called removeValidated(" + object + ")");
166     }
167     _validated.remove(object);
168   }
169 
170   /**
171    * Adds current ID (as seen during (un)marshalling) to the ID cache. If this ID was previously
172    * added to the Set of unresolved IDs, then remove it from that Set.
173    *
174    * @param id The current ID
175    * @throws ValidationException If an ID is used more than once.
176    * @see #getUnresolvedIdRefs()
177    */
178   public void addID(final String id) throws ValidationException {
179     if (!_ids.contains(id)) {
180       _ids.add(id);
181       _unresolvedIdrefs.remove(id);
182     } else if (!_internalContext.getLenientIdValidation()) {
183       throw new ValidationException("ID " + id + " is already used within current document.");
184     }
185   }
186 
187   /**
188    * Checks an ID Reference, returning true if the provided ID is known. If the provided ID is not
189    * known, it is added to the Set of unresolved ID references. Note that if this ID is later found,
190    * it will be removed from this Set.
191    *
192    * @param id The ID to check.
193    * @return true if the provided ID is known.
194    * @see #getUnresolvedIdRefs()
195    */
196   public boolean checkIdRef(final String id) {
197     if (!_ids.contains(id)) {
198       _unresolvedIdrefs.add(id);
199       return false;
200     }
201     return true;
202   }
203 
204   /**
205    * Returns the Set of unresolved ID references. The Set returns is not modifiable, but is
206    * available to be used to list all unresolved references.
207    *
208    * @return the Set of unresolved ID references.
209    */
210   public Set<String> getUnresolvedIdRefs() {
211     return Collections.unmodifiableSet(_unresolvedIdrefs);
212   }
213 
214   /**
215    * Life-cycle method for proper 'shutdown operations'.
216    */
217   public void cleanup() {
218     _ids.clear();
219     _validated.clear();
220     _unresolvedIdrefs.clear();
221   }
222 }