1 package org.exolab.castor.xml.parsing;
2
3 import org.exolab.castor.xml.UnmarshalHandler;
4
5 /**
6 * A helper class for {@link UnmarshalHandler}.
7 *
8 * Keeps track if elements, which appear in XML but for which there is no
9 * mapping, should be allowed.
10 *
11 * @author <a href="mailto:philipp DOT erlacher AT gmail DOT com">Philipp
12 * Erlacher</a>
13 *
14 * @since 1.3.2
15 */
16 public class StrictElementHandler {
17
18 /**
19 * A boolean that indicates element processing should be strict and an error
20 * should be flagged if any extra elements exist.
21 **/
22 private boolean _strictElements = true;
23
24 /**
25 * A depth counter that increases as we skip elements ( in startElement )
26 * and decreases as we process and endElement. Only active if _strictElements is
27 * set.
28 */
29 private int _ignoreElementDepth = 0;
30
31 /**
32 * Sets whether or not elements that do not match a specific field should
33 * simply be ignored or reported as an error. By default, extra elements
34 * are ignored.
35 *
36 * @param ignoreExtraElems
37 * a boolean that when true will allow non-matched attributes to
38 * simply be ignored.
39 **/
40 public void setIgnoreExtraElements(boolean ignoreExtraElems) {
41 _strictElements = (!ignoreExtraElems);
42 }
43
44 /**
45 * Checks if extra elements will be ignored.
46 *
47 * @return true if we ignore extra elements, false otherwise
48 */
49 public boolean areElementsIgnorable() {
50 return !_strictElements;
51 }
52
53 /**
54 * Skip element that appear in XML but for which we have no mapping
55 *
56 * @return
57 */
58 public boolean skipElement() {
59 return _ignoreElementDepth > 0;
60 }
61
62 /**
63 * Checks if a start element can be skipped
64 *
65 * @return true if start element can be skipped, false otherwise
66 */
67 public boolean skipStartElement() {
68 if (areElementsIgnorable() && skipElement()) {
69 addIgnorableElement();
70 return true;
71 }
72 return false;
73 }
74
75 /**
76 * Checks if a start element can be skipped omitting current value of element depth.
77 *
78 * @return true if start element can be skipped, false otherwise
79 */
80 public boolean skipStartElementIgnoringDepth() {
81 if (areElementsIgnorable()) {
82 addIgnorableElement();
83 return true;
84 }
85 return false;
86 }
87
88 /**
89 * Checks if an end element can be skipped.
90 *
91 * @return true if end element can be skipped, false otherwise
92 */
93 public boolean skipEndElement() {
94 if (skipElement()) {
95 remIgnorableElement();
96 return true;
97 }
98 return false;
99 }
100
101 /**
102 * Decreases the depth counter for elements which should be skipped.
103 */
104 private void remIgnorableElement() {
105 --_ignoreElementDepth;
106 }
107
108 /**
109 * Increases the depth counter for elements for which we have no mapping.
110 */
111 private void addIgnorableElement() {
112 ++_ignoreElementDepth;
113 }
114 }