/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* A processor of a {@link XMLStreamBuffer} that reads the XML infoset as
* {@link XMLStreamReader}.
*
* <p>
* Because of {@link XMLStreamReader} design, this processor always produce
* a full document infoset, even if the buffer just contains a fragment.
*
* <p>
* When {@link XMLStreamBuffer} contains a multiple tree (AKA "forest"),
* {@link XMLStreamReader} will behave as if there are multiple root elements
* (so you'll see {@link #START_ELEMENT} event where you'd normally expect
* {@link #END_DOCUMENT}.)
*
* @author Paul.Sandoz@Sun.Com
* @author K.Venugopal@sun.com
*/
// Stack to hold element and namespace declaration information
/** The top-most active entry of the {@link #_stack}. */
/** The element depth that we are in. Used to determine when we are done with a tree. */
protected int _depth;
// Arrays to hold all namespace declarations
/**
* Namespace prefixes. Can be empty but not null.
*/
protected int _namespaceAIIsEnd;
// Internal namespace context implementation
// The current event type
protected int _eventType;
/**
* Holder of the attributes.
*
* Be careful that this follows the SAX convention of using "" instead of null.
*/
// Characters as a CharSequence
// Characters as a char array with offset and length
protected char[] _characters;
protected int _textOffset;
protected int _textLen;
//
// Represents the parser state wrt the end of parsing.
//
/**
* The parser is in the middle of parsing a document,
* with no end in sight.
*/
/**
* The parser has already reported the {@link #END_ELEMENT},
* and we are parsing a fragment. We'll report {@link #END_DOCUMENT}
* next and be done.
*/
/**
* The parser has reported the {@link #END_DOCUMENT} event,
* so we are really done parsing.
*/
/**
* True if processing is complete.
*/
private int _completionState;
public StreamReaderBufferProcessor() {
_stack[i] = new ElementStackEntry();
}
_attributeCache = new AttributesHolder();
}
this();
}
_namespaceAIIsEnd = 0;
_characters = null;
}
/**
* Does {@link #nextTag()} and if the parser moved to a new start tag,
* returns a {@link XMLStreamBufferMark} that captures the infoset starting
* from the newly discovered element.
*
* <p>
* (Ideally we should have a method that works against the current position,
* but the way the data structure is read makes this somewhat difficult.)
*
* This creates a new {@link XMLStreamBufferMark} that shares the underlying
* data storage, thus it's fairly efficient.
*/
while (true) {
int s = peekStructure();
// next is start element.
for (int i=0 ; i<_namespaceAIIsEnd; i++)
next();
return mark;
} else if((s &TYPE_MASK)==T_DOCUMENT) {
//move the pointer to next structure.
//mark the next start element
XMLStreamBufferMark mark = new XMLStreamBufferMark(new HashMap<String, String>(_namespaceAIIsEnd), this);
next();
return mark;
}
if(next()==END_ELEMENT)
return null;
}
}
return null;
}
switch(_completionState) {
case COMPLETED:
throw new XMLStreamException("Invalid State");
case PENDING_END_DOCUMENT:
_namespaceAIIsEnd = 0;
return _eventType = END_DOCUMENT;
}
// Pop the stack of elements
// This is a post-processing operation
// The stack of the element should be poppoed after
// the END_ELEMENT event is returned so that the correct element name
// and namespace scope is returned
switch(_eventType) {
case END_ELEMENT:
if (_depth > 1) {
_depth--;
// _depth index is always set to the next free stack entry
// to push
} else if (_depth == 1) {
_depth--;
}
}
_characters = null;
while(true) {// loop only if we read STATE_DOCUMENT
int eiiState = readEiiState();
switch(eiiState) {
case STATE_DOCUMENT:
// we'll always produce a full document, and we've already report START_DOCUMENT event.
// so simply skil this
continue;
case STATE_ELEMENT_U_LN_QN: {
return _eventType = START_ELEMENT;
}
case STATE_ELEMENT_P_U_LN:
return _eventType = START_ELEMENT;
case STATE_ELEMENT_U_LN:
return _eventType = START_ELEMENT;
case STATE_ELEMENT_LN:
return _eventType = START_ELEMENT;
_textLen = readStructure();
return _eventType = CHARACTERS;
_textLen = readStructure16();
return _eventType = CHARACTERS;
_textOffset = 0;
return _eventType = CHARACTERS;
case STATE_TEXT_AS_STRING:
return _eventType = CHARACTERS;
case STATE_TEXT_AS_OBJECT:
return _eventType = CHARACTERS;
_textLen = readStructure();
return _eventType = COMMENT;
_textLen = readStructure16();
return _eventType = COMMENT;
_textOffset = 0;
return _eventType = COMMENT;
case STATE_COMMENT_AS_STRING:
return _eventType = COMMENT;
return _eventType = PROCESSING_INSTRUCTION;
case STATE_END:
if (_depth > 1) {
// normal case
return _eventType = END_ELEMENT;
} else if (_depth == 1) {
// this is the last end element for the current tree.
if (_fragmentMode) {
}
return _eventType = END_ELEMENT;
} else {
// this only happens when we are processing a full document
// and we hit the "end of document" marker
_namespaceAIIsEnd = 0;
return _eventType = END_DOCUMENT;
}
default:
}
// this should be unreachable
}
}
public final void require(int type, String namespaceURI, String localName) throws XMLStreamException {
if( type != _eventType) {
throw new XMLStreamException("");
}
throw new XMLStreamException("");
}
throw new XMLStreamException("");
}
}
// TODO getElementText* methods more efficiently
return getElementText().trim();
}
if(_eventType != START_ELEMENT) {
throw new XMLStreamException("");
}
next();
return getElementText(true);
}
if (!startElementRead) {
throw new XMLStreamException("");
}
int eventType = getEventType();
while(eventType != END_ELEMENT ) {
if(eventType == CHARACTERS
|| eventType == ENTITY_REFERENCE) {
} else if(eventType == PROCESSING_INSTRUCTION
// skipping
} else if(eventType == END_DOCUMENT) {
throw new XMLStreamException("");
} else if(eventType == START_ELEMENT) {
throw new XMLStreamException("");
} else {
throw new XMLStreamException("");
}
}
}
next();
return nextTag(true);
}
int eventType = getEventType();
if (!currentTagRead) {
}
}
throw new XMLStreamException("");
}
return eventType;
}
public final boolean hasNext() {
return (_eventType != END_DOCUMENT);
}
}
public final boolean isStartElement() {
return (_eventType == START_ELEMENT);
}
public final boolean isEndElement() {
return (_eventType == END_ELEMENT);
}
public final boolean isCharacters() {
return (_eventType == CHARACTERS);
}
public final boolean isWhiteSpace() {
char [] ch = this.getTextCharacters();
int start = this.getTextStart();
int length = this.getTextLength();
final char c = ch[i];
if (!(c == 0x20 || c == 0x9 || c == 0xD || c == 0xA))
return false;
}
return true;
}
return false;
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
if (namespaceURI == null) {
// Set to the empty string to be compatible with the
// org.xml.sax.Attributes interface
namespaceURI = "";
}
}
public final int getAttributeCount() {
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
return _attributeCache.getLength();
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
if (_eventType != START_ELEMENT) {
throw new IllegalStateException("");
}
}
return false;
}
public final int getNamespaceCount() {
}
throw new IllegalStateException("");
}
}
throw new IllegalStateException("");
}
}
throw new IllegalStateException("");
}
}
return _nsCtx;
}
public final int getEventType() {
return _eventType;
}
if (_characters != null) {
_charSequence = s;
return s;
} else if (_charSequence != null) {
return _charSequence.toString();
} else {
throw new IllegalStateException();
}
}
public final char[] getTextCharacters() {
if (_characters != null) {
return _characters;
} else if (_charSequence != null) {
// TODO try to avoid creation of a temporary String for some
// CharSequence implementations
_textOffset = 0;
return _characters;
} else {
throw new IllegalStateException();
}
}
public final int getTextStart() {
if (_characters != null) {
return _textOffset;
} else if (_charSequence != null) {
return 0;
} else {
throw new IllegalStateException();
}
}
public final int getTextLength() {
if (_characters != null) {
return _textLen;
} else if (_charSequence != null) {
return _charSequence.length();
} else {
throw new IllegalStateException();
}
}
if (_characters != null) {
} else if (_charSequence != null) {
_textOffset = 0;
} else {
throw new IllegalStateException("");
}
try {
return len;
} catch (IndexOutOfBoundsException e) {
throw new XMLStreamException(e);
}
}
private final int _offset;
private final int _length;
}
public int length() {
return _length;
}
} else {
throw new IndexOutOfBoundsException();
}
}
throw new IndexOutOfBoundsException();
}
}
}
}
if (_characters != null) {
} else if (_charSequence != null) {
return _charSequence;
} else {
throw new IllegalStateException();
}
}
return "UTF-8";
}
public final boolean hasText() {
}
return new DummyLocation();
}
public final boolean hasName() {
}
}
}
}
}
return "1.0";
}
public final boolean isStandalone() {
return false;
}
public final boolean standaloneSet() {
return false;
}
return "UTF-8";
}
if (_eventType == PROCESSING_INSTRUCTION) {
return _piTarget;
}
throw new IllegalStateException("");
}
if (_eventType == PROCESSING_INSTRUCTION) {
return _piData;
}
throw new IllegalStateException("");
}
int item = peekStructure();
// Skip the namespace declarations on the element
// they will have been added already
}
}
}
private void resizeNamespaceAttributes() {
}
do {
}
switch(getNIIState(item)){
// Undeclaration of default namespace
break;
// Undeclaration of namespace
break;
// Declaration with prefix
break;
// Default declaration
break;
}
item = peekStructure();
return item;
}
do {
switch(getAIIState(item)){
case STATE_ATTRIBUTE_U_LN_QN: {
_attributeCache.addAttributeWithPrefix(prefix, uri, localName, readStructureString(), readContentString());
break;
}
case STATE_ATTRIBUTE_P_U_LN:
_attributeCache.addAttributeWithPrefix(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString());
break;
case STATE_ATTRIBUTE_U_LN:
// _attributeCache follows SAX convention
_attributeCache.addAttributeWithPrefix("", readStructureString(), readStructureString(), readStructureString(), readContentString());
break;
case STATE_ATTRIBUTE_LN: {
_attributeCache.addAttributeWithPrefix("", "", readStructureString(), readStructureString(), readContentString());
break;
}
default :
assert false : "Internal XSB Error: wrong attribute state, Item="+item;
}
item = peekStructure();
}
private void pushElementStack() {
// resize stack
_stack[i] = new ElementStackEntry();
}
}
}
// _depth is checked outside this method
// Move back the position of the namespace index
}
private final class ElementStackEntry {
/**
* Prefix.
* Just like everywhere else in StAX, this can be null but can't be empty.
*/
/**
* Namespace URI.
* Just like everywhere else in StAX, this can be null but can't be empty.
*/
// Start and end of namespace declarations
// in namespace declaration arrays
int namespaceAIIsStart;
int namespaceAIIsEnd;
this.namespaceAIIsStart = this.namespaceAIIsEnd = StreamReaderBufferProcessor.this._namespaceAIIsEnd;
}
}
return qname;
}
return (s == null) ? "" : s;
}
}
@SuppressWarnings({"StringEquality"})
throw new IllegalArgumentException("Prefix cannot be null");
}
/*
* If the buffer was created using string interning
* intern the prefix and check for reference equality
* rather than using String.equals();
*/
if (_stringInterningFeature) {
// Find the most recently declared prefix
if (prefix == _namespaceAIIsPrefix[i]) {
return _namespaceAIIsNamespaceName[i];
}
}
} else {
// Find the most recently declared prefix
return _namespaceAIIsNamespaceName[i];
}
}
}
// Check for XML-based prefixes
return XMLConstants.XML_NS_URI;
return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
}
return null;
}
if (i.hasNext()) {
} else {
return null;
}
}
if (namespaceURI == null){
throw new IllegalArgumentException("NamespaceURI cannot be null");
}
}
return new Iterator() {
private int i = _namespaceAIIsEnd - 1;
private boolean requireFindNext = true;
private String p;
while(i >= 0) {
// Find the most recently declared namespace
// Find the most recently declared prefix of the namespace
// and check if the prefix is in scope with that namespace
_namespaceAIIsNamespaceName[i])) {
return p = _namespaceAIIsPrefix[i];
}
}
i--;
}
return p = null;
}
public boolean hasNext() {
if (requireFindNext) {
findNext();
requireFindNext = false;
}
return (p != null);
}
if (requireFindNext) {
findNext();
}
requireFindNext = true;
if (p == null) {
throw new NoSuchElementException();
}
return p;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
return _prefix;
}
return _namespaceURI;
}
}
private boolean requireFindNext = true;
while(current >= 0) {
// Find if the current prefix occurs more recently
// If so then it is not in scope
int i = end;
for (;i > current; i--) {
break;
}
}
if (i == current--) {
// The current prefix is in-scope
}
}
}
public boolean hasNext() {
if (requireFindNext) {
findNext();
requireFindNext = false;
}
}
if (requireFindNext) {
findNext();
}
requireFindNext = true;
throw new NoSuchElementException();
}
return namespace;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
public int getLineNumber() {
return -1;
}
public int getColumnNumber() {
return -1;
}
public int getCharacterOffset() {
return -1;
}
return null;
}
return _buffer.getSystemId();
}
}
// s must not be null, so no need to check for that. that would be bug.
else return s;
}
}