1 package net.sf.saxon.tinytree; 2 3 import net.sf.saxon.event.PipelineConfiguration; 4 import net.sf.saxon.om.*; 5 import net.sf.saxon.pull.PullProvider; 6 import net.sf.saxon.trans.XPathException; 7 import net.sf.saxon.type.Type; 8 import net.sf.saxon.value.AtomicValue; 9 import net.sf.saxon.style.StandardNames; 10 11 import javax.xml.transform.SourceLocator ; 12 13 22 23 public class TinyTreeWalker implements PullProvider, SourceLocator { 24 25 private int startNode; 26 private int currentNode; 27 private int currentEvent; 28 private TinyTree tree; 29 private PipelineConfiguration pipe; 30 private NamespaceDeclarationsImpl nsDeclarations; 31 private int[] nsBuffer = new int[10]; 32 33 39 40 public TinyTreeWalker(TinyNodeImpl startNode) { 41 int kind = startNode.getNodeKind(); 42 if (kind == Type.ATTRIBUTE || kind == Type.NAMESPACE) { 43 throw new IllegalArgumentException ("TinyTreeWalker cannot start at an attribute or namespace node"); 44 } 45 this.startNode = startNode.nodeNr; 46 this.tree = startNode.tree; 47 this.nsDeclarations = new NamespaceDeclarationsImpl(); 48 nsDeclarations.setNamePool(startNode.getNamePool()); 49 } 50 51 55 56 public void setPipelineConfiguration(PipelineConfiguration pipe) { 57 this.pipe = pipe; 58 } 59 60 63 64 public PipelineConfiguration getPipelineConfiguration() { 65 return pipe; 66 } 67 68 74 75 public int next() throws XPathException { 76 switch(currentEvent) { 77 case START_OF_INPUT: 78 currentNode = startNode; 79 switch (tree.nodeKind[currentNode]) { 80 case Type.DOCUMENT: 81 currentEvent = START_DOCUMENT; 82 break; 83 case Type.ELEMENT: 84 currentEvent = START_ELEMENT; 85 break; 86 case Type.TEXT: 87 currentEvent = TEXT; 88 break; 89 case Type.COMMENT: 90 currentEvent = COMMENT; 91 break; 92 case Type.PROCESSING_INSTRUCTION: 93 currentEvent = PROCESSING_INSTRUCTION; 94 break; 95 case Type.PARENT_POINTER: 96 throw new IllegalStateException ("Current node is a parent-pointer pseudo-node"); 97 } 98 return currentEvent; 99 100 case START_DOCUMENT: 101 case START_ELEMENT: 102 103 if (tree.depth[currentNode+1] > tree.depth[currentNode]) { 104 switch (tree.nodeKind[++currentNode]) { 106 case Type.ELEMENT: 107 currentEvent = START_ELEMENT; 108 break; 109 case Type.TEXT: 110 currentEvent = TEXT; 111 break; 112 case Type.COMMENT: 113 currentEvent = COMMENT; 114 break; 115 case Type.PROCESSING_INSTRUCTION: 116 currentEvent = PROCESSING_INSTRUCTION; 117 break; 118 case Type.PARENT_POINTER: 119 throw new IllegalStateException ("First child node must not be a parent-pointer pseudo-node"); 120 } 121 return currentEvent; 122 } else { 123 if (currentEvent == START_DOCUMENT) { 124 currentEvent = END_DOCUMENT; 125 } else { 126 currentEvent = END_ELEMENT; 127 } 128 return currentEvent; 129 } 130 case END_ELEMENT: 131 case TEXT: 132 case COMMENT: 133 case PROCESSING_INSTRUCTION: 134 if (currentNode == startNode) { 135 currentEvent = END_OF_INPUT; 136 return currentEvent; 137 } 138 int next = tree.next[currentNode]; 139 if (next > currentNode) { 140 currentNode = tree.next[currentNode]; 142 do { 143 switch (tree.nodeKind[currentNode]) { 144 case Type.ELEMENT: 145 currentEvent = START_ELEMENT; 146 break; 147 case Type.TEXT: 148 currentEvent = TEXT; 149 break; 150 case Type.COMMENT: 151 currentEvent = COMMENT; 152 break; 153 case Type.PROCESSING_INSTRUCTION: 154 currentEvent = PROCESSING_INSTRUCTION; 155 break; 156 case Type.PARENT_POINTER: 157 currentEvent = -1; 159 currentNode++; 160 break; 161 } 162 } while (currentEvent == -1); 163 return currentEvent; 164 } else { 165 currentNode = next; 167 if (currentNode == -1) { 168 currentEvent = END_OF_INPUT; 170 return currentEvent; 171 } 172 switch (tree.nodeKind[currentNode]) { 173 case Type.ELEMENT: 174 currentEvent = END_ELEMENT; 175 break; 176 case Type.DOCUMENT: 177 currentEvent = END_DOCUMENT; 178 break; 179 } 180 return currentEvent; 181 } 182 183 case ATTRIBUTE: 184 case NAMESPACE: 185 case END_DOCUMENT: 186 currentEvent = END_OF_INPUT; 187 return currentEvent; 188 189 case END_OF_INPUT: 190 throw new IllegalStateException ("Cannot call next() when input is exhausted"); 191 192 default: 193 throw new IllegalStateException ("Unrecognized event " + currentEvent); 194 195 } 196 } 197 198 205 206 public int current() { 207 return currentEvent; 208 } 209 210 224 225 public AttributeCollection getAttributes() throws XPathException { 226 if (tree.nodeKind[currentNode] == Type.ELEMENT) { 227 if (tree.alpha[currentNode] == -1) { 228 return AttributeCollectionImpl.EMPTY_ATTRIBUTE_COLLECTION; 229 } 230 return new TinyAttributeCollection(tree, currentNode); 231 } else { 232 throw new IllegalStateException ("getAttributes() called when current event is not ELEMENT_START"); 233 } 234 } 235 236 255 256 public NamespaceDeclarations getNamespaceDeclarations() throws XPathException { 257 if (tree.nodeKind[currentNode] == Type.ELEMENT) { 258 int[] decl; 259 if (currentNode == startNode) { 260 decl = TinyElementImpl.getInScopeNamespaces(tree, currentNode, nsBuffer); 262 } else { 263 decl = TinyElementImpl.getDeclaredNamespaces(tree, currentNode, nsBuffer); 265 } 266 nsDeclarations.setNamespaceCodes(decl); 267 return nsDeclarations; 268 } 269 throw new IllegalStateException ("getNamespaceDeclarations() called when current event is not START_ELEMENT"); 270 } 271 272 278 279 public int skipToMatchingEnd() throws XPathException { 280 switch (currentEvent) { 283 case START_DOCUMENT: 284 currentEvent = END_DOCUMENT; 285 return currentEvent; 286 case START_ELEMENT: 287 currentEvent = END_ELEMENT; 288 return currentEvent; 289 default: 290 throw new IllegalStateException ( 291 "Cannot call skipToMatchingEnd() except when at start of element or document"); 292 293 } 294 } 295 296 303 304 public void close() { 305 } 307 308 313 314 public NamePool getNamePool() { 315 return pipe.getConfiguration().getNamePool(); 316 } 317 318 329 330 public int getNameCode() { 331 switch (currentEvent) { 332 case START_ELEMENT: 333 case PROCESSING_INSTRUCTION: 334 case END_ELEMENT: 335 return tree.nameCode[currentNode]; 336 default: 337 throw new IllegalStateException ("getNameCode() called when its value is undefined"); 338 } 339 } 340 341 354 355 public int getFingerprint() { 356 int nc = getNameCode(); 357 if (nc == -1) { 358 return -1; 359 } else { 360 return nc & NamePool.FP_MASK; 361 } 362 } 363 364 371 372 public CharSequence getStringValue() throws XPathException { 373 switch (tree.nodeKind[currentNode]) { 374 case Type.TEXT: 375 return TinyTextImpl.getStringValue(tree, currentNode); 376 case Type.COMMENT: 377 case Type.PROCESSING_INSTRUCTION: 378 return tree.getNode(currentNode).getStringValue(); 380 case Type.ELEMENT: 381 currentEvent = END_ELEMENT; 382 return TinyParentNodeImpl.getStringValue(tree, currentNode); 383 case Type.PARENT_POINTER: 384 throw new IllegalStateException ("Trying to get string value of a parent-pointer pseudo node"); 385 } 386 return null; 387 } 388 389 394 395 public AtomicValue getAtomicValue() { 396 throw new IllegalStateException (); 397 } 398 399 407 408 public int getTypeAnnotation() { 409 if (tree.nodeKind[currentNode] != Type.ELEMENT) { 410 throw new IllegalStateException ("getTypeAnnotation() called when current event is not ELEMENT_START or "); 411 } 412 if (tree.typeCodeArray == null) { 413 return StandardNames.XDT_UNTYPED; 414 } 415 return tree.typeCodeArray[currentNode]; 416 } 417 418 425 426 public SourceLocator getSourceLocator() { 427 return this; 428 } 429 430 441 public String getPublicId() { 442 return null; 443 } 444 445 459 public String getSystemId() { 460 return tree.getSystemId(currentNode); 461 } 462 463 478 public int getLineNumber() { 479 return tree.getLineNumber(currentNode); 480 } 481 482 497 public int getColumnNumber() { 498 return -1; 499 } 500 } 501 502 | Popular Tags |