View Javadoc
1   package org.exolab.castor.xml.parsing;
2   
3   import org.exolab.castor.types.AnyNode;
4   import org.exolab.castor.xml.util.SAX2ANY;
5   import org.xml.sax.AttributeList;
6   import org.xml.sax.Attributes;
7   import org.xml.sax.SAXException;
8   
9   public class AnyNodeUnmarshalHandler {
10  
11    private NamespaceHandling _namespaceHandling;
12  
13    /**
14     * A SAX2ANY unmarshaller in case we are dealing with {@literal <any>}.
15     */
16    private SAX2ANY _anyUnmarshaller = null;
17  
18    /**
19     * The any branch depth.
20     */
21    private int _depth = 0;
22  
23    /**
24     * Keeps track of the current element information as passed by the parser.
25     */
26    private ElementInfo _elemInfo = null;
27  
28    public AnyNodeUnmarshalHandler(NamespaceHandling namespaceHandling) {
29      _namespaceHandling = namespaceHandling;
30    }
31  
32    /**
33     * Delegates startElement to SAX2ANY. Sets any branch depth counter to 1.
34     * 
35     * @param name Name of the element if we use SAX 2
36     * @param namespace Namespace of the element
37     * @param wsPreserve preserve whitespaces ?
38     * @return Object anyUnmarshaller get StartingNode
39     * @throws SAXException
40     */
41    public Object commonStartElement(String name, String namespace, boolean wsPreserve)
42        throws SAXException {
43      // 1- creates a new SAX2ANY handler
44      _anyUnmarshaller = new SAX2ANY(_namespaceHandling.getNamespaceStack(), wsPreserve);
45      // 2- delegates the element handling
46      if (_elemInfo._attributeList != null) {
47        // -- SAX 1
48        startElement(_elemInfo._qName, _elemInfo._attributeList);
49      } else {
50        // -- SAX 2
51        startElement(namespace, name, _elemInfo._qName, _elemInfo._attributes);
52      }
53      // first element so depth can only be one at this point
54      _depth = 1;
55      return _anyUnmarshaller.getStartingNode();
56    }
57  
58    /**
59     * delegates ignorableWhitespace call to SAX2ANY.
60     * 
61     * @param ch Characters
62     * @param start Offset
63     * @param length Length
64     * @throws SAXException
65     */
66    public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
67      _anyUnmarshaller.ignorableWhitespace(ch, start, length);
68    }
69  
70    /**
71     * Delegates SAX1 startElement to SAX2ANY. Increases any branch depth counter.
72     * 
73     * @param name Name of the element.
74     * @param attList Attribute list.
75     * @throws SAXException
76     */
77    public void startElement(String name, AttributeList attList) throws SAXException {
78      _depth++;
79      _anyUnmarshaller.startElement(name, attList);
80      return;
81    }
82  
83    /**
84     * Delegates SAX2 startElement to SAX2ANY. Increases any branch depth counter.
85     * 
86     * @param namespaceURI
87     * @param localName
88     * @param qName
89     * @param atts
90     * @throws SAXException
91     */
92    public void startElement(String namespaceURI, String localName, String qName, Attributes atts)
93        throws SAXException {
94      _depth++;
95      _anyUnmarshaller.startElement(namespaceURI, localName, qName, atts);
96      return;
97    }
98  
99    /**
100    * Delegates endElement to SAX2ANY.
101    * 
102    * @param name
103    * @throws SAXException
104    */
105   public void endElement(String name) throws SAXException {
106     _anyUnmarshaller.endElement(name);
107     _depth--;
108   }
109 
110   /**
111    * delegates characters to SAX2ANY.
112    * 
113    * @param ch
114    * @param start
115    * @param length
116    * @throws SAXException
117    */
118   public void characters(char[] ch, int start, int length) throws SAXException {
119     _anyUnmarshaller.characters(ch, start, length);
120   }
121 
122   /**
123    * delegates startPrefixMapping to SAX2ANY.
124    * 
125    * @param prefix
126    * @param uri
127    * @throws SAXException
128    */
129   public void startPrefixMapping(String prefix, String uri) throws SAXException {
130     _anyUnmarshaller.startPrefixMapping(prefix, uri);
131   }
132 
133   /**
134    * delegates endPrefixMapping to SAX2ANY.
135    * 
136    * @param prefix
137    * @throws SAXException
138    */
139   public void endPrefixMapping(String prefix) throws SAXException {
140     _anyUnmarshaller.endPrefixMapping(prefix);
141   }
142 
143   /**
144    * Checks if there is a SAX2ANY object
145    * 
146    * @return True if there is a SAX2ANY.
147    */
148   public boolean hasAnyUnmarshaller() {
149     return _anyUnmarshaller != null;
150   }
151 
152   /**
153    * Checks if any branch depth counter is zero.
154    * 
155    * @return true if 0
156    */
157   public boolean isStartingNode() {
158     return _depth == 0;
159   }
160 
161   /**
162    * Returns SAX2ANY startingNode.
163    * 
164    * @return
165    */
166   public AnyNode getStartingNode() {
167     AnyNode startingNode = _anyUnmarshaller.getStartingNode();
168     _anyUnmarshaller = null;
169     return startingNode;
170   }
171 
172   /**
173    * Preserves passed name and attributes.
174    * 
175    * @param name Name
176    * @param atts Attributes
177    */
178   public void preservePassedArguments(String name, Attributes atts) {
179     _elemInfo = setElementInfo(_elemInfo, name, atts);
180   }
181 
182   /**
183    * Preserves passed name and attributes.
184    * 
185    * @param name Name
186    * @param attList AttributeList
187    */
188   public void preservePassedArguments(String name, AttributeList attList) {
189     _elemInfo = setElementInfo(_elemInfo, name, attList);
190   }
191 
192   /**
193    * Sets name and attList on element
194    * 
195    * @param element ElementInfo, can be null
196    * @param name Name
197    * @param attList Attributes
198    * @return element on which name and attList are set
199    */
200   private ElementInfo setElementInfo(ElementInfo element, String name, AttributeList attList) {
201     if (element == null) {
202       return new ElementInfo(name, attList);
203     }
204     element.clear();
205     element._qName = name;
206     element._attributeList = attList;
207     return element;
208   }
209 
210   /**
211    * Sets name and attributes on element
212    * 
213    * @param element ElementInfo, can be null
214    * @param name Name
215    * @param attributes Attributes
216    * @return element on which name and attributes are set
217    */
218   private ElementInfo setElementInfo(ElementInfo element, String name, Attributes attributes) {
219     if (element == null) {
220       return new ElementInfo(name, attributes);
221     }
222     element.clear();
223     element._qName = name;
224     element._attributes = attributes;
225     return element;
226   }
227 
228   /**
229    * A utility class for keeping track of the qName and how the SAX parser passed attributes.
230    */
231   class ElementInfo {
232     String _qName = null;
233     Attributes _attributes = null;
234     AttributeList _attributeList = null;
235 
236     ElementInfo() {
237       super();
238     }
239 
240     ElementInfo(String qName, Attributes atts) {
241       super();
242       _qName = qName;
243       _attributes = atts;
244     }
245 
246     ElementInfo(String qName, AttributeList atts) {
247       super();
248       _qName = qName;
249       _attributeList = atts;
250     }
251 
252     void clear() {
253       _qName = null;
254       _attributes = null;
255       _attributeList = null;
256     }
257 
258   } // -- ElementInfo
259 
260 }