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