001: /*
002: Copyright (c) 2004-2007, Dennis M. Sosnoski
003: All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without modification,
006: are permitted provided that the following conditions are met:
007:
008: * Redistributions of source code must retain the above copyright notice, this
009: list of conditions and the following disclaimer.
010: * Redistributions in binary form must reproduce the above copyright notice,
011: this list of conditions and the following disclaimer in the documentation
012: and/or other materials provided with the distribution.
013: * Neither the name of JiBX nor the names of its contributors may be used
014: to endorse or promote products derived from this software without specific
015: prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
018: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
019: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
020: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
021: ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
022: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
023: LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
024: ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
026: SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: package org.jibx.binding.model;
030:
031: import java.util.ArrayList;
032:
033: /**
034: * Tracks the validation state. This includes the current validation phase, as
035: * well as order-dependent state information collected while walking the tree
036: * structure of a binding model. Collects all errors and warnings and maintains
037: * a summary of the severity of the problems found.
038: *
039: * @author Dennis M. Sosnoski
040: * @version 1.0
041: */
042:
043: public class ValidationContext extends TreeContext {
044: /** Number of warnings reported. */
045: private int m_warningCount;
046:
047: /** Number of errors reported. */
048: private int m_errorCount;
049:
050: /** Number of fatals reported. */
051: private int m_fatalCount;
052:
053: /** List of problem items reported by validation. */
054: private ArrayList m_problemList;
055:
056: /**
057: * Constructor.
058: *
059: * @param iloc class locator
060: */
061: public ValidationContext(IClassLocator iloc) {
062: super (iloc);
063: m_problemList = new ArrayList();
064: }
065:
066: /**
067: * Peek current element of hierarchy, if any. This variation should be used
068: * for the actual error handling, in case an error occurs during the
069: * initialization of the outer context definitions (canned definitions).
070: *
071: * @return current element, or <code>null</code> if none
072: */
073: private ElementBase safePeekElement() {
074: try {
075: return peekElement();
076: } catch (ArrayIndexOutOfBoundsException e) {
077: // just in case there is no context element
078: return null;
079: }
080: }
081:
082: /**
083: * Prevalidate binding model tree. This calls the prevalidate method for
084: * each element in the tree, in preorder traversal order.
085: *
086: * @param root binding node of tree to be prevalidated
087: */
088: public void prevalidate(BindingElement root) {
089: PrevalidationVisitor visitor = new PrevalidationVisitor();
090: tourTree(root, visitor);
091: }
092:
093: /**
094: * Validate binding model tree. This calls the validate method for each
095: * element in the tree, in postorder traversal order.
096: *
097: * @param root binding node of tree to be prevalidated
098: */
099: public void validate(BindingElement root) {
100: ValidationVisitor visitor = new ValidationVisitor();
101: tourTree(root, visitor);
102: }
103:
104: /**
105: * Get number of warning problems reported.
106: *
107: * @return warning problem count
108: */
109: public int getWarningCount() {
110: return m_warningCount;
111: }
112:
113: /**
114: * Get number of error problems reported.
115: *
116: * @return error problem count
117: */
118: public int getErrorCount() {
119: return m_errorCount;
120: }
121:
122: /**
123: * Get number of fatal problems reported.
124: *
125: * @return fatal problem count
126: */
127: public int getFatalCount() {
128: return m_fatalCount;
129: }
130:
131: /**
132: * Add warning item for current element. Adds a warning item to the problem
133: * list, which is a possible problem that still allows reasonable operation.
134: * This form of the call can only be used during a tree tour being
135: * controlled by this context.
136: *
137: * @param msg problem description
138: */
139: public void addWarning(String msg) {
140: addWarning(msg, safePeekElement());
141: }
142:
143: /**
144: * Add warning item. Adds a warning item to the problem list, which is a
145: * possible problem that still allows reasonable operation.
146: *
147: * @param msg problem description
148: * @param obj source object for validation error
149: */
150: public void addWarning(String msg, Object obj) {
151: addProblem(new ValidationProblem(
152: ValidationProblem.WARNING_LEVEL, msg, obj));
153: }
154:
155: /**
156: * Add error item for current element. Adds an error item to the problem
157: * list, which is a definite problem that still allows validation to
158: * proceed. This form of the call can only be used during a tree tour being
159: * controlled by this context.
160: *
161: * @param msg problem description
162: */
163: public void addError(String msg) {
164: addError(msg, safePeekElement());
165: }
166:
167: /**
168: * Add error item. Adds an error item to the problem list, which is a
169: * definite problem that still allows validation to proceed.
170: *
171: * @param msg problem description
172: * @param obj source object for validation error
173: */
174: public void addError(String msg, Object obj) {
175: addProblem(new ValidationProblem(ValidationProblem.ERROR_LEVEL,
176: msg, obj));
177: }
178:
179: /**
180: * Add fatal item for current element. Adds a fatal item to the problem
181: * list, which is a severe problem that blocks further validation within the
182: * tree branch involved. This form of the call can only be used during a
183: * tree tour being controlled by this context.
184: *
185: * @param msg problem description
186: */
187: public void addFatal(String msg) {
188: addFatal(msg, safePeekElement());
189: }
190:
191: /**
192: * Add fatal item. Adds a fatal item to the problem list, which is a severe
193: * problem that blocks further validation within the tree branch involved.
194: * The object associated with a fatal error should always be an element.
195: *
196: * @param msg problem description
197: * @param obj source object for validation error (should be an element)
198: */
199: public void addFatal(String msg, Object obj) {
200: addProblem(new ValidationProblem(ValidationProblem.FATAL_LEVEL,
201: msg, obj));
202: }
203:
204: /**
205: * Add problem report. The problem is added and counted as appropriate.
206: *
207: * @param problem details of problem report
208: */
209: public void addProblem(ValidationProblem problem) {
210: m_problemList.add(problem);
211: switch (problem.getSeverity()) {
212:
213: case ValidationProblem.ERROR_LEVEL:
214: m_errorCount++;
215: break;
216:
217: case ValidationProblem.FATAL_LEVEL:
218: m_fatalCount++;
219: addSkip(problem.getComponent());
220: break;
221:
222: case ValidationProblem.WARNING_LEVEL:
223: m_warningCount++;
224: break;
225:
226: }
227: }
228:
229: /**
230: * Get list of problems.
231: *
232: * @return problem list
233: */
234: public ArrayList getProblems() {
235: return m_problemList;
236: }
237:
238: /**
239: * Inner class for handling prevalidation. This visitor implementation just
240: * calls the {@link org.jibx.binding.model#prevalidate} method for each
241: * element visited in preorder.
242: */
243: protected class PrevalidationVisitor extends ModelVisitor {
244: /* (non-Javadoc)
245: * @see org.jibx.binding.model.ModelVisitor#visit(org.jibx.binding.model.ElementBase)
246: */
247: public boolean visit(ElementBase node) {
248: try {
249: node.prevalidate(ValidationContext.this );
250: } catch (Throwable t) {
251: addFatal("Error during validation: " + t.getMessage());
252: t.printStackTrace();
253: return false;
254: }
255: return true;
256: }
257: }
258:
259: /**
260: * Inner class for handling validation. This visitor implementation just
261: * calls the {@link org.jibx.binding.model#validate} method for each
262: * element visited in postorder.
263: */
264: protected class ValidationVisitor extends ModelVisitor {
265: /* (non-Javadoc)
266: * @see org.jibx.binding.model.ModelVisitor#exit(org.jibx.binding.model.ElementBase)
267: */
268: public void exit(ElementBase node) {
269: try {
270: node.validate(ValidationContext.this );
271: } catch (Throwable t) {
272: addFatal("Error during validation: " + t.getMessage());
273: t.printStackTrace();
274: }
275: }
276: }
277: }
|