All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axiom.util.stax.XMLFragmentStreamReader Maven / Gradle / Ivy

There is a newer version: 5.0.22
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axiom.util.stax;

import java.util.NoSuchElementException;

import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

/**
 * Wrapping XML stream reader that reads a single element from the underlying stream.
 * It will generate START_DOCUMENT and END_DOCUMENT events as required to make
 * the sequence of events appear as a complete document.
 * 

* Assume for example that the parent reader is parsing the following document: *

<a><b>text</b></a>
* If the current event is <b> when the wrapper is created, it will produce * the following sequence of events: *

*

    *
  • A synthetic START_DOCUMENT event.
  • *
  • START_ELEMENT, CHARACTERS and END_ELEMENT events for <b>text</b>. * For these events, the wrapper directly delegates to the parent reader.
  • *
  • A synthetic END_DOCUMENT event.
  • *
* By default, after all events have been consumed from the wrapper, the current event on the * parent reader will be the event following the last END_ELEMENT of the fragment. In the example * above this will be </a>. The * {@link #XMLFragmentStreamReader(XMLStreamReader, boolean)} constructor allows to override this * behavior. *

* The wrapper will release the reference to the parent reader when {@link #close()} is called. * For obvious reasons, the wrapper will never call {@link XMLStreamReader#close()} on the parent * reader. */ public class XMLFragmentStreamReader implements XMLStreamReader { // The current event is a synthetic START_DOCUMENT event private static final int STATE_START_DOCUMENT = 0; // The current event is from the fragment and there will be more events from the fragment private static final int STATE_IN_FRAGMENT = 1; // The current event is the final END_ELEMENT event from the fragment private static final int STATE_FRAGMENT_END = 2; // The current event is a synthetic END_DOCUMENT event private static final int STATE_END_DOCUMENT = 3; private XMLStreamReader parent; private final boolean proceedToNext; private int state; private int depth; /** * Constructor. * * @param parent the parent reader to read the fragment from * @throws IllegalStateException if the current event on the parent is not a START_ELEMENT */ public XMLFragmentStreamReader(XMLStreamReader parent) { this(parent, true); } /** * Constructor. * * @param parent * the parent reader to read the fragment from * @param proceedToNext * determines whether the parent reader should be positioned on the * {@link XMLStreamConstants#END_ELEMENT} event of the fragment ({@code false}) or on * event following the {@link XMLStreamConstants#END_ELEMENT} event ({@code true}) * after all events have been consumed from the wrapper * @throws IllegalStateException * if the current event on the parent is not a START_ELEMENT */ public XMLFragmentStreamReader(XMLStreamReader parent, boolean proceedToNext) { this.parent = parent; this.proceedToNext = proceedToNext; if (parent.getEventType() != START_ELEMENT) { throw new IllegalStateException("Expected START_ELEMENT as current event"); } } @Override public int getEventType() { switch (state) { case STATE_START_DOCUMENT: return START_DOCUMENT; case STATE_IN_FRAGMENT: return parent.getEventType(); case STATE_FRAGMENT_END: return END_ELEMENT; case STATE_END_DOCUMENT: return END_DOCUMENT; default: // We will never get here; just make the compiler happy. throw new IllegalStateException(); } } @Override public int next() throws XMLStreamException { switch (state) { case STATE_START_DOCUMENT: state = STATE_IN_FRAGMENT; return START_ELEMENT; case STATE_IN_FRAGMENT: int type = parent.next(); switch (type) { case START_ELEMENT: depth++; break; case END_ELEMENT: if (depth == 0) { state = STATE_FRAGMENT_END; } else { depth--; } } return type; case STATE_FRAGMENT_END: if (proceedToNext) { parent.next(); } state = STATE_END_DOCUMENT; return END_DOCUMENT; default: throw new NoSuchElementException("End of document reached"); } } @Override public int nextTag() throws XMLStreamException { switch (state) { case STATE_START_DOCUMENT: state = STATE_IN_FRAGMENT; return START_ELEMENT; case STATE_END_DOCUMENT: case STATE_FRAGMENT_END: throw new NoSuchElementException(); default: int result = parent.nextTag(); switch (result) { case START_ELEMENT: depth++; break; case END_ELEMENT: if (depth == 0) { state = STATE_FRAGMENT_END; } else { depth--; } } return result; } } @Override public void close() throws XMLStreamException { parent = null; } @Override public Object getProperty(String name) throws IllegalArgumentException { return parent.getProperty(name); } @Override public String getCharacterEncodingScheme() { if (state == STATE_START_DOCUMENT) { return null; } else { throw new IllegalStateException(); } } @Override public String getEncoding() { if (state == STATE_START_DOCUMENT) { return null; } else { throw new IllegalStateException(); } } @Override public String getVersion() { return "1.0"; } @Override public boolean isStandalone() { return true; } @Override public boolean standaloneSet() { return false; } @Override public Location getLocation() { return parent.getLocation(); } @Override public int getAttributeCount() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeCount(); } } @Override public String getAttributeLocalName(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeLocalName(index); } } @Override public QName getAttributeName(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeName(index); } } @Override public String getAttributeNamespace(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeNamespace(index); } } @Override public String getAttributePrefix(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributePrefix(index); } } @Override public String getAttributeType(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeType(index); } } @Override public String getAttributeValue(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeValue(index); } } @Override public boolean isAttributeSpecified(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.isAttributeSpecified(index); } } @Override public String getAttributeValue(String namespaceURI, String localName) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getAttributeValue(namespaceURI, localName); } } @Override public String getElementText() throws XMLStreamException { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getElementText(); } } @Override public String getLocalName() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getLocalName(); } } @Override public QName getName() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getName(); } } @Override public String getPrefix() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getPrefix(); } } @Override public String getNamespaceURI() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getNamespaceURI(); } } @Override public int getNamespaceCount() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getNamespaceCount(); } } @Override public String getNamespacePrefix(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getNamespacePrefix(index); } } @Override public String getNamespaceURI(int index) { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getNamespaceURI(index); } } @Override public String getNamespaceURI(String prefix) { // It is not clear whether this method is allowed in all states. // The XMLStreamReader Javadoc suggest it is, but Woodstox doesn't // allow it on states other than START_ELEMENT and END_ELEMENT. // We emulate behavior of Woodstox. if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getNamespaceURI(prefix); } } @Override public NamespaceContext getNamespaceContext() { return parent.getNamespaceContext(); } @Override public String getPIData() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getPIData(); } } @Override public String getPITarget() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getPITarget(); } } @Override public String getText() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getText(); } } @Override public char[] getTextCharacters() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getTextCharacters(); } } @Override public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) throws XMLStreamException { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return getTextCharacters(sourceStart, target, targetStart, length); } } @Override public int getTextLength() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getTextLength(); } } @Override public int getTextStart() { if (state == STATE_START_DOCUMENT || state == STATE_END_DOCUMENT) { throw new IllegalStateException(); } else { return parent.getTextStart(); } } @Override public boolean hasName() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.hasName(); } @Override public boolean hasNext() throws XMLStreamException { return state != STATE_END_DOCUMENT; } @Override public boolean hasText() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.hasText(); } @Override public boolean isCharacters() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.isCharacters(); } @Override public boolean isStartElement() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.isStartElement(); } @Override public boolean isEndElement() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.isEndElement(); } @Override public boolean isWhiteSpace() { return state != STATE_START_DOCUMENT && state != STATE_END_DOCUMENT && parent.isWhiteSpace(); } @Override public void require(int type, String namespaceURI, String localName) throws XMLStreamException { switch (state) { case STATE_START_DOCUMENT: if (type != START_DOCUMENT) { throw new XMLStreamException("Expected START_DOCUMENT"); } break; case STATE_END_DOCUMENT: if (type != END_DOCUMENT) { throw new XMLStreamException("Expected END_DOCUMENT"); } break; default: parent.require(type, namespaceURI, localName); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy