001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: package com.sun.xml.stream.buffer.stax;
021:
022: import com.sun.xml.stream.buffer.MutableXMLStreamBuffer;
023: import org.jvnet.staxex.Base64Data;
024: import org.jvnet.staxex.XMLStreamReaderEx;
025:
026: import javax.xml.stream.XMLStreamException;
027: import javax.xml.stream.XMLStreamReader;
028: import java.util.HashMap;
029: import java.util.Map;
030:
031: /**
032: * Create a buffer using an {@link XMLStreamReader}.
033: * <p>
034: * TODO: Implement the marking the stream on the element when an ID
035: * attribute on the element is defined
036: */
037: public class StreamReaderBufferCreator extends StreamBufferCreator {
038: private int _eventType;
039: private boolean _storeInScopeNamespacesOnElementFragment;
040: private Map<String, Integer> _inScopePrefixes;
041:
042: /**
043: * Create a stream reader buffer creator.
044: * <p>
045: * A stream buffer will be created for storing the infoset
046: * from a stream reader.
047: */
048: public StreamReaderBufferCreator() {
049: }
050:
051: /**
052: * Create a stream reader buffer creator using a mutable stream buffer.
053: * <p>
054: * @param buffer the mutable stream buffer.
055: */
056: public StreamReaderBufferCreator(MutableXMLStreamBuffer buffer) {
057: setBuffer(buffer);
058: }
059:
060: /**
061: * Create the buffer from a stream reader.
062: * <p>
063: * The stream reader must be positioned at the start of the document
064: * or the start of an element.
065: * <p>
066: * If the stream is positioned at the start of the document then the
067: * whole document is stored and after storing the stream will be positioned
068: * at the end of the document.
069: * <p>
070: * If the stream is positioned at the start of an element then the
071: * element and all its children will be stored and after storing the stream
072: * will be positioned at the next event after the end of the element.
073: * <p>
074: * @return the mutable stream buffer.
075: * @throws XMLStreamException if the stream reader is not positioned at
076: * the start of the document or at an element.
077: */
078: public MutableXMLStreamBuffer create(XMLStreamReader reader)
079: throws XMLStreamException {
080: if (_buffer == null) {
081: createBuffer();
082: }
083: store(reader);
084:
085: return getXMLStreamBuffer();
086: }
087:
088: /**
089: * Creates the buffer from a stream reader that is an element fragment.
090: * <p>
091: * The stream reader will be moved to the position of the next start of
092: * an element if the stream reader is not already positioned at the start
093: * of an element.
094: * <p>
095: * The element and all its children will be stored and after storing the stream
096: * will be positioned at the next event after the end of the element.
097: * <p>
098: * @param storeInScopeNamespaces true if in-scope namespaces of the element
099: * fragment should be stored.
100: * @return the mutable stream buffer.
101: * @throws XMLStreamException if the stream reader cannot be positioned at
102: * the start of an element.
103: */
104: public MutableXMLStreamBuffer createElementFragment(
105: XMLStreamReader reader, boolean storeInScopeNamespaces)
106: throws XMLStreamException {
107: if (_buffer == null) {
108: createBuffer();
109: }
110:
111: if (!reader.hasNext()) {
112: return _buffer;
113: }
114:
115: _storeInScopeNamespacesOnElementFragment = storeInScopeNamespaces;
116:
117: _eventType = reader.getEventType();
118: if (_eventType != XMLStreamReader.START_ELEMENT) {
119: do {
120: _eventType = reader.next();
121: } while (_eventType != XMLStreamReader.START_ELEMENT
122: && _eventType != XMLStreamReader.END_DOCUMENT);
123: }
124:
125: if (storeInScopeNamespaces) {
126: _inScopePrefixes = new HashMap<String, Integer>();
127: }
128:
129: storeElementAndChildren(reader);
130:
131: return getXMLStreamBuffer();
132: }
133:
134: private void store(XMLStreamReader reader)
135: throws XMLStreamException {
136: if (!reader.hasNext()) {
137: return;
138: }
139:
140: _eventType = reader.getEventType();
141: switch (_eventType) {
142: case XMLStreamReader.START_DOCUMENT:
143: storeDocumentAndChildren(reader);
144: break;
145: case XMLStreamReader.START_ELEMENT:
146: storeElementAndChildren(reader);
147: break;
148: default:
149: throw new XMLStreamException(
150: "XMLStreamReader not positioned at a document or element");
151: }
152:
153: increaseTreeCount();
154: }
155:
156: private void storeDocumentAndChildren(XMLStreamReader reader)
157: throws XMLStreamException {
158: storeStructure(T_DOCUMENT);
159:
160: _eventType = reader.next();
161: while (_eventType != XMLStreamReader.END_DOCUMENT) {
162: switch (_eventType) {
163: case XMLStreamReader.START_ELEMENT:
164: storeElementAndChildren(reader);
165: continue;
166: case XMLStreamReader.COMMENT:
167: storeComment(reader);
168: break;
169: case XMLStreamReader.PROCESSING_INSTRUCTION:
170: storeProcessingInstruction(reader);
171: break;
172: }
173: _eventType = reader.next();
174: }
175:
176: storeStructure(T_END);
177: }
178:
179: private void storeElementAndChildren(XMLStreamReader reader)
180: throws XMLStreamException {
181: if (reader instanceof XMLStreamReaderEx) {
182: storeElementAndChildrenEx((XMLStreamReaderEx) reader);
183: } else {
184: storeElementAndChildrenNoEx(reader);
185: }
186: }
187:
188: private void storeElementAndChildrenEx(XMLStreamReaderEx reader)
189: throws XMLStreamException {
190: int depth = 1;
191: if (_storeInScopeNamespacesOnElementFragment) {
192: storeElementWithInScopeNamespaces(reader);
193: } else {
194: storeElement(reader);
195: }
196:
197: while (depth > 0) {
198: _eventType = reader.next();
199: switch (_eventType) {
200: case XMLStreamReader.START_ELEMENT:
201: depth++;
202: storeElement(reader);
203: break;
204: case XMLStreamReader.END_ELEMENT:
205: depth--;
206: storeStructure(T_END);
207: break;
208: case XMLStreamReader.NAMESPACE:
209: storeNamespaceAttributes(reader);
210: break;
211: case XMLStreamReader.ATTRIBUTE:
212: storeAttributes(reader);
213: break;
214: case XMLStreamReader.SPACE:
215: case XMLStreamReader.CHARACTERS:
216: case XMLStreamReader.CDATA: {
217: CharSequence c = reader.getPCDATA();
218: if (c instanceof Base64Data) {
219: storeStructure(T_TEXT_AS_OBJECT);
220: storeContentObject(((Base64Data) c).clone());
221: } else {
222: storeContentCharacters(T_TEXT_AS_CHAR_ARRAY, reader
223: .getTextCharacters(),
224: reader.getTextStart(), reader
225: .getTextLength());
226: }
227: break;
228: }
229: case XMLStreamReader.COMMENT:
230: storeComment(reader);
231: break;
232: case XMLStreamReader.PROCESSING_INSTRUCTION:
233: storeProcessingInstruction(reader);
234: break;
235: }
236: }
237:
238: /*
239: * Move to next item after the end of the element
240: * that has been stored
241: */
242: _eventType = reader.next();
243: }
244:
245: private void storeElementAndChildrenNoEx(XMLStreamReader reader)
246: throws XMLStreamException {
247: int depth = 1;
248: if (_storeInScopeNamespacesOnElementFragment) {
249: storeElementWithInScopeNamespaces(reader);
250: } else {
251: storeElement(reader);
252: }
253:
254: while (depth > 0) {
255: _eventType = reader.next();
256: switch (_eventType) {
257: case XMLStreamReader.START_ELEMENT:
258: depth++;
259: storeElement(reader);
260: break;
261: case XMLStreamReader.END_ELEMENT:
262: depth--;
263: storeStructure(T_END);
264: break;
265: case XMLStreamReader.NAMESPACE:
266: storeNamespaceAttributes(reader);
267: break;
268: case XMLStreamReader.ATTRIBUTE:
269: storeAttributes(reader);
270: break;
271: case XMLStreamReader.SPACE:
272: case XMLStreamReader.CHARACTERS:
273: case XMLStreamReader.CDATA: {
274: storeContentCharacters(T_TEXT_AS_CHAR_ARRAY, reader
275: .getTextCharacters(), reader.getTextStart(),
276: reader.getTextLength());
277: break;
278: }
279: case XMLStreamReader.COMMENT:
280: storeComment(reader);
281: break;
282: case XMLStreamReader.PROCESSING_INSTRUCTION:
283: storeProcessingInstruction(reader);
284: break;
285: }
286: }
287:
288: /*
289: * Move to next item after the end of the element
290: * that has been stored
291: */
292: _eventType = reader.next();
293: }
294:
295: private void storeElementWithInScopeNamespaces(
296: XMLStreamReader reader) {
297: storeQualifiedName(T_ELEMENT_LN, reader.getPrefix(), reader
298: .getNamespaceURI(), reader.getLocalName());
299:
300: if (reader.getNamespaceCount() > 0) {
301: storeNamespaceAttributes(reader);
302: }
303:
304: if (reader.getAttributeCount() > 0) {
305: storeAttributes(reader);
306: }
307: }
308:
309: private void storeElement(XMLStreamReader reader) {
310: storeQualifiedName(T_ELEMENT_LN, reader.getPrefix(), reader
311: .getNamespaceURI(), reader.getLocalName());
312:
313: if (reader.getNamespaceCount() > 0) {
314: storeNamespaceAttributes(reader);
315: }
316:
317: if (reader.getAttributeCount() > 0) {
318: storeAttributes(reader);
319: }
320: }
321:
322: private void storeNamespaceAttributes(XMLStreamReader reader) {
323: int count = reader.getNamespaceCount();
324: for (int i = 0; i < count; i++) {
325: storeNamespaceAttribute(reader.getNamespacePrefix(i),
326: reader.getNamespaceURI(i));
327: }
328: }
329:
330: private void storeAttributes(XMLStreamReader reader) {
331: int count = reader.getAttributeCount();
332: for (int i = 0; i < count; i++) {
333: storeAttribute(reader.getAttributePrefix(i), reader
334: .getAttributeNamespace(i), reader
335: .getAttributeLocalName(i), reader
336: .getAttributeType(i), reader.getAttributeValue(i));
337: }
338: }
339:
340: private void storeComment(XMLStreamReader reader) {
341: storeContentCharacters(T_COMMENT_AS_CHAR_ARRAY, reader
342: .getTextCharacters(), reader.getTextStart(), reader
343: .getTextLength());
344: }
345:
346: private void storeProcessingInstruction(XMLStreamReader reader) {
347: storeProcessingInstruction(reader.getPITarget(), reader
348: .getPIData());
349: }
350: }
|