Source Code Cross Referenced for VirtualTreeWalker.java in  » XML » saxonb » net » sf » saxon » pull » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML » saxonb » net.sf.saxon.pull 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package net.sf.saxon.pull;
002:
003:        import net.sf.saxon.Configuration;
004:        import net.sf.saxon.event.PipelineConfiguration;
005:        import net.sf.saxon.expr.XPathContext;
006:        import net.sf.saxon.instruct.DocumentInstr;
007:        import net.sf.saxon.instruct.ElementCreator;
008:        import net.sf.saxon.instruct.ParentNodeConstructor;
009:        import net.sf.saxon.om.*;
010:        import net.sf.saxon.trans.DynamicError;
011:        import net.sf.saxon.trans.XPathException;
012:        import net.sf.saxon.type.Type;
013:        import net.sf.saxon.value.AtomicValue;
014:
015:        import javax.xml.transform.SourceLocator;
016:        import java.util.ArrayList;
017:        import java.util.Stack;
018:
019:        /**
020:         * A virtual tree walker provides a sequence of pull events describing the structure and content of a tree
021:         * that is conceptually being constructed by expressions in a query or stylesheet; in fact the tree is
022:         * not necessarily constructed in memory, and exists only as this stream of pull events.
023:         * <p>
024:         * The tree is physically constructed if operations are requested that depend on the identity of the nodes
025:         * in the tree, or that navigate within the tree. Operations such as copying or atomizing the tree can be done
026:         * directly, without building it in memory. (Note however that if such operations are done more than once, the
027:         * underlying instructions may be evaluated repeatedly.)
028:         */
029:
030:        public class VirtualTreeWalker implements  PullProvider,
031:                NamespaceDeclarations {
032:
033:            private PipelineConfiguration pipe;
034:            private int currentEvent = START_OF_INPUT;
035:            private int nameCode;
036:            private int nextNameCode;
037:            private ParentNodeConstructor instruction;
038:            private XPathContext context;
039:            private Stack constructorStack = new Stack();
040:            private Stack iteratorStack = new Stack();
041:            private PullProvider subordinateTreeWalker = null;
042:            // The subordinateTreeWalker is used if the tree construction expression pulls in references
043:            // to document or element nodes in an existing source document. When this happens, tree walking
044:            // events generated by walking the source document are copied into to the stream of events
045:            // generated by this class.
046:            private boolean alreadyRead = false;
047:            private boolean allowAttributes = false;
048:
049:            private int stripDepth = -1;
050:            // If this is >0, it indicates that instructions on the constructor stack with depth < stripDepth
051:            // specify validation=preserve, while those at greater depth effectively specify validation=strip
052:            // (It doesn't matter if they actually say validation=preserve, the stripping takes priority)
053:
054:            private AttributeCollectionImpl attributes;
055:            private boolean foundAttributes;
056:            private int[] activeNamespaces;
057:            private ArrayList additionalNamespaces = new ArrayList(10); // array of namespace nodes
058:
059:            /**
060:             * Create a VirtualTreeWalker to navigate the tree constructed by evaluating a given instruction
061:             * in a given dyamic context
062:             * @param instruction the instruction (this will always be an instruction that creates element or
063:             * document nodes)
064:             * @param context the dynamic evaluation context
065:             */
066:
067:            public VirtualTreeWalker(ParentNodeConstructor instruction,
068:                    XPathContext context) {
069:                this .instruction = instruction;
070:                this .context = context;
071:            }
072:
073:            /**
074:             * Set configuration information. This must only be called before any events
075:             * have been read.
076:             */
077:
078:            public void setPipelineConfiguration(PipelineConfiguration pipe) {
079:                this .pipe = pipe;
080:            }
081:
082:            /**
083:             * Get configuration information.
084:             */
085:
086:            public PipelineConfiguration getPipelineConfiguration() {
087:                return pipe;
088:            }
089:
090:            /**
091:             * Get the namepool
092:             */
093:
094:            public NamePool getNamePool() {
095:                return pipe.getConfiguration().getNamePool();
096:            }
097:
098:            /**
099:             * Get the next event
100:             *
101:             * @return an integer code indicating the type of event. The code
102:             *         {@link #END_OF_INPUT} is returned at the end of the sequence.
103:             */
104:
105:            public int next() throws XPathException {
106:
107:                try {
108:
109:                    // First see if we are currently walking some other tree that has been logically
110:                    // copied into this tree.
111:
112:                    if (subordinateTreeWalker != null) {
113:                        currentEvent = subordinateTreeWalker.next();
114:                        if (currentEvent == END_OF_INPUT) {
115:                            subordinateTreeWalker = null;
116:                            return next();
117:                        }
118:                        return currentEvent;
119:                    }
120:
121:                    // On the first call, produce a START_ELEMENT or START_DOCUMENT event depending on the instruction
122:
123:                    if (currentEvent == START_OF_INPUT) {
124:                        constructorStack.push(instruction);
125:                        if (stripDepth < 0
126:                                && instruction.getValidationAction() == Validation.STRIP) {
127:                            stripDepth = constructorStack.size();
128:                        }
129:                        SequenceIterator content = instruction
130:                                .getContentExpression().iterate(context);
131:                        iteratorStack.push(content);
132:                        if (instruction instanceof  DocumentInstr) {
133:                            currentEvent = START_DOCUMENT;
134:                            nameCode = -1;
135:                        } else {
136:                            currentEvent = START_ELEMENT;
137:                            nameCode = ((ElementCreator) instruction)
138:                                    .getNameCode(context);
139:                            allowAttributes = true;
140:                            // look ahead to generate all the attributes and namespaces of the element
141:                            processAttributesAndNamespaces(
142:                                    (ElementCreator) instruction, content);
143:                            // remember that we've read one event too many
144:                            allowAttributes = false;
145:                            alreadyRead = true;
146:                        }
147:                        return currentEvent;
148:                    }
149:
150:                    if (iteratorStack.isEmpty()) {
151:                        // if we're at the top level, see if we've just started, or are about to finish
152:                        if (currentEvent == START_DOCUMENT
153:                                || currentEvent == START_ELEMENT) {
154:                            // we've just started: start processing the content of the instruction
155:                            SequenceIterator iter = instruction
156:                                    .getContentExpression().iterate(context);
157:                            constructorStack.push(instruction);
158:                            if (stripDepth < 0
159:                                    && instruction.getValidationAction() == Validation.STRIP) {
160:                                stripDepth = constructorStack.size();
161:                            }
162:                            iteratorStack.push(iter);
163:                        } else if (currentEvent == END_DOCUMENT
164:                                || currentEvent == END_ELEMENT) {
165:                            // we're about to finish
166:                            currentEvent = END_OF_INPUT;
167:                            return currentEvent;
168:                        } else {
169:                            // we're going to finish soon, but must first generate the last END_DOCUMENT or END_ELEMENT event
170:                            currentEvent = ((instruction instanceof  DocumentInstr) ? END_DOCUMENT
171:                                    : END_ELEMENT);
172:                            return currentEvent;
173:                        }
174:                    }
175:
176:                    // Read the next item from the current content iterator
177:
178:                    SequenceIterator iterator = ((SequenceIterator) iteratorStack
179:                            .peek());
180:                    if (alreadyRead) {
181:                        Item item = iterator.current();
182:                        alreadyRead = false;
183:                        nameCode = nextNameCode;
184:                        return processItem(iterator, item);
185:                    } else {
186:                        return processItem(iterator, iterator.next());
187:                    }
188:                } catch (XPathException e) {
189:                    // report any dynamic errors unless already reported
190:                    context.getController().reportFatalError(e);
191:                    throw e;
192:                }
193:            }
194:
195:            private FastStringBuffer textNodeBuffer = new FastStringBuffer(100);
196:
197:            /**
198:             * Process an item in the content of an element or document node
199:             * @param iterator the iterator over the contents of the element or document
200:             * @param item the current item to be processed, or null if the end of the content
201:             * iterator has been reached
202:             * @return the next event code
203:             * @throws XPathException if a dynamic error occurs
204:             */
205:
206:            private int processItem(SequenceIterator iterator, Item item)
207:                    throws XPathException {
208:                if (item == null) {
209:                    // we've reached the end of the children
210:                    if (stripDepth == constructorStack.size()) {
211:                        stripDepth = -1;
212:                    }
213:                    ParentNodeConstructor inst = (ParentNodeConstructor) constructorStack
214:                            .pop();
215:                    if (inst instanceof  DocumentInstr) {
216:                        iteratorStack.pop();
217:                        if (iteratorStack.isEmpty()) {
218:                            currentEvent = END_DOCUMENT;
219:                            nameCode = -1;
220:                            return currentEvent;
221:                        }
222:                        // skip the END_DOCUMENT event for a nested document node
223:                        return next();
224:                    } else {
225:                        currentEvent = END_ELEMENT;
226:                        nameCode = -1;
227:                        iteratorStack.pop();
228:                        return currentEvent;
229:                    }
230:
231:                } else if (item instanceof  UnconstructedParent) {
232:                    // this represents a nested element or document node constructor
233:                    UnconstructedParent parent = (UnconstructedParent) item;
234:                    ParentNodeConstructor inst = parent.getInstruction();
235:
236:                    constructorStack.push(inst);
237:                    if (stripDepth < 0
238:                            && inst.getValidationAction() == Validation.STRIP) {
239:                        stripDepth = constructorStack.size();
240:                    }
241:                    SequenceIterator content = inst.getContentExpression()
242:                            .iterate(parent.getXPathContext());
243:                    if (inst instanceof  DocumentInstr) {
244:                        iteratorStack.push(content);
245:                        // skip the START_DOCUMENT event
246:                        return next();
247:                    } else {
248:                        currentEvent = START_ELEMENT;
249:                        nameCode = ((UnconstructedElement) item).getNameCode();
250:                        processAttributesAndNamespaces((ElementCreator) inst,
251:                                content);
252:                        alreadyRead = true;
253:                        iteratorStack.push(content);
254:                        return currentEvent;
255:                    }
256:
257:                } else if (item instanceof  AtomicValue) {
258:                    textNodeBuffer.setLength(0);
259:                    textNodeBuffer.append(item.getStringValueCS());
260:                    while (true) {
261:                        Item next = iterator.next();
262:                        if (next instanceof  AtomicValue) {
263:                            textNodeBuffer.append(' ');
264:                            textNodeBuffer.append(next.getStringValueCS());
265:                            continue;
266:                        } else {
267:                            currentEvent = TEXT;
268:                            nameCode = -1;
269:                            alreadyRead = true;
270:                            return currentEvent;
271:                        }
272:                    }
273:
274:                } else {
275:                    nameCode = ((NodeInfo) item).getNameCode();
276:                    switch (((NodeInfo) item).getNodeKind()) {
277:                    case Type.TEXT:
278:                        currentEvent = TEXT;
279:                        textNodeBuffer.setLength(0);
280:                        textNodeBuffer.append(item.getStringValueCS());
281:                        // TODO: avoid this unnecessary copy.
282:                        return currentEvent;
283:
284:                    case Type.COMMENT:
285:                        currentEvent = COMMENT;
286:                        return currentEvent;
287:
288:                    case Type.PROCESSING_INSTRUCTION:
289:                        currentEvent = PROCESSING_INSTRUCTION;
290:                        return currentEvent;
291:
292:                    case Type.ATTRIBUTE:
293:                        if (!allowAttributes) {
294:                            DynamicError de;
295:                            if (constructorStack.peek() instanceof  DocumentInstr) {
296:                                de = new DynamicError(
297:                                        "Attributes cannot be attached to a document node");
298:                                if (context.getController().getExecutable()
299:                                        .getHostLanguage() == Configuration.XQUERY) {
300:                                    de.setErrorCode("XQTY0004");
301:                                } else {
302:                                    de.setErrorCode("XTDE0420");
303:                                }
304:                            } else {
305:                                de = new DynamicError(
306:                                        "Attributes in the content of an element must come before the child nodes");
307:                                if (context.getController().getExecutable()
308:                                        .getHostLanguage() == Configuration.XQUERY) {
309:                                    de.setErrorCode("XQDY0024");
310:                                } else {
311:                                    de.setErrorCode("XTDE0410");
312:                                }
313:                            }
314:                            de.setXPathContext(context);
315:                            de.setLocator(getSourceLocator());
316:                            throw de;
317:                        }
318:                        currentEvent = ATTRIBUTE;
319:                        return currentEvent;
320:
321:                    case Type.NAMESPACE:
322:                        if (!allowAttributes) {
323:                            DynamicError de = new DynamicError(
324:                                    "Namespace nodes in the content of an element must come before the child nodes");
325:                            de.setErrorCode("XTDE0410");
326:                            de.setXPathContext(context);
327:                            de.setLocator(getSourceLocator());
328:                            throw de;
329:                        }
330:                        currentEvent = NAMESPACE;
331:                        return currentEvent;
332:
333:                    case Type.ELEMENT:
334:                        subordinateTreeWalker = TreeWalker
335:                                .makeTreeWalker((NodeInfo) item);
336:                        subordinateTreeWalker.setPipelineConfiguration(pipe);
337:                        currentEvent = subordinateTreeWalker.next();
338:                        nameCode = subordinateTreeWalker.getNameCode();
339:                        return currentEvent;
340:
341:                    case Type.DOCUMENT:
342:                        subordinateTreeWalker = TreeWalker
343:                                .makeTreeWalker((NodeInfo) item);
344:                        subordinateTreeWalker.setPipelineConfiguration(pipe);
345:                        subordinateTreeWalker = new DocumentEventIgnorer(
346:                                subordinateTreeWalker);
347:                        subordinateTreeWalker.setPipelineConfiguration(pipe);
348:                        currentEvent = subordinateTreeWalker.next();
349:                        nameCode = -1;
350:                        return currentEvent;
351:
352:                    default:
353:                        throw new IllegalStateException();
354:
355:                    }
356:                }
357:            }
358:
359:            /**
360:             * Following a START_ELEMENT event, evaluate the contents of the element to obtain all attributes and namespaces.
361:             * This process stops when the first event other than an attribute or namespace is read. We then remember the
362:             * extra event, which will be the next event returned in the normal sequence. Note that the relative order
363:             * of attributes and namespaces is undefined.
364:             * @param inst The instruction that creates the element node
365:             * @param content Iterator over the expression that generates the attributes, namespaces, and content of the
366:             * element
367:             * @throws XPathException if any dynamic error occurs
368:             */
369:            private void processAttributesAndNamespaces(ElementCreator inst,
370:                    SequenceIterator content) throws XPathException {
371:                foundAttributes = false;
372:                additionalNamespaces.clear();
373:                activeNamespaces = inst.getActiveNamespaces();
374:                if (activeNamespaces == null) {
375:                    activeNamespaces = EMPTY_INT_ARRAY;
376:                }
377:                boolean preserve = (stripDepth < 0);
378:                while (true) {
379:                    Item next = content.next();
380:                    if (next == null) {
381:                        break;
382:                    } else if (next instanceof  NodeInfo) {
383:                        NodeInfo node = (NodeInfo) next;
384:                        int kind = node.getNodeKind();
385:                        if (kind == Type.ATTRIBUTE) {
386:                            if (!foundAttributes) {
387:                                if (attributes == null) {
388:                                    attributes = new AttributeCollectionImpl(
389:                                            context.getNamePool());
390:                                }
391:                                attributes.clear();
392:                                foundAttributes = true;
393:                            }
394:                            int index = attributes.getIndexByFingerprint(node
395:                                    .getFingerprint());
396:                            if (index >= 0) {
397:                                // Attribute already exists. In XQuery this is an error. In XSLT, the last attribute wins
398:                                if (context.getController().getExecutable()
399:                                        .getHostLanguage() == Configuration.XSLT) {
400:                                    attributes.setAttribute(index, node
401:                                            .getNameCode(), preserve ? node
402:                                            .getTypeAnnotation() : -1, node
403:                                            .getStringValue(), 0, 0);
404:                                } else {
405:                                    DynamicError de = new DynamicError(
406:                                            "The attributes of an element must have distinct names");
407:                                    de.setErrorCode("XQDY0025");
408:                                    de.setXPathContext(context);
409:                                    de.setLocator(getSourceLocator());
410:                                    throw de;
411:                                }
412:                            } else {
413:                                attributes.addAttribute(node.getNameCode(),
414:                                        preserve ? node.getTypeAnnotation()
415:                                                : -1, node.getStringValue(), 0,
416:                                        0);
417:                            }
418:                        } else if (kind == Type.NAMESPACE) {
419:                            additionalNamespaces.add(node);
420:                        } else if (kind == Type.TEXT
421:                                && node.getStringValue().equals("")) {
422:                            continue; // ignore zero-length text nodes
423:                        } else {
424:                            nextNameCode = ((NodeInfo) next).getNameCode();
425:                            break;
426:                        }
427:                    } else {
428:                        break;
429:                    }
430:                }
431:            }
432:
433:            /**
434:             * Get the event most recently returned by next(), or by other calls that change
435:             * the position, for example getStringValue() and skipToMatchingEnd(). This
436:             * method does not change the position of the PullProvider.
437:             *
438:             * @return the current event
439:             */
440:
441:            public int current() {
442:                return currentEvent;
443:            }
444:
445:            /**
446:             * Get the attributes associated with the current element. This method must
447:             * be called only after a START_ELEMENT event has been notified. The contents
448:             * of the returned AttributeCollection are guaranteed to remain unchanged
449:             * until the next START_ELEMENT event, but may be modified thereafter. The object
450:             * should not be modified by the client.
451:             * <p/>
452:             * <p>Attributes may be read before or after reading the namespaces of an element,
453:             * but must not be read after the first child node has been read, or after calling
454:             * one of the methods skipToEnd(), getStringValue(), or getTypedValue().</p>
455:             *
456:             * @return an AttributeCollection representing the attributes of the element
457:             *         that has just been notified.
458:             */
459:
460:            public AttributeCollection getAttributes() throws XPathException {
461:                if (subordinateTreeWalker != null) {
462:                    return subordinateTreeWalker.getAttributes();
463:                } else {
464:                    if (foundAttributes) {
465:                        return attributes;
466:                    } else {
467:                        return AttributeCollectionImpl.EMPTY_ATTRIBUTE_COLLECTION;
468:                    }
469:                }
470:            }
471:
472:            /**
473:             * Get the namespace declarations associated with the current element. This method must
474:             * be called only after a START_ELEMENT event has been notified. In the case of a top-level
475:             * START_ELEMENT event (that is, an element that either has no parent node, or whose parent
476:             * is not included in the sequence being read), the NamespaceDeclarations object returned
477:             * will contain a namespace declaration for each namespace that is in-scope for this element
478:             * node. In the case of a non-top-level element, the NamespaceDeclarations will contain
479:             * a set of namespace declarations and undeclarations, representing the differences between
480:             * this element and its parent.
481:             * <p/>
482:             * <p>It is permissible for this method to return namespace declarations that are redundant.</p>
483:             * <p/>
484:             * <p>The NamespaceDeclarations object is guaranteed to remain unchanged until the next START_ELEMENT
485:             * event, but may then be overwritten. The object should not be modified by the client.</p>
486:             * <p/>
487:             * <p>Namespaces may be read before or after reading the attributes of an element,
488:             * but must not be read after the first child node has been read, or after calling
489:             * one of the methods skipToEnd(), getStringValue(), or getTypedValue().</p>*
490:             */
491:
492:            public NamespaceDeclarations getNamespaceDeclarations()
493:                    throws XPathException {
494:                if (subordinateTreeWalker != null) {
495:                    return subordinateTreeWalker.getNamespaceDeclarations();
496:                } else {
497:                    return this ;
498:                }
499:            }
500:
501:            /**
502:             * Skip the current subtree. This method may be called only immediately after
503:             * a START_DOCUMENT or START_ELEMENT event. This call returns the matching
504:             * END_DOCUMENT or END_ELEMENT event; the next call on next() will return
505:             * the event following the END_DOCUMENT or END_ELEMENT.
506:             * @throws IllegalStateException if the method is called at any time other than
507:             * immediately after a START_DOCUMENT or START_ELEMENT event.
508:             */
509:
510:            public int skipToMatchingEnd() throws XPathException {
511:                if (currentEvent != START_DOCUMENT
512:                        && currentEvent != START_ELEMENT) {
513:                    throw new IllegalStateException();
514:                }
515:                if (subordinateTreeWalker != null) {
516:                    return subordinateTreeWalker.skipToMatchingEnd();
517:                } else {
518:                    SequenceIterator content = (SequenceIterator) iteratorStack
519:                            .peek();
520:                    if (alreadyRead) {
521:                        alreadyRead = false;
522:                    }
523:                    while (true) {
524:                        Item next = content.next();
525:                        if (next == null) {
526:                            break;
527:                        }
528:                    }
529:                    return (currentEvent == START_DOCUMENT ? END_DOCUMENT
530:                            : END_ELEMENT);
531:                }
532:            }
533:
534:            /**
535:             * Close the event reader. This indicates that no further events are required.
536:             * It is not necessary to close an event reader after {@link #END_OF_INPUT} has
537:             * been reported, but it is recommended to close it if reading terminates
538:             * prematurely. Once an event reader has been closed, the effect of further
539:             * calls on next() is undefined.
540:             */
541:
542:            public void close() {
543:                if (subordinateTreeWalker != null) {
544:                    subordinateTreeWalker.close();
545:                } else {
546:                    // do nothing
547:                }
548:            }
549:
550:            /**
551:             * Set the initial nameCode (the nameCode of the node at the root of the tree being walked)
552:             */
553:
554:            public void setNameCode(int nameCode) {
555:                this .nameCode = nameCode;
556:            }
557:
558:            /**
559:             * Get the nameCode identifying the name of the current node. This method
560:             * can be used after the {@link #START_ELEMENT}, {@link #END_ELEMENT}, {@link #PROCESSING_INSTRUCTION},
561:             * {@link #ATTRIBUTE}, or {@link #NAMESPACE} events. With some PullProvider implementations,
562:             * <b>but not this one</b>, it can also be used after {@link #END_ELEMENT}.
563:             * If called at other times, the result is undefined and may result in an IllegalStateException.
564:             * If called when the current node is an unnamed namespace node (a node representing the default namespace)
565:             * the returned value is -1.
566:             *
567:             * @return the nameCode. The nameCode can be used to obtain the prefix, local name,
568:             *         and namespace URI from the name pool.
569:             */
570:
571:            public int getNameCode() {
572:                if (subordinateTreeWalker != null) {
573:                    return subordinateTreeWalker.getNameCode();
574:                }
575:                return nameCode;
576:            }
577:
578:            /**
579:             * Get the fingerprint of the name of the element. This is similar to the nameCode, except that
580:             * it does not contain any information about the prefix: so two elements with the same fingerprint
581:             * have the same name, excluding prefix. This method
582:             * can be used after the {@link #START_ELEMENT}, {@link #END_ELEMENT}, {@link #PROCESSING_INSTRUCTION},
583:             * {@link #ATTRIBUTE}, or {@link #NAMESPACE} events.
584:             * If called at other times, the result is undefined and may result in an IllegalStateException.
585:             * If called when the current node is an unnamed namespace node (a node representing the default namespace)
586:             * the returned value is -1.
587:             *
588:             * @return the fingerprint. The fingerprint can be used to obtain the local name
589:             *         and namespace URI from the name pool.
590:             */
591:
592:            public int getFingerprint() {
593:                int nc = getNameCode();
594:                if (nc == -1) {
595:                    return -1;
596:                } else {
597:                    return nc & NamePool.FP_MASK;
598:                }
599:            }
600:
601:            /**
602:             * Get the string value of the current element, text node, processing-instruction,
603:             * or top-level attribute or namespace node, or atomic value.
604:             * <p/>
605:             * <p>In other situations the result is undefined and may result in an IllegalStateException.</p>
606:             * <p/>
607:             * <p>If the most recent event was a {@link #START_ELEMENT}, this method causes the content
608:             * of the element to be read. The current event on completion of this method will be the
609:             * corresponding {@link #END_ELEMENT}. The next call of next() will return the event following
610:             * the END_ELEMENT event.</p>
611:             *
612:             * @return the String Value of the node in question, defined according to the rules in the
613:             *         XPath data model.
614:             */
615:
616:            public CharSequence getStringValue() throws XPathException {
617:                if (subordinateTreeWalker != null) {
618:                    return subordinateTreeWalker.getStringValue();
619:                } else if (currentEvent == TEXT) {
620:                    return textNodeBuffer;
621:                } else if (currentEvent != START_ELEMENT
622:                        && currentEvent != START_DOCUMENT) {
623:                    SequenceIterator content = (SequenceIterator) iteratorStack
624:                            .peek();
625:                    if (content.current() == null) {
626:                        return "";
627:                    }
628:                    return content.current().getStringValue();
629:                } else {
630:                    FastStringBuffer sb = new FastStringBuffer(100);
631:                    SequenceIterator content = (SequenceIterator) iteratorStack
632:                            .peek();
633:                    if (alreadyRead) {
634:                        if (content.current() == null) {
635:                            return "";
636:                        }
637:                        processText(content.current(), sb);
638:                        alreadyRead = false;
639:                    }
640:                    while (true) {
641:                        Item next = content.next();
642:                        if (next == null) {
643:                            break;
644:                        }
645:                        processText(next, sb);
646:                    }
647:                    return sb;
648:                }
649:            }
650:
651:            /**
652:             * Add the string value of a child item to a string buffer that is used to accumulate the
653:             * string value of a document or element node
654:             * @param item the child item
655:             * @param sb the string buffer where the content is accumulated
656:             */
657:
658:            private void processText(Item item, FastStringBuffer sb) {
659:                if (item instanceof  UnconstructedParent) {
660:                    sb.append(item.getStringValueCS());
661:                } else if (item instanceof  AtomicValue) {
662:                    sb.append(item.getStringValueCS());
663:                } else {
664:                    NodeInfo node = (NodeInfo) item;
665:                    switch (node.getNodeKind()) {
666:                    case Type.DOCUMENT:
667:                    case Type.ELEMENT:
668:                    case Type.TEXT:
669:                        sb.append(node.getStringValueCS());
670:                    default:
671:                        // do nothing
672:                    }
673:                }
674:            }
675:
676:            /**
677:             * Get an atomic value. This call may be used only when the last event reported was
678:             * ATOMIC_VALUE. This indicates that the PullProvider is reading a sequence that contains
679:             * a free-standing atomic value; it is never used when reading the content of a node.
680:             */
681:
682:            public AtomicValue getAtomicValue() {
683:                throw new IllegalStateException();
684:            }
685:
686:            /**
687:             * Get the type annotation of the current attribute or element node, or atomic value.
688:             * The result of this method is undefined unless the most recent event was START_ELEMENT,
689:             * ATTRIBUTE, or ATOMIC_VALUE.
690:             *
691:             * @return the type annotation. This code is the fingerprint of a type name, which may be
692:             *         resolved to a {@link net.sf.saxon.type.SchemaType} by access to the Configuration.
693:             */
694:
695:            public int getTypeAnnotation() {
696:                if (subordinateTreeWalker != null && stripDepth < 0) {
697:                    return subordinateTreeWalker.getTypeAnnotation();
698:                } else {
699:                    return -1;
700:                }
701:            }
702:
703:            /**
704:             * Get the location of the current event.
705:             * For an event stream representing a real document, the location information
706:             * should identify the location in the lexical XML source. For a constructed document, it should
707:             * identify the location in the query or stylesheet that caused the node to be created.
708:             * A value of null can be returned if no location information is available.
709:             */
710:
711:            public SourceLocator getSourceLocator() {
712:                return instruction;
713:            }
714:
715:            /**
716:             * Get the number of declarations (and undeclarations) in this list.
717:             */
718:
719:            public int getLength() {
720:                return activeNamespaces.length + additionalNamespaces.size();
721:            }
722:
723:            /**
724:             * Get the prefix of the n'th declaration (or undeclaration) in the list,
725:             * counting from zero.
726:             *
727:             * @param index the index identifying which declaration is required.
728:             * @return the namespace prefix. For a declaration or undeclaration of the
729:             *         default namespace, this is the zero-length string.
730:             * @throws IndexOutOfBoundsException if the index is out of range.
731:             */
732:
733:            public String getPrefix(int index) {
734:                if (index < activeNamespaces.length) {
735:                    return getNamePool().getPrefixFromNamespaceCode(
736:                            activeNamespaces[index]);
737:                } else {
738:                    return ((NodeInfo) additionalNamespaces.get(index
739:                            - activeNamespaces.length)).getLocalPart();
740:                }
741:            }
742:
743:            /**
744:             * Get the namespace URI of the n'th declaration (or undeclaration) in the list,
745:             * counting from zero.
746:             *
747:             * @param index the index identifying which declaration is required.
748:             * @return the namespace URI. For a namespace undeclaration, this is the
749:             *         zero-length string.
750:             * @throws IndexOutOfBoundsException if the index is out of range.
751:             */
752:
753:            public String getURI(int index) {
754:                if (index < activeNamespaces.length) {
755:                    return getNamePool().getURIFromNamespaceCode(
756:                            activeNamespaces[index]);
757:                } else {
758:                    return ((NodeInfo) additionalNamespaces.get(index
759:                            - activeNamespaces.length)).getStringValue();
760:                }
761:            }
762:
763:            /**
764:             * Get the n'th declaration in the list in the form of a namespace code. Namespace
765:             * codes can be translated into a prefix and URI by means of methods in the
766:             * NamePool
767:             *
768:             * @param index the index identifying which declaration is required.
769:             * @return the namespace code. This is an integer whose upper half indicates
770:             *         the prefix (0 represents the default namespace), and whose lower half indicates
771:             *         the URI (0 represents an undeclaration).
772:             * @throws IndexOutOfBoundsException if the index is out of range.
773:             * @see net.sf.saxon.om.NamePool#getPrefixFromNamespaceCode(int)
774:             * @see net.sf.saxon.om.NamePool#getURIFromNamespaceCode(int)
775:             */
776:
777:            public int getNamespaceCode(int index) {
778:                if (index < activeNamespaces.length) {
779:                    return activeNamespaces[index];
780:                } else {
781:                    return getNamePool().allocateNamespaceCode(
782:                            getPrefix(index), getURI(index));
783:                }
784:            }
785:
786:            /**
787:             * Get all the namespace codes, as an array.
788:             *
789:             * @param buffer a sacrificial array that the method is free to use to contain the result.
790:             *               May be null.
791:             * @return an integer array containing namespace codes. The array may be filled completely
792:             *         with namespace codes, or it may be incompletely filled, in which case a -1 integer acts
793:             *         as a terminator.
794:             */
795:
796:            // TODO: not coded for efficiency!
797:            public int[] getNamespaceCodes(int[] buffer) {
798:                if (buffer.length < getLength()) {
799:                    buffer = new int[getLength()];
800:                } else {
801:                    buffer[getLength()] = -1;
802:                }
803:                for (int i = 0; i < getLength(); i++) {
804:                    buffer[i] = getNamespaceCode(i);
805:                }
806:                return buffer;
807:            }
808:
809:            private static final int[] EMPTY_INT_ARRAY = new int[0];
810:        }
811:
812:        //
813:        // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
814:        // you may not use this file except in compliance with the License. You may obtain a copy of the
815:        // License at http://www.mozilla.org/MPL/
816:        //
817:        // Software distributed under the License is distributed on an "AS IS" basis,
818:        // WITHOUT WARRANTY OF ANY KIND, either express or implied.
819:        // See the License for the specific language governing rights and limitations under the License.
820:        //
821:        // The Original Code is: all this file.
822:        //
823:        // The Initial Developer of the Original Code is Michael H. Kay.
824:        //
825:        // Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
826:        //
827:        // Contributor(s): none.
828:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.