src/share/jaxws_classes/com/sun/xml/internal/stream/buffer/stax/StreamReaderBufferProcessor.java

Fri, 23 Aug 2013 09:57:21 +0100

author
mkos
date
Fri, 23 Aug 2013 09:57:21 +0100
changeset 397
b99d7e355d4b
parent 368
0989ad8c0860
child 637
9c07ef4934dd
permissions
-rw-r--r--

8022885: Update JAX-WS RI integration to 2.2.9-b14140
8013016: Rebase 8009009 against the latest jdk8/jaxws
Reviewed-by: alanb, chegar

ohair@286 1 /*
mkos@397 2 * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.xml.internal.stream.buffer.stax;
ohair@286 27
ohair@286 28 import com.sun.xml.internal.stream.buffer.AbstractProcessor;
ohair@286 29 import com.sun.xml.internal.stream.buffer.AttributesHolder;
ohair@286 30 import com.sun.xml.internal.stream.buffer.XMLStreamBuffer;
ohair@286 31 import com.sun.xml.internal.stream.buffer.XMLStreamBufferMark;
ohair@286 32 import com.sun.xml.internal.org.jvnet.staxex.NamespaceContextEx;
ohair@286 33 import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx;
ohair@286 34
ohair@286 35 import javax.xml.XMLConstants;
ohair@286 36 import javax.xml.namespace.QName;
ohair@286 37 import javax.xml.stream.Location;
ohair@286 38 import javax.xml.stream.XMLStreamException;
ohair@286 39 import javax.xml.stream.XMLStreamReader;
ohair@286 40 import java.util.*;
ohair@286 41
ohair@286 42 /**
ohair@286 43 * A processor of a {@link XMLStreamBuffer} that reads the XML infoset as
ohair@286 44 * {@link XMLStreamReader}.
ohair@286 45 *
ohair@286 46 * <p>
ohair@286 47 * Because of {@link XMLStreamReader} design, this processor always produce
ohair@286 48 * a full document infoset, even if the buffer just contains a fragment.
ohair@286 49 *
ohair@286 50 * <p>
ohair@286 51 * When {@link XMLStreamBuffer} contains a multiple tree (AKA "forest"),
ohair@286 52 * {@link XMLStreamReader} will behave as if there are multiple root elements
ohair@286 53 * (so you'll see {@link #START_ELEMENT} event where you'd normally expect
ohair@286 54 * {@link #END_DOCUMENT}.)
ohair@286 55 *
ohair@286 56 * @author Paul.Sandoz@Sun.Com
ohair@286 57 * @author K.Venugopal@sun.com
ohair@286 58 */
ohair@286 59 public class StreamReaderBufferProcessor extends AbstractProcessor implements XMLStreamReaderEx {
ohair@286 60 private static final int CACHE_SIZE = 16;
ohair@286 61
ohair@286 62 // Stack to hold element and namespace declaration information
ohair@286 63 protected ElementStackEntry[] _stack = new ElementStackEntry[CACHE_SIZE];
ohair@286 64 /** The top-most active entry of the {@link #_stack}. */
ohair@286 65 protected ElementStackEntry _stackTop;
ohair@286 66 /** The element depth that we are in. Used to determine when we are done with a tree. */
ohair@286 67 protected int _depth;
ohair@286 68
ohair@286 69 // Arrays to hold all namespace declarations
ohair@286 70 /**
ohair@286 71 * Namespace prefixes. Can be empty but not null.
ohair@286 72 */
ohair@286 73 protected String[] _namespaceAIIsPrefix = new String[CACHE_SIZE];
ohair@286 74 protected String[] _namespaceAIIsNamespaceName = new String[CACHE_SIZE];
ohair@286 75 protected int _namespaceAIIsEnd;
ohair@286 76
ohair@286 77 // Internal namespace context implementation
ohair@286 78 protected InternalNamespaceContext _nsCtx = new InternalNamespaceContext();
ohair@286 79
ohair@286 80 // The current event type
ohair@286 81 protected int _eventType;
ohair@286 82
ohair@286 83 /**
ohair@286 84 * Holder of the attributes.
ohair@286 85 *
ohair@286 86 * Be careful that this follows the SAX convention of using "" instead of null.
ohair@286 87 */
ohair@286 88 protected AttributesHolder _attributeCache;
ohair@286 89
ohair@286 90 // Characters as a CharSequence
ohair@286 91 protected CharSequence _charSequence;
ohair@286 92
ohair@286 93 // Characters as a char array with offset and length
ohair@286 94 protected char[] _characters;
ohair@286 95 protected int _textOffset;
ohair@286 96 protected int _textLen;
ohair@286 97
ohair@286 98 protected String _piTarget;
ohair@286 99 protected String _piData;
ohair@286 100
ohair@286 101 //
ohair@286 102 // Represents the parser state wrt the end of parsing.
ohair@286 103 //
ohair@286 104 /**
ohair@286 105 * The parser is in the middle of parsing a document,
ohair@286 106 * with no end in sight.
ohair@286 107 */
ohair@286 108 private static final int PARSING = 1;
ohair@286 109 /**
ohair@286 110 * The parser has already reported the {@link #END_ELEMENT},
ohair@286 111 * and we are parsing a fragment. We'll report {@link #END_DOCUMENT}
ohair@286 112 * next and be done.
ohair@286 113 */
ohair@286 114 private static final int PENDING_END_DOCUMENT = 2;
ohair@286 115 /**
ohair@286 116 * The parser has reported the {@link #END_DOCUMENT} event,
ohair@286 117 * so we are really done parsing.
ohair@286 118 */
ohair@286 119 private static final int COMPLETED = 3;
ohair@286 120
ohair@286 121 /**
ohair@286 122 * True if processing is complete.
ohair@286 123 */
ohair@286 124 private int _completionState;
ohair@286 125
ohair@286 126 public StreamReaderBufferProcessor() {
ohair@286 127 for (int i=0; i < _stack.length; i++){
ohair@286 128 _stack[i] = new ElementStackEntry();
ohair@286 129 }
ohair@286 130
ohair@286 131 _attributeCache = new AttributesHolder();
ohair@286 132 }
ohair@286 133
ohair@286 134 public StreamReaderBufferProcessor(XMLStreamBuffer buffer) throws XMLStreamException {
ohair@286 135 this();
ohair@286 136 setXMLStreamBuffer(buffer);
ohair@286 137 }
ohair@286 138
ohair@286 139 public void setXMLStreamBuffer(XMLStreamBuffer buffer) throws XMLStreamException {
ohair@286 140 setBuffer(buffer,buffer.isFragment());
ohair@286 141
ohair@286 142 _completionState = PARSING;
ohair@286 143 _namespaceAIIsEnd = 0;
ohair@286 144 _characters = null;
ohair@286 145 _charSequence = null;
ohair@286 146 _eventType = START_DOCUMENT;
ohair@286 147 }
ohair@286 148
ohair@286 149 /**
ohair@286 150 * Does {@link #nextTag()} and if the parser moved to a new start tag,
ohair@286 151 * returns a {@link XMLStreamBufferMark} that captures the infoset starting
ohair@286 152 * from the newly discovered element.
ohair@286 153 *
ohair@286 154 * <p>
ohair@286 155 * (Ideally we should have a method that works against the current position,
ohair@286 156 * but the way the data structure is read makes this somewhat difficult.)
ohair@286 157 *
ohair@286 158 * This creates a new {@link XMLStreamBufferMark} that shares the underlying
ohair@286 159 * data storage, thus it's fairly efficient.
ohair@286 160 */
ohair@286 161 public XMLStreamBuffer nextTagAndMark() throws XMLStreamException {
ohair@286 162 while (true) {
ohair@286 163 int s = peekStructure();
ohair@286 164 if((s &TYPE_MASK)==T_ELEMENT) {
ohair@286 165 // next is start element.
ohair@286 166 Map<String,String> inscope = new HashMap<String, String>(_namespaceAIIsEnd);
ohair@286 167
ohair@286 168 for (int i=0 ; i<_namespaceAIIsEnd; i++)
ohair@286 169 inscope.put(_namespaceAIIsPrefix[i],_namespaceAIIsNamespaceName[i]);
ohair@286 170
ohair@286 171 XMLStreamBufferMark mark = new XMLStreamBufferMark(inscope, this);
ohair@286 172 next();
ohair@286 173 return mark;
ohair@286 174 } else if((s &TYPE_MASK)==T_DOCUMENT) {
ohair@286 175 //move the pointer to next structure.
ohair@286 176 readStructure();
ohair@286 177 //mark the next start element
ohair@286 178 XMLStreamBufferMark mark = new XMLStreamBufferMark(new HashMap<String, String>(_namespaceAIIsEnd), this);
ohair@286 179 next();
ohair@286 180 return mark;
ohair@286 181 }
ohair@286 182
ohair@286 183 if(next()==END_ELEMENT)
ohair@286 184 return null;
ohair@286 185 }
ohair@286 186 }
ohair@286 187
ohair@286 188 public Object getProperty(String name) {
ohair@286 189 return null;
ohair@286 190 }
ohair@286 191
ohair@286 192 public int next() throws XMLStreamException {
ohair@286 193 switch(_completionState) {
ohair@286 194 case COMPLETED:
ohair@286 195 throw new XMLStreamException("Invalid State");
ohair@286 196 case PENDING_END_DOCUMENT:
ohair@286 197 _namespaceAIIsEnd = 0;
ohair@286 198 _completionState = COMPLETED;
ohair@286 199 return _eventType = END_DOCUMENT;
ohair@286 200 }
ohair@286 201
ohair@286 202 // Pop the stack of elements
ohair@286 203 // This is a post-processing operation
ohair@286 204 // The stack of the element should be poppoed after
ohair@286 205 // the END_ELEMENT event is returned so that the correct element name
ohair@286 206 // and namespace scope is returned
ohair@286 207 switch(_eventType) {
ohair@286 208 case END_ELEMENT:
ohair@286 209 if (_depth > 1) {
ohair@286 210 _depth--;
ohair@286 211 // _depth index is always set to the next free stack entry
ohair@286 212 // to push
ohair@286 213 popElementStack(_depth);
ohair@286 214 } else if (_depth == 1) {
ohair@286 215 _depth--;
ohair@286 216 }
ohair@286 217 }
ohair@286 218
ohair@286 219 _characters = null;
ohair@286 220 _charSequence = null;
ohair@286 221 while(true) {// loop only if we read STATE_DOCUMENT
ohair@286 222 int eiiState = readEiiState();
ohair@286 223 switch(eiiState) {
ohair@286 224 case STATE_DOCUMENT:
ohair@286 225 // we'll always produce a full document, and we've already report START_DOCUMENT event.
ohair@286 226 // so simply skil this
ohair@286 227 continue;
ohair@286 228 case STATE_ELEMENT_U_LN_QN: {
ohair@286 229 final String uri = readStructureString();
ohair@286 230 final String localName = readStructureString();
ohair@286 231 final String prefix = getPrefixFromQName(readStructureString());
ohair@286 232
ohair@286 233 processElement(prefix, uri, localName, isInscope(_depth));
ohair@286 234 return _eventType = START_ELEMENT;
ohair@286 235 }
ohair@286 236 case STATE_ELEMENT_P_U_LN:
ohair@286 237 processElement(readStructureString(), readStructureString(), readStructureString(),isInscope(_depth));
ohair@286 238 return _eventType = START_ELEMENT;
ohair@286 239 case STATE_ELEMENT_U_LN:
ohair@286 240 processElement(null, readStructureString(), readStructureString(),isInscope(_depth));
ohair@286 241 return _eventType = START_ELEMENT;
ohair@286 242 case STATE_ELEMENT_LN:
ohair@286 243 processElement(null, null, readStructureString(),isInscope(_depth));
ohair@286 244 return _eventType = START_ELEMENT;
ohair@286 245 case STATE_TEXT_AS_CHAR_ARRAY_SMALL:
ohair@286 246 _textLen = readStructure();
ohair@286 247 _textOffset = readContentCharactersBuffer(_textLen);
ohair@286 248 _characters = _contentCharactersBuffer;
ohair@286 249
ohair@286 250 return _eventType = CHARACTERS;
ohair@286 251 case STATE_TEXT_AS_CHAR_ARRAY_MEDIUM:
ohair@286 252 _textLen = readStructure16();
ohair@286 253 _textOffset = readContentCharactersBuffer(_textLen);
ohair@286 254 _characters = _contentCharactersBuffer;
ohair@286 255
ohair@286 256 return _eventType = CHARACTERS;
ohair@286 257 case STATE_TEXT_AS_CHAR_ARRAY_COPY:
ohair@286 258 _characters = readContentCharactersCopy();
ohair@286 259 _textLen = _characters.length;
ohair@286 260 _textOffset = 0;
ohair@286 261
ohair@286 262 return _eventType = CHARACTERS;
ohair@286 263 case STATE_TEXT_AS_STRING:
ohair@286 264 _eventType = CHARACTERS;
ohair@286 265 _charSequence = readContentString();
ohair@286 266
ohair@286 267 return _eventType = CHARACTERS;
ohair@286 268 case STATE_TEXT_AS_OBJECT:
ohair@286 269 _eventType = CHARACTERS;
ohair@286 270 _charSequence = (CharSequence)readContentObject();
ohair@286 271
ohair@286 272 return _eventType = CHARACTERS;
ohair@286 273 case STATE_COMMENT_AS_CHAR_ARRAY_SMALL:
ohair@286 274 _textLen = readStructure();
ohair@286 275 _textOffset = readContentCharactersBuffer(_textLen);
ohair@286 276 _characters = _contentCharactersBuffer;
ohair@286 277
ohair@286 278 return _eventType = COMMENT;
ohair@286 279 case STATE_COMMENT_AS_CHAR_ARRAY_MEDIUM:
ohair@286 280 _textLen = readStructure16();
ohair@286 281 _textOffset = readContentCharactersBuffer(_textLen);
ohair@286 282 _characters = _contentCharactersBuffer;
ohair@286 283
ohair@286 284 return _eventType = COMMENT;
ohair@286 285 case STATE_COMMENT_AS_CHAR_ARRAY_COPY:
ohair@286 286 _characters = readContentCharactersCopy();
ohair@286 287 _textLen = _characters.length;
ohair@286 288 _textOffset = 0;
ohair@286 289
ohair@286 290 return _eventType = COMMENT;
ohair@286 291 case STATE_COMMENT_AS_STRING:
ohair@286 292 _charSequence = readContentString();
ohair@286 293
ohair@286 294 return _eventType = COMMENT;
ohair@286 295 case STATE_PROCESSING_INSTRUCTION:
ohair@286 296 _piTarget = readStructureString();
ohair@286 297 _piData = readStructureString();
ohair@286 298
ohair@286 299 return _eventType = PROCESSING_INSTRUCTION;
ohair@286 300 case STATE_END:
ohair@286 301 if (_depth > 1) {
ohair@286 302 // normal case
ohair@286 303 return _eventType = END_ELEMENT;
ohair@286 304 } else if (_depth == 1) {
ohair@286 305 // this is the last end element for the current tree.
ohair@286 306 if (_fragmentMode) {
ohair@286 307 if(--_treeCount==0) // is this the last tree in the forest?
ohair@286 308 _completionState = PENDING_END_DOCUMENT;
ohair@286 309 }
ohair@286 310 return _eventType = END_ELEMENT;
ohair@286 311 } else {
ohair@286 312 // this only happens when we are processing a full document
ohair@286 313 // and we hit the "end of document" marker
ohair@286 314 _namespaceAIIsEnd = 0;
ohair@286 315 _completionState = COMPLETED;
ohair@286 316 return _eventType = END_DOCUMENT;
ohair@286 317 }
ohair@286 318 default:
ohair@286 319 throw new XMLStreamException("Internal XSB error: Invalid State="+eiiState);
ohair@286 320 }
ohair@286 321 // this should be unreachable
ohair@286 322 }
ohair@286 323 }
ohair@286 324
ohair@286 325 public final void require(int type, String namespaceURI, String localName) throws XMLStreamException {
ohair@286 326 if( type != _eventType) {
ohair@286 327 throw new XMLStreamException("");
ohair@286 328 }
ohair@286 329 if( namespaceURI != null && !namespaceURI.equals(getNamespaceURI())) {
ohair@286 330 throw new XMLStreamException("");
ohair@286 331 }
ohair@286 332 if(localName != null && !localName.equals(getLocalName())) {
ohair@286 333 throw new XMLStreamException("");
ohair@286 334 }
ohair@286 335 }
ohair@286 336
ohair@286 337 public final String getElementTextTrim() throws XMLStreamException {
ohair@286 338 // TODO getElementText* methods more efficiently
ohair@286 339 return getElementText().trim();
ohair@286 340 }
ohair@286 341
ohair@286 342 public final String getElementText() throws XMLStreamException {
ohair@286 343 if(_eventType != START_ELEMENT) {
ohair@286 344 throw new XMLStreamException("");
ohair@286 345 }
ohair@286 346
ohair@286 347 next();
ohair@286 348 return getElementText(true);
ohair@286 349 }
ohair@286 350
ohair@286 351 public final String getElementText(boolean startElementRead) throws XMLStreamException {
ohair@286 352 if (!startElementRead) {
ohair@286 353 throw new XMLStreamException("");
ohair@286 354 }
ohair@286 355
ohair@286 356 int eventType = getEventType();
alanb@368 357 StringBuilder content = new StringBuilder();
ohair@286 358 while(eventType != END_ELEMENT ) {
ohair@286 359 if(eventType == CHARACTERS
ohair@286 360 || eventType == CDATA
ohair@286 361 || eventType == SPACE
ohair@286 362 || eventType == ENTITY_REFERENCE) {
ohair@286 363 content.append(getText());
ohair@286 364 } else if(eventType == PROCESSING_INSTRUCTION
ohair@286 365 || eventType == COMMENT) {
ohair@286 366 // skipping
ohair@286 367 } else if(eventType == END_DOCUMENT) {
ohair@286 368 throw new XMLStreamException("");
ohair@286 369 } else if(eventType == START_ELEMENT) {
ohair@286 370 throw new XMLStreamException("");
ohair@286 371 } else {
ohair@286 372 throw new XMLStreamException("");
ohair@286 373 }
ohair@286 374 eventType = next();
ohair@286 375 }
ohair@286 376 return content.toString();
ohair@286 377 }
ohair@286 378
ohair@286 379 public final int nextTag() throws XMLStreamException {
ohair@286 380 next();
ohair@286 381 return nextTag(true);
ohair@286 382 }
ohair@286 383
ohair@286 384 public final int nextTag(boolean currentTagRead) throws XMLStreamException {
ohair@286 385 int eventType = getEventType();
ohair@286 386 if (!currentTagRead) {
ohair@286 387 eventType = next();
ohair@286 388 }
ohair@286 389 while((eventType == CHARACTERS && isWhiteSpace()) // skip whitespace
ohair@286 390 || (eventType == CDATA && isWhiteSpace())
ohair@286 391 || eventType == SPACE
ohair@286 392 || eventType == PROCESSING_INSTRUCTION
ohair@286 393 || eventType == COMMENT) {
ohair@286 394 eventType = next();
ohair@286 395 }
ohair@286 396 if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
ohair@286 397 throw new XMLStreamException("");
ohair@286 398 }
ohair@286 399 return eventType;
ohair@286 400 }
ohair@286 401
ohair@286 402 public final boolean hasNext() {
ohair@286 403 return (_eventType != END_DOCUMENT);
ohair@286 404 }
ohair@286 405
ohair@286 406 public void close() throws XMLStreamException {
ohair@286 407 }
ohair@286 408
ohair@286 409 public final boolean isStartElement() {
ohair@286 410 return (_eventType == START_ELEMENT);
ohair@286 411 }
ohair@286 412
ohair@286 413 public final boolean isEndElement() {
ohair@286 414 return (_eventType == END_ELEMENT);
ohair@286 415 }
ohair@286 416
ohair@286 417 public final boolean isCharacters() {
ohair@286 418 return (_eventType == CHARACTERS);
ohair@286 419 }
ohair@286 420
ohair@286 421 public final boolean isWhiteSpace() {
ohair@286 422 if(isCharacters() || (_eventType == CDATA)){
ohair@286 423 char [] ch = this.getTextCharacters();
ohair@286 424 int start = this.getTextStart();
ohair@286 425 int length = this.getTextLength();
ohair@286 426 for (int i = start; i < length; i++){
ohair@286 427 final char c = ch[i];
ohair@286 428 if (!(c == 0x20 || c == 0x9 || c == 0xD || c == 0xA))
ohair@286 429 return false;
ohair@286 430 }
ohair@286 431 return true;
ohair@286 432 }
ohair@286 433 return false;
ohair@286 434 }
ohair@286 435
ohair@286 436 public final String getAttributeValue(String namespaceURI, String localName) {
ohair@286 437 if (_eventType != START_ELEMENT) {
ohair@286 438 throw new IllegalStateException("");
ohair@286 439 }
ohair@286 440
ohair@286 441 if (namespaceURI == null) {
ohair@286 442 // Set to the empty string to be compatible with the
ohair@286 443 // org.xml.sax.Attributes interface
ohair@286 444 namespaceURI = "";
ohair@286 445 }
ohair@286 446
ohair@286 447 return _attributeCache.getValue(namespaceURI, localName);
ohair@286 448 }
ohair@286 449
ohair@286 450 public final int getAttributeCount() {
ohair@286 451 if (_eventType != START_ELEMENT) {
ohair@286 452 throw new IllegalStateException("");
ohair@286 453 }
ohair@286 454
ohair@286 455 return _attributeCache.getLength();
ohair@286 456 }
ohair@286 457
ohair@286 458 public final javax.xml.namespace.QName getAttributeName(int index) {
ohair@286 459 if (_eventType != START_ELEMENT) {
ohair@286 460 throw new IllegalStateException("");
ohair@286 461 }
ohair@286 462
ohair@286 463 final String prefix = _attributeCache.getPrefix(index);
ohair@286 464 final String localName = _attributeCache.getLocalName(index);
ohair@286 465 final String uri = _attributeCache.getURI(index);
ohair@286 466 return new QName(uri,localName,prefix);
ohair@286 467 }
ohair@286 468
ohair@286 469
ohair@286 470 public final String getAttributeNamespace(int index) {
ohair@286 471 if (_eventType != START_ELEMENT) {
ohair@286 472 throw new IllegalStateException("");
ohair@286 473 }
ohair@286 474 return fixEmptyString(_attributeCache.getURI(index));
ohair@286 475 }
ohair@286 476
ohair@286 477 public final String getAttributeLocalName(int index) {
ohair@286 478 if (_eventType != START_ELEMENT) {
ohair@286 479 throw new IllegalStateException("");
ohair@286 480 }
ohair@286 481 return _attributeCache.getLocalName(index);
ohair@286 482 }
ohair@286 483
ohair@286 484 public final String getAttributePrefix(int index) {
ohair@286 485 if (_eventType != START_ELEMENT) {
ohair@286 486 throw new IllegalStateException("");
ohair@286 487 }
ohair@286 488 return fixEmptyString(_attributeCache.getPrefix(index));
ohair@286 489 }
ohair@286 490
ohair@286 491 public final String getAttributeType(int index) {
ohair@286 492 if (_eventType != START_ELEMENT) {
ohair@286 493 throw new IllegalStateException("");
ohair@286 494 }
ohair@286 495 return _attributeCache.getType(index);
ohair@286 496 }
ohair@286 497
ohair@286 498 public final String getAttributeValue(int index) {
ohair@286 499 if (_eventType != START_ELEMENT) {
ohair@286 500 throw new IllegalStateException("");
ohair@286 501 }
ohair@286 502
ohair@286 503 return _attributeCache.getValue(index);
ohair@286 504 }
ohair@286 505
ohair@286 506 public final boolean isAttributeSpecified(int index) {
ohair@286 507 return false;
ohair@286 508 }
ohair@286 509
ohair@286 510 public final int getNamespaceCount() {
ohair@286 511 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
ohair@286 512 return _stackTop.namespaceAIIsEnd - _stackTop.namespaceAIIsStart;
ohair@286 513 }
ohair@286 514
ohair@286 515 throw new IllegalStateException("");
ohair@286 516 }
ohair@286 517
ohair@286 518 public final String getNamespacePrefix(int index) {
ohair@286 519 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
ohair@286 520 return _namespaceAIIsPrefix[_stackTop.namespaceAIIsStart + index];
ohair@286 521 }
ohair@286 522
ohair@286 523 throw new IllegalStateException("");
ohair@286 524 }
ohair@286 525
ohair@286 526 public final String getNamespaceURI(int index) {
ohair@286 527 if (_eventType == START_ELEMENT || _eventType == END_ELEMENT) {
ohair@286 528 return _namespaceAIIsNamespaceName[_stackTop.namespaceAIIsStart + index];
ohair@286 529 }
ohair@286 530
ohair@286 531 throw new IllegalStateException("");
ohair@286 532 }
ohair@286 533
ohair@286 534 public final String getNamespaceURI(String prefix) {
ohair@286 535 return _nsCtx.getNamespaceURI(prefix);
ohair@286 536 }
ohair@286 537
ohair@286 538 public final NamespaceContextEx getNamespaceContext() {
ohair@286 539 return _nsCtx;
ohair@286 540 }
ohair@286 541
ohair@286 542 public final int getEventType() {
ohair@286 543 return _eventType;
ohair@286 544 }
ohair@286 545
ohair@286 546 public final String getText() {
ohair@286 547 if (_characters != null) {
ohair@286 548 String s = new String(_characters, _textOffset, _textLen);
ohair@286 549 _charSequence = s;
ohair@286 550 return s;
ohair@286 551 } else if (_charSequence != null) {
ohair@286 552 return _charSequence.toString();
ohair@286 553 } else {
ohair@286 554 throw new IllegalStateException();
ohair@286 555 }
ohair@286 556 }
ohair@286 557
ohair@286 558 public final char[] getTextCharacters() {
ohair@286 559 if (_characters != null) {
ohair@286 560 return _characters;
ohair@286 561 } else if (_charSequence != null) {
ohair@286 562 // TODO try to avoid creation of a temporary String for some
ohair@286 563 // CharSequence implementations
ohair@286 564 _characters = _charSequence.toString().toCharArray();
ohair@286 565 _textLen = _characters.length;
ohair@286 566 _textOffset = 0;
ohair@286 567 return _characters;
ohair@286 568 } else {
ohair@286 569 throw new IllegalStateException();
ohair@286 570 }
ohair@286 571 }
ohair@286 572
ohair@286 573 public final int getTextStart() {
ohair@286 574 if (_characters != null) {
ohair@286 575 return _textOffset;
ohair@286 576 } else if (_charSequence != null) {
ohair@286 577 return 0;
ohair@286 578 } else {
ohair@286 579 throw new IllegalStateException();
ohair@286 580 }
ohair@286 581 }
ohair@286 582
ohair@286 583 public final int getTextLength() {
ohair@286 584 if (_characters != null) {
ohair@286 585 return _textLen;
ohair@286 586 } else if (_charSequence != null) {
ohair@286 587 return _charSequence.length();
ohair@286 588 } else {
ohair@286 589 throw new IllegalStateException();
ohair@286 590 }
ohair@286 591 }
ohair@286 592
ohair@286 593 public final int getTextCharacters(int sourceStart, char[] target,
ohair@286 594 int targetStart, int length) throws XMLStreamException {
ohair@286 595 if (_characters != null) {
ohair@286 596 } else if (_charSequence != null) {
ohair@286 597 _characters = _charSequence.toString().toCharArray();
ohair@286 598 _textLen = _characters.length;
ohair@286 599 _textOffset = 0;
ohair@286 600 } else {
ohair@286 601 throw new IllegalStateException("");
ohair@286 602 }
ohair@286 603
ohair@286 604 try {
ohair@286 605 int remaining = _textLen - sourceStart;
ohair@286 606 int len = remaining > length ? length : remaining;
ohair@286 607 sourceStart += _textOffset;
ohair@286 608 System.arraycopy(_characters, sourceStart, target, targetStart, len);
ohair@286 609 return len;
ohair@286 610 } catch (IndexOutOfBoundsException e) {
ohair@286 611 throw new XMLStreamException(e);
ohair@286 612 }
ohair@286 613 }
ohair@286 614
ohair@286 615 private class CharSequenceImpl implements CharSequence {
ohair@286 616 private final int _offset;
ohair@286 617 private final int _length;
ohair@286 618
ohair@286 619 CharSequenceImpl(int offset, int length) {
ohair@286 620 _offset = offset;
ohair@286 621 _length = length;
ohair@286 622 }
ohair@286 623
ohair@286 624 public int length() {
ohair@286 625 return _length;
ohair@286 626 }
ohair@286 627
ohair@286 628 public char charAt(int index) {
ohair@286 629 if (index >= 0 && index < _textLen) {
ohair@286 630 return _characters[_textOffset + index];
ohair@286 631 } else {
ohair@286 632 throw new IndexOutOfBoundsException();
ohair@286 633 }
ohair@286 634 }
ohair@286 635
ohair@286 636 public CharSequence subSequence(int start, int end) {
ohair@286 637 final int length = end - start;
ohair@286 638 if (end < 0 || start < 0 || end > length || start > end) {
ohair@286 639 throw new IndexOutOfBoundsException();
ohair@286 640 }
ohair@286 641
ohair@286 642 return new CharSequenceImpl(_offset + start, length);
ohair@286 643 }
ohair@286 644
alanb@368 645 @Override
ohair@286 646 public String toString() {
ohair@286 647 return new String(_characters, _offset, _length);
ohair@286 648 }
ohair@286 649 }
ohair@286 650
ohair@286 651 public final CharSequence getPCDATA() {
ohair@286 652 if (_characters != null) {
ohair@286 653 return new CharSequenceImpl(_textOffset, _textLen);
ohair@286 654 } else if (_charSequence != null) {
ohair@286 655 return _charSequence;
ohair@286 656 } else {
ohair@286 657 throw new IllegalStateException();
ohair@286 658 }
ohair@286 659 }
ohair@286 660
ohair@286 661 public final String getEncoding() {
ohair@286 662 return "UTF-8";
ohair@286 663 }
ohair@286 664
ohair@286 665 public final boolean hasText() {
ohair@286 666 return (_characters != null || _charSequence != null);
ohair@286 667 }
ohair@286 668
ohair@286 669 public final Location getLocation() {
ohair@286 670 return new DummyLocation();
ohair@286 671 }
ohair@286 672
ohair@286 673 public final boolean hasName() {
ohair@286 674 return (_eventType == START_ELEMENT || _eventType == END_ELEMENT);
ohair@286 675 }
ohair@286 676
ohair@286 677 public final QName getName() {
ohair@286 678 return _stackTop.getQName();
ohair@286 679 }
ohair@286 680
ohair@286 681 public final String getLocalName() {
ohair@286 682 return _stackTop.localName;
ohair@286 683 }
ohair@286 684
ohair@286 685 public final String getNamespaceURI() {
ohair@286 686 return _stackTop.uri;
ohair@286 687 }
ohair@286 688
ohair@286 689 public final String getPrefix() {
ohair@286 690 return _stackTop.prefix;
ohair@286 691
ohair@286 692 }
ohair@286 693
ohair@286 694 public final String getVersion() {
ohair@286 695 return "1.0";
ohair@286 696 }
ohair@286 697
ohair@286 698 public final boolean isStandalone() {
ohair@286 699 return false;
ohair@286 700 }
ohair@286 701
ohair@286 702 public final boolean standaloneSet() {
ohair@286 703 return false;
ohair@286 704 }
ohair@286 705
ohair@286 706 public final String getCharacterEncodingScheme() {
ohair@286 707 return "UTF-8";
ohair@286 708 }
ohair@286 709
ohair@286 710 public final String getPITarget() {
ohair@286 711 if (_eventType == PROCESSING_INSTRUCTION) {
ohair@286 712 return _piTarget;
ohair@286 713 }
ohair@286 714 throw new IllegalStateException("");
ohair@286 715 }
ohair@286 716
ohair@286 717 public final String getPIData() {
ohair@286 718 if (_eventType == PROCESSING_INSTRUCTION) {
ohair@286 719 return _piData;
ohair@286 720 }
ohair@286 721 throw new IllegalStateException("");
ohair@286 722 }
ohair@286 723
ohair@286 724 protected void processElement(String prefix, String uri, String localName, boolean inscope) {
ohair@286 725 pushElementStack();
ohair@286 726 _stackTop.set(prefix, uri, localName);
ohair@286 727
ohair@286 728 _attributeCache.clear();
ohair@286 729
ohair@286 730 int item = peekStructure();
ohair@286 731 if ((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE || inscope) {
ohair@286 732 // Skip the namespace declarations on the element
ohair@286 733 // they will have been added already
ohair@286 734 item = processNamespaceAttributes(item, inscope);
ohair@286 735 }
ohair@286 736 if ((item & TYPE_MASK) == T_ATTRIBUTE) {
ohair@286 737 processAttributes(item);
ohair@286 738 }
ohair@286 739 }
ohair@286 740
ohair@286 741 private boolean isInscope(int depth) {
ohair@286 742 return _buffer.getInscopeNamespaces().size() > 0 && depth ==0;
ohair@286 743 }
ohair@286 744
ohair@286 745 private void resizeNamespaceAttributes() {
ohair@286 746 final String[] namespaceAIIsPrefix = new String[_namespaceAIIsEnd * 2];
ohair@286 747 System.arraycopy(_namespaceAIIsPrefix, 0, namespaceAIIsPrefix, 0, _namespaceAIIsEnd);
ohair@286 748 _namespaceAIIsPrefix = namespaceAIIsPrefix;
ohair@286 749
ohair@286 750 final String[] namespaceAIIsNamespaceName = new String[_namespaceAIIsEnd * 2];
ohair@286 751 System.arraycopy(_namespaceAIIsNamespaceName, 0, namespaceAIIsNamespaceName, 0, _namespaceAIIsEnd);
ohair@286 752 _namespaceAIIsNamespaceName = namespaceAIIsNamespaceName;
ohair@286 753 }
ohair@286 754
ohair@286 755 private int processNamespaceAttributes(int item, boolean inscope){
ohair@286 756 _stackTop.namespaceAIIsStart = _namespaceAIIsEnd;
ohair@286 757 Set<String> prefixSet = inscope ? new HashSet<String>() : Collections.<String>emptySet();
ohair@286 758
ohair@286 759 while((item & TYPE_MASK) == T_NAMESPACE_ATTRIBUTE) {
ohair@286 760 if (_namespaceAIIsEnd == _namespaceAIIsPrefix.length) {
ohair@286 761 resizeNamespaceAttributes();
ohair@286 762 }
ohair@286 763
ohair@286 764 switch(getNIIState(item)){
ohair@286 765 case STATE_NAMESPACE_ATTRIBUTE:
ohair@286 766 // Undeclaration of default namespace
ohair@286 767 _namespaceAIIsPrefix[_namespaceAIIsEnd] =
ohair@286 768 _namespaceAIIsNamespaceName[_namespaceAIIsEnd++] = "";
ohair@286 769 if (inscope) {
ohair@286 770 prefixSet.add("");
ohair@286 771 }
ohair@286 772 break;
ohair@286 773 case STATE_NAMESPACE_ATTRIBUTE_P:
ohair@286 774 // Undeclaration of namespace
ohair@286 775 _namespaceAIIsPrefix[_namespaceAIIsEnd] = readStructureString();
ohair@286 776 if (inscope) {
ohair@286 777 prefixSet.add(_namespaceAIIsPrefix[_namespaceAIIsEnd]);
ohair@286 778 }
ohair@286 779 _namespaceAIIsNamespaceName[_namespaceAIIsEnd++] = "";
ohair@286 780 break;
ohair@286 781 case STATE_NAMESPACE_ATTRIBUTE_P_U:
ohair@286 782 // Declaration with prefix
ohair@286 783 _namespaceAIIsPrefix[_namespaceAIIsEnd] = readStructureString();
ohair@286 784 if (inscope) {
ohair@286 785 prefixSet.add(_namespaceAIIsPrefix[_namespaceAIIsEnd]);
ohair@286 786 }
ohair@286 787 _namespaceAIIsNamespaceName[_namespaceAIIsEnd++] = readStructureString();
ohair@286 788 break;
ohair@286 789 case STATE_NAMESPACE_ATTRIBUTE_U:
ohair@286 790 // Default declaration
ohair@286 791 _namespaceAIIsPrefix[_namespaceAIIsEnd] = "";
ohair@286 792 if (inscope) {
ohair@286 793 prefixSet.add("");
ohair@286 794 }
ohair@286 795 _namespaceAIIsNamespaceName[_namespaceAIIsEnd++] = readStructureString();
ohair@286 796 break;
ohair@286 797 }
ohair@286 798 readStructure();
ohair@286 799
ohair@286 800 item = peekStructure();
ohair@286 801 }
ohair@286 802
ohair@286 803 if (inscope) {
ohair@286 804 for (Map.Entry<String, String> e : _buffer.getInscopeNamespaces().entrySet()) {
ohair@286 805 String key = fixNull(e.getKey());
ohair@286 806 // If the prefix is already written, do not write the prefix
ohair@286 807 if (!prefixSet.contains(key)) {
ohair@286 808 if (_namespaceAIIsEnd == _namespaceAIIsPrefix.length) {
ohair@286 809 resizeNamespaceAttributes();
ohair@286 810 }
ohair@286 811 _namespaceAIIsPrefix[_namespaceAIIsEnd] = key;
ohair@286 812 _namespaceAIIsNamespaceName[_namespaceAIIsEnd++] = e.getValue();
ohair@286 813 }
ohair@286 814 }
ohair@286 815 }
ohair@286 816 _stackTop.namespaceAIIsEnd = _namespaceAIIsEnd;
ohair@286 817
ohair@286 818 return item;
ohair@286 819 }
ohair@286 820
ohair@286 821 private static String fixNull(String s) {
ohair@286 822 if (s == null) return "";
ohair@286 823 else return s;
ohair@286 824 }
ohair@286 825
ohair@286 826 private void processAttributes(int item){
ohair@286 827 do {
ohair@286 828 switch(getAIIState(item)){
ohair@286 829 case STATE_ATTRIBUTE_U_LN_QN: {
ohair@286 830 final String uri = readStructureString();
ohair@286 831 final String localName = readStructureString();
ohair@286 832 final String prefix = getPrefixFromQName(readStructureString());
ohair@286 833 _attributeCache.addAttributeWithPrefix(prefix, uri, localName, readStructureString(), readContentString());
ohair@286 834 break;
ohair@286 835 }
ohair@286 836 case STATE_ATTRIBUTE_P_U_LN:
ohair@286 837 _attributeCache.addAttributeWithPrefix(readStructureString(), readStructureString(), readStructureString(), readStructureString(), readContentString());
ohair@286 838 break;
ohair@286 839 case STATE_ATTRIBUTE_U_LN:
ohair@286 840 // _attributeCache follows SAX convention
ohair@286 841 _attributeCache.addAttributeWithPrefix("", readStructureString(), readStructureString(), readStructureString(), readContentString());
ohair@286 842 break;
ohair@286 843 case STATE_ATTRIBUTE_LN: {
ohair@286 844 _attributeCache.addAttributeWithPrefix("", "", readStructureString(), readStructureString(), readContentString());
ohair@286 845 break;
ohair@286 846 }
ohair@286 847 default :
ohair@286 848 assert false : "Internal XSB Error: wrong attribute state, Item="+item;
ohair@286 849 }
ohair@286 850 readStructure();
ohair@286 851
ohair@286 852 item = peekStructure();
ohair@286 853 } while((item & TYPE_MASK) == T_ATTRIBUTE);
ohair@286 854 }
ohair@286 855
ohair@286 856 private void pushElementStack() {
ohair@286 857 if (_depth == _stack.length) {
ohair@286 858 // resize stack
ohair@286 859 ElementStackEntry [] tmp = _stack;
ohair@286 860 _stack = new ElementStackEntry[_stack.length * 3 /2 + 1];
ohair@286 861 System.arraycopy(tmp, 0, _stack, 0, tmp.length);
ohair@286 862 for (int i = tmp.length; i < _stack.length; i++){
ohair@286 863 _stack[i] = new ElementStackEntry();
ohair@286 864 }
ohair@286 865 }
ohair@286 866
ohair@286 867 _stackTop = _stack[_depth++];
ohair@286 868 }
ohair@286 869
ohair@286 870 private void popElementStack(int depth) {
ohair@286 871 // _depth is checked outside this method
ohair@286 872 _stackTop = _stack[depth - 1];
ohair@286 873 // Move back the position of the namespace index
ohair@286 874 _namespaceAIIsEnd = _stack[depth].namespaceAIIsStart;
ohair@286 875 }
ohair@286 876
ohair@286 877 private final class ElementStackEntry {
ohair@286 878 /**
ohair@286 879 * Prefix.
ohair@286 880 * Just like everywhere else in StAX, this can be null but can't be empty.
ohair@286 881 */
ohair@286 882 String prefix;
ohair@286 883 /**
ohair@286 884 * Namespace URI.
ohair@286 885 * Just like everywhere else in StAX, this can be null but can't be empty.
ohair@286 886 */
ohair@286 887 String uri;
ohair@286 888 String localName;
ohair@286 889 QName qname;
ohair@286 890
ohair@286 891 // Start and end of namespace declarations
ohair@286 892 // in namespace declaration arrays
ohair@286 893 int namespaceAIIsStart;
ohair@286 894 int namespaceAIIsEnd;
ohair@286 895
ohair@286 896 public void set(String prefix, String uri, String localName) {
ohair@286 897 this.prefix = prefix;
ohair@286 898 this.uri = uri;
ohair@286 899 this.localName = localName;
ohair@286 900 this.qname = null;
ohair@286 901
ohair@286 902 this.namespaceAIIsStart = this.namespaceAIIsEnd = StreamReaderBufferProcessor.this._namespaceAIIsEnd;
ohair@286 903 }
ohair@286 904
ohair@286 905 public QName getQName() {
ohair@286 906 if (qname == null) {
ohair@286 907 qname = new QName(fixNull(uri), localName, fixNull(prefix));
ohair@286 908 }
ohair@286 909 return qname;
ohair@286 910 }
ohair@286 911
ohair@286 912 private String fixNull(String s) {
ohair@286 913 return (s == null) ? "" : s;
ohair@286 914 }
ohair@286 915 }
ohair@286 916
ohair@286 917 private final class InternalNamespaceContext implements NamespaceContextEx {
ohair@286 918 @SuppressWarnings({"StringEquality"})
ohair@286 919 public String getNamespaceURI(String prefix) {
ohair@286 920 if (prefix == null) {
ohair@286 921 throw new IllegalArgumentException("Prefix cannot be null");
ohair@286 922 }
ohair@286 923
ohair@286 924 /*
ohair@286 925 * If the buffer was created using string interning
ohair@286 926 * intern the prefix and check for reference equality
ohair@286 927 * rather than using String.equals();
ohair@286 928 */
ohair@286 929 if (_stringInterningFeature) {
ohair@286 930 prefix = prefix.intern();
ohair@286 931
ohair@286 932 // Find the most recently declared prefix
ohair@286 933 for (int i = _namespaceAIIsEnd - 1; i >=0; i--) {
ohair@286 934 if (prefix == _namespaceAIIsPrefix[i]) {
ohair@286 935 return _namespaceAIIsNamespaceName[i];
ohair@286 936 }
ohair@286 937 }
ohair@286 938 } else {
ohair@286 939 // Find the most recently declared prefix
ohair@286 940 for (int i = _namespaceAIIsEnd - 1; i >=0; i--) {
ohair@286 941 if (prefix.equals(_namespaceAIIsPrefix[i])) {
ohair@286 942 return _namespaceAIIsNamespaceName[i];
ohair@286 943 }
ohair@286 944 }
ohair@286 945 }
ohair@286 946
ohair@286 947 // Check for XML-based prefixes
ohair@286 948 if (prefix.equals(XMLConstants.XML_NS_PREFIX)) {
ohair@286 949 return XMLConstants.XML_NS_URI;
ohair@286 950 } else if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
ohair@286 951 return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
ohair@286 952 }
ohair@286 953
ohair@286 954 return null;
ohair@286 955 }
ohair@286 956
ohair@286 957 public String getPrefix(String namespaceURI) {
ohair@286 958 final Iterator i = getPrefixes(namespaceURI);
ohair@286 959 if (i.hasNext()) {
ohair@286 960 return (String)i.next();
ohair@286 961 } else {
ohair@286 962 return null;
ohair@286 963 }
ohair@286 964 }
ohair@286 965
ohair@286 966 public Iterator getPrefixes(final String namespaceURI) {
ohair@286 967 if (namespaceURI == null){
ohair@286 968 throw new IllegalArgumentException("NamespaceURI cannot be null");
ohair@286 969 }
ohair@286 970
ohair@286 971 if (namespaceURI.equals(XMLConstants.XML_NS_URI)) {
ohair@286 972 return Collections.singletonList(XMLConstants.XML_NS_PREFIX).iterator();
ohair@286 973 } else if (namespaceURI.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
ohair@286 974 return Collections.singletonList(XMLConstants.XMLNS_ATTRIBUTE).iterator();
ohair@286 975 }
ohair@286 976
ohair@286 977 return new Iterator() {
ohair@286 978 private int i = _namespaceAIIsEnd - 1;
ohair@286 979 private boolean requireFindNext = true;
ohair@286 980 private String p;
ohair@286 981
ohair@286 982 private String findNext() {
ohair@286 983 while(i >= 0) {
ohair@286 984 // Find the most recently declared namespace
ohair@286 985 if (namespaceURI.equals(_namespaceAIIsNamespaceName[i])) {
ohair@286 986 // Find the most recently declared prefix of the namespace
ohair@286 987 // and check if the prefix is in scope with that namespace
ohair@286 988 if (getNamespaceURI(_namespaceAIIsPrefix[i]).equals(
ohair@286 989 _namespaceAIIsNamespaceName[i])) {
ohair@286 990 return p = _namespaceAIIsPrefix[i];
ohair@286 991 }
ohair@286 992 }
ohair@286 993 i--;
ohair@286 994 }
ohair@286 995 return p = null;
ohair@286 996 }
ohair@286 997
ohair@286 998 public boolean hasNext() {
ohair@286 999 if (requireFindNext) {
ohair@286 1000 findNext();
ohair@286 1001 requireFindNext = false;
ohair@286 1002 }
ohair@286 1003 return (p != null);
ohair@286 1004 }
ohair@286 1005
ohair@286 1006 public Object next() {
ohair@286 1007 if (requireFindNext) {
ohair@286 1008 findNext();
ohair@286 1009 }
ohair@286 1010 requireFindNext = true;
ohair@286 1011
ohair@286 1012 if (p == null) {
ohair@286 1013 throw new NoSuchElementException();
ohair@286 1014 }
ohair@286 1015
ohair@286 1016 return p;
ohair@286 1017 }
ohair@286 1018
ohair@286 1019 public void remove() {
ohair@286 1020 throw new UnsupportedOperationException();
ohair@286 1021 }
ohair@286 1022 };
ohair@286 1023 }
ohair@286 1024
ohair@286 1025 private class BindingImpl implements NamespaceContextEx.Binding {
ohair@286 1026 final String _prefix;
ohair@286 1027 final String _namespaceURI;
ohair@286 1028
ohair@286 1029 BindingImpl(String prefix, String namespaceURI) {
ohair@286 1030 _prefix = prefix;
ohair@286 1031 _namespaceURI = namespaceURI;
ohair@286 1032 }
ohair@286 1033
ohair@286 1034 public String getPrefix() {
ohair@286 1035 return _prefix;
ohair@286 1036 }
ohair@286 1037
ohair@286 1038 public String getNamespaceURI() {
ohair@286 1039 return _namespaceURI;
ohair@286 1040 }
ohair@286 1041 }
ohair@286 1042
ohair@286 1043 public Iterator<NamespaceContextEx.Binding> iterator() {
ohair@286 1044 return new Iterator<NamespaceContextEx.Binding>() {
ohair@286 1045 private final int end = _namespaceAIIsEnd - 1;
ohair@286 1046 private int current = end;
ohair@286 1047 private boolean requireFindNext = true;
ohair@286 1048 private NamespaceContextEx.Binding namespace;
ohair@286 1049
ohair@286 1050 private NamespaceContextEx.Binding findNext() {
ohair@286 1051 while(current >= 0) {
ohair@286 1052 final String prefix = _namespaceAIIsPrefix[current];
ohair@286 1053
ohair@286 1054 // Find if the current prefix occurs more recently
ohair@286 1055 // If so then it is not in scope
ohair@286 1056 int i = end;
ohair@286 1057 for (;i > current; i--) {
ohair@286 1058 if (prefix.equals(_namespaceAIIsPrefix[i])) {
ohair@286 1059 break;
ohair@286 1060 }
ohair@286 1061 }
ohair@286 1062 if (i == current--) {
ohair@286 1063 // The current prefix is in-scope
ohair@286 1064 return namespace = new BindingImpl(prefix, _namespaceAIIsNamespaceName[current]);
ohair@286 1065 }
ohair@286 1066 }
ohair@286 1067 return namespace = null;
ohair@286 1068 }
ohair@286 1069
ohair@286 1070 public boolean hasNext() {
ohair@286 1071 if (requireFindNext) {
ohair@286 1072 findNext();
ohair@286 1073 requireFindNext = false;
ohair@286 1074 }
ohair@286 1075 return (namespace != null);
ohair@286 1076 }
ohair@286 1077
ohair@286 1078 public NamespaceContextEx.Binding next() {
ohair@286 1079 if (requireFindNext) {
ohair@286 1080 findNext();
ohair@286 1081 }
ohair@286 1082 requireFindNext = true;
ohair@286 1083
ohair@286 1084 if (namespace == null) {
ohair@286 1085 throw new NoSuchElementException();
ohair@286 1086 }
ohair@286 1087
ohair@286 1088 return namespace;
ohair@286 1089 }
ohair@286 1090
ohair@286 1091 public void remove() {
ohair@286 1092 throw new UnsupportedOperationException();
ohair@286 1093 }
ohair@286 1094 };
ohair@286 1095 }
ohair@286 1096 }
ohair@286 1097
ohair@286 1098 private class DummyLocation implements Location {
ohair@286 1099 public int getLineNumber() {
ohair@286 1100 return -1;
ohair@286 1101 }
ohair@286 1102
ohair@286 1103 public int getColumnNumber() {
ohair@286 1104 return -1;
ohair@286 1105 }
ohair@286 1106
ohair@286 1107 public int getCharacterOffset() {
ohair@286 1108 return -1;
ohair@286 1109 }
ohair@286 1110
ohair@286 1111 public String getPublicId() {
ohair@286 1112 return null;
ohair@286 1113 }
ohair@286 1114
ohair@286 1115 public String getSystemId() {
ohair@286 1116 return _buffer.getSystemId();
ohair@286 1117 }
ohair@286 1118 }
ohair@286 1119
ohair@286 1120 private static String fixEmptyString(String s) {
ohair@286 1121 // s must not be null, so no need to check for that. that would be bug.
ohair@286 1122 if(s.length()==0) return null;
ohair@286 1123 else return s;
ohair@286 1124 }
ohair@286 1125
ohair@286 1126 }

mercurial