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