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