KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > dom > SAXImpl


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 /*
17  * $Id: SAXImpl.java,v 1.19 2004/02/24 04:21:50 zongaro Exp $
18  */

19
20 package org.apache.xalan.xsltc.dom;
21
22 import java.net.URL JavaDoc;
23 import java.net.MalformedURLException JavaDoc;
24 import java.util.Enumeration JavaDoc;
25
26 import javax.xml.transform.Source JavaDoc;
27 import javax.xml.transform.dom.DOMSource JavaDoc;
28
29 import org.apache.xalan.xsltc.DOM;
30 import org.apache.xalan.xsltc.DOMEnhancedForDTM;
31 import org.apache.xalan.xsltc.StripFilter;
32 import org.apache.xalan.xsltc.TransletException;
33 import org.apache.xalan.xsltc.runtime.BasisLibrary;
34 import org.apache.xalan.xsltc.runtime.Hashtable;
35 import org.apache.xml.dtm.DTM;
36 import org.apache.xml.dtm.DTMAxisIterator;
37 import org.apache.xml.dtm.DTMManager;
38 import org.apache.xml.dtm.DTMWSFilter;
39 import org.apache.xml.dtm.ref.DTMAxisIterNodeList;
40 import org.apache.xml.dtm.ref.DTMDefaultBase;
41 import org.apache.xml.dtm.ref.EmptyIterator;
42 import org.apache.xml.dtm.ref.DTMNodeProxy;
43 import org.apache.xml.dtm.ref.sax2dtm.SAX2DTM2;
44 import org.apache.xml.serializer.SerializationHandler;
45 import org.apache.xml.serializer.ToXMLSAXHandler;
46 import org.apache.xml.utils.XMLStringFactory;
47 import org.apache.xml.utils.SystemIDResolver;
48 import org.w3c.dom.Node JavaDoc;
49 import org.w3c.dom.NodeList JavaDoc;
50 import org.w3c.dom.Document JavaDoc;
51 import org.w3c.dom.DocumentType JavaDoc;
52 import org.w3c.dom.NamedNodeMap JavaDoc;
53 import org.w3c.dom.Entity JavaDoc;
54
55 import org.xml.sax.Attributes JavaDoc;
56 import org.xml.sax.SAXException JavaDoc;
57
58
59 /**
60  * SAXImpl is the core model for SAX input source. SAXImpl objects are
61  * usually created from an XSLTCDTMManager.
62  *
63  * <p>DOMSource inputs are handled using DOM2SAX + SAXImpl. SAXImpl has a
64  * few specific fields (e.g. _node2Ids, _document) to keep DOM-related
65  * information. They are used when the processing behavior between DOM and
66  * SAX has to be different. Examples of these include id function and
67  * unparsed entity.
68  *
69  * <p>SAXImpl extends SAX2DTM2 instead of SAX2DTM for better performance.
70  * @author Jacek Ambroziak
71  * @author Santiago Pericas-Geertsen
72  * @author Morten Jorgensen
73  * @author Douglas Sellers <douglasjsellers@hotmail.com>
74  */

75 public final class SAXImpl extends SAX2DTM2
76                            implements DOMEnhancedForDTM, DOMBuilder
77 {
78     
79     /* ------------------------------------------------------------------- */
80     /* DOMBuilder fields BEGIN */
81     /* ------------------------------------------------------------------- */
82
83     // Namespace prefix-to-uri mapping stuff
84
private int _uriCount = 0;
85     private int _prefixCount = 0;
86
87     // Stack used to keep track of what whitespace text nodes are protected
88
// by xml:space="preserve" attributes and which nodes that are not.
89
private int[] _xmlSpaceStack;
90     private int _idx = 1;
91     private boolean _preserve = false;
92
93     private static final String JavaDoc XML_STRING = "xml:";
94     private static final String JavaDoc XML_PREFIX = "xml";
95     private static final String JavaDoc XMLSPACE_STRING = "xml:space";
96     private static final String JavaDoc PRESERVE_STRING = "preserve";
97     private static final String JavaDoc XMLNS_PREFIX = "xmlns";
98     private static final String JavaDoc XML_URI = "http://www.w3.org/XML/1998/namespace";
99
100     private boolean _escaping = true;
101     private boolean _disableEscaping = false;
102     private int _textNodeToProcess = DTM.NULL;
103
104     /* ------------------------------------------------------------------- */
105     /* DOMBuilder fields END */
106     /* ------------------------------------------------------------------- */
107
108     // empty String for null attribute values
109
private final static String JavaDoc EMPTYSTRING = "";
110
111     // empty iterator to be returned when there are no children
112
private final static DTMAxisIterator EMPTYITERATOR = EmptyIterator.getInstance();
113     // The number of expanded names
114
private int _namesSize = -1;
115
116     // Namespace related stuff
117
private Hashtable _nsIndex = new Hashtable();
118    
119     // The initial size of the text buffer
120
private int _size = 0;
121     
122     // Tracks which textnodes are not escaped
123
private BitArray _dontEscape = null;
124
125     // The URI to this document
126
private String JavaDoc _documentURI = null;
127     static private int _documentURIIndex = 0;
128
129     // The owner Document when the input source is DOMSource.
130
private Document JavaDoc _document;
131
132     // The hashtable for org.w3c.dom.Node to node id mapping.
133
// This is only used when the input is a DOMSource and the
134
// buildIdIndex flag is true.
135
private Hashtable _node2Ids = null;
136
137     // True if the input source is a DOMSource.
138
private boolean _hasDOMSource = false;
139
140     // The DTMManager
141
private XSLTCDTMManager _dtmManager;
142
143     // Support for access/navigation through org.w3c.dom API
144
private Node JavaDoc[] _nodes;
145     private NodeList[] _nodeLists;
146     private final static String JavaDoc XML_LANG_ATTRIBUTE =
147         "http://www.w3.org/XML/1998/namespace:@lang";
148
149     /**
150      * Define the origin of the document from which the tree was built
151      */

152     public void setDocumentURI(String JavaDoc uri) {
153         if (uri != null) {
154             setDocumentBaseURI(SystemIDResolver.getAbsoluteURI(uri));
155         }
156     }
157
158     /**
159      * Returns the origin of the document from which the tree was built
160      */

161     public String JavaDoc getDocumentURI() {
162         String JavaDoc baseURI = getDocumentBaseURI();
163         return (baseURI != null) ? baseURI : "rtf" + _documentURIIndex++;
164     }
165
166     public String JavaDoc getDocumentURI(int node) {
167         return getDocumentURI();
168     }
169
170     public void setupMapping(String JavaDoc[] names, String JavaDoc[] urisArray,
171                              int[] typesArray, String JavaDoc[] namespaces) {
172         // This method only has a function in DOM adapters
173
}
174
175     /**
176      * Lookup a namespace URI from a prefix starting at node. This method
177      * is used in the execution of xsl:element when the prefix is not known
178      * at compile time.
179      */

180     public String JavaDoc lookupNamespace(int node, String JavaDoc prefix)
181         throws TransletException
182     {
183         int anode, nsnode;
184         final AncestorIterator ancestors = new AncestorIterator();
185
186         if (isElement(node)) {
187             ancestors.includeSelf();
188         }
189
190         ancestors.setStartNode(node);
191         while ((anode = ancestors.next()) != DTM.NULL) {
192             final NamespaceIterator namespaces = new NamespaceIterator();
193
194             namespaces.setStartNode(anode);
195             while ((nsnode = namespaces.next()) != DTM.NULL) {
196                 if (getLocalName(nsnode).equals(prefix)) {
197                     return getNodeValue(nsnode);
198                 }
199             }
200         }
201
202         BasisLibrary.runTimeError(BasisLibrary.NAMESPACE_PREFIX_ERR, prefix);
203         return null;
204     }
205
206     /**
207      * Returns 'true' if a specific node is an element (of any type)
208      */

209     public boolean isElement(final int node) {
210         return getNodeType(node) == DTM.ELEMENT_NODE;
211     }
212
213     /**
214      * Returns 'true' if a specific node is an attribute (of any type)
215      */

216     public boolean isAttribute(final int node) {
217         return getNodeType(node) == DTM.ATTRIBUTE_NODE;
218     }
219
220     /**
221      * Returns the number of nodes in the tree (used for indexing)
222      */

223     public int getSize() {
224         return getNumberOfNodes();
225     }
226
227     /**
228      * Part of the DOM interface - no function here.
229      */

230     public void setFilter(StripFilter filter) {
231     }
232
233
234     /**
235      * Returns true if node1 comes before node2 in document order
236      */

237     public boolean lessThan(int node1, int node2) {
238         if (node1 == DTM.NULL) {
239             return false;
240         }
241
242         if (node2 == DTM.NULL) {
243             return true;
244         }
245
246         return (node1 < node2);
247     }
248
249     /**
250      * Create an org.w3c.dom.Node from a node in the tree
251      */

252     public Node JavaDoc makeNode(int index) {
253         if (_nodes == null) {
254             _nodes = new Node JavaDoc[_namesSize];
255         }
256
257         int nodeID = makeNodeIdentity(index);
258         if (nodeID < 0) {
259             return null;
260         }
261         else if (nodeID < _nodes.length) {
262             return (_nodes[nodeID] != null) ? _nodes[nodeID]
263                 : (_nodes[nodeID] = new DTMNodeProxy((DTM)this, index));
264         }
265         else {
266             return new DTMNodeProxy((DTM)this, index);
267         }
268     }
269
270     /**
271      * Create an org.w3c.dom.Node from a node in an iterator
272      * The iterator most be started before this method is called
273      */

274     public Node JavaDoc makeNode(DTMAxisIterator iter) {
275         return makeNode(iter.next());
276     }
277
278     /**
279      * Create an org.w3c.dom.NodeList from a node in the tree
280      */

281     public NodeList makeNodeList(int index) {
282         if (_nodeLists == null) {
283             _nodeLists = new NodeList[_namesSize];
284         }
285         
286         int nodeID = makeNodeIdentity(index);
287         if (nodeID < 0) {
288             return null;
289         }
290         else if (nodeID < _nodeLists.length) {
291             return (_nodeLists[nodeID] != null) ? _nodeLists[nodeID]
292                    : (_nodeLists[nodeID] = new DTMAxisIterNodeList(this,
293                                                  new SingletonIterator(index)));
294     }
295         else {
296             return new DTMAxisIterNodeList(this, new SingletonIterator(index));
297         }
298     }
299
300     /**
301      * Create an org.w3c.dom.NodeList from a node iterator
302      * The iterator most be started before this method is called
303      */

304     public NodeList makeNodeList(DTMAxisIterator iter) {
305         return new DTMAxisIterNodeList(this, iter);
306     }
307
308     /**
309      * Iterator that returns the namespace nodes as defined by the XPath data
310      * model for a given node, filtered by extended type ID.
311      */

312     public class TypedNamespaceIterator extends NamespaceIterator {
313         
314         private String JavaDoc _nsPrefix;
315
316         /**
317          * Constructor TypedChildrenIterator
318          *
319          *
320          * @param nodeType The extended type ID being requested.
321          */

322         public TypedNamespaceIterator(int nodeType) {
323             super();
324             if(m_expandedNameTable != null){
325                 _nsPrefix = m_expandedNameTable.getLocalName(nodeType);
326             }
327         }
328
329        /**
330         * Get the next node in the iteration.
331         *
332         * @return The next node handle in the iteration, or END.
333         */

334         public int next() {
335             if ((_nsPrefix == null) ||(_nsPrefix.length() == 0) ){
336                 return (END);
337             }
338             int node = END;
339             for (node = super.next(); node != END; node = super.next()) {
340                 if (_nsPrefix.compareTo(getLocalName(node))== 0) {
341                     return returnNode(node);
342                 }
343             }
344             return (END);
345         }
346     } // end of TypedNamespaceIterator
347

348
349
350     /**************************************************************
351      * This is a specialised iterator for predicates comparing node or
352      * attribute values to variable or parameter values.
353      */

354     private final class NodeValueIterator extends InternalAxisIteratorBase
355     {
356
357     private DTMAxisIterator _source;
358     private String JavaDoc _value;
359     private boolean _op;
360     private final boolean _isReverse;
361     private int _returnType = RETURN_PARENT;
362
363     public NodeValueIterator(DTMAxisIterator source, int returnType,
364                  String JavaDoc value, boolean op)
365         {
366         _source = source;
367         _returnType = returnType;
368         _value = value;
369         _op = op;
370         _isReverse = source.isReverse();
371     }
372
373     public boolean isReverse()
374         {
375         return _isReverse;
376     }
377
378         public DTMAxisIterator cloneIterator()
379         {
380             try {
381                 NodeValueIterator clone = (NodeValueIterator)super.clone();
382                 clone._isRestartable = false;
383                 clone._source = _source.cloneIterator();
384                 clone._value = _value;
385                 clone._op = _op;
386                 return clone.reset();
387             }
388             catch (CloneNotSupportedException JavaDoc e) {
389                 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
390                                           e.toString());
391                 return null;
392             }
393         }
394   
395         public void setRestartable(boolean isRestartable)
396         {
397         _isRestartable = isRestartable;
398         _source.setRestartable(isRestartable);
399     }
400
401     public DTMAxisIterator reset()
402         {
403         _source.reset();
404         return resetPosition();
405     }
406
407     public int next()
408         {
409             int node;
410             while ((node = _source.next()) != END) {
411                 String JavaDoc val = getStringValueX(node);
412                 if (_value.equals(val) == _op) {
413                     if (_returnType == RETURN_CURRENT) {
414                         return returnNode(node);
415                     }
416                     else {
417                         return returnNode(getParent(node));
418                     }
419                 }
420             }
421             return END;
422         }
423
424     public DTMAxisIterator setStartNode(int node)
425         {
426             if (_isRestartable) {
427                 _source.setStartNode(_startNode = node);
428                 return resetPosition();
429             }
430             return this;
431         }
432
433     public void setMark()
434         {
435         _source.setMark();
436     }
437
438     public void gotoMark()
439         {
440         _source.gotoMark();
441     }
442     } // end NodeValueIterator
443

444     public DTMAxisIterator getNodeValueIterator(DTMAxisIterator iterator, int type,
445                          String JavaDoc value, boolean op)
446     {
447         return(DTMAxisIterator)(new NodeValueIterator(iterator, type, value, op));
448     }
449
450     /**
451      * Encapsulates an iterator in an OrderedIterator to ensure node order
452      */

453     public DTMAxisIterator orderNodes(DTMAxisIterator source, int node)
454     {
455         return new DupFilterIterator(source);
456     }
457
458     /**
459      * Returns singleton iterator containg the document root
460      * Works for them main document (mark == 0)
461      */

462     public DTMAxisIterator getIterator()
463     {
464         return new SingletonIterator(getDocument());
465     }
466
467      /**
468      * Get mapping from DOM namespace types to external namespace types
469      */

470     public int getNSType(int node)
471     {
472         String JavaDoc s = getNamespaceURI(node);
473         if (s == null) {
474             return 0;
475         }
476         int eType = getIdForNamespace(s);
477         return ((Integer JavaDoc)_nsIndex.get(new Integer JavaDoc(eType))).intValue();
478     }
479     
480     
481
482     /**
483      * Returns the namespace type of a specific node
484      */

485     public int getNamespaceType(final int node)
486     {
487         return super.getNamespaceType(node);
488     }
489
490     /**
491      * Sets up a translet-to-dom type mapping table
492      */

493     private int[] setupMapping(String JavaDoc[] names, String JavaDoc[] uris, int[] types, int nNames) {
494         // Padding with number of names, because they
495
// may need to be added, i.e for RTFs. See copy03
496
final int[] result = new int[m_expandedNameTable.getSize()];
497         for (int i = 0; i < nNames; i++) {
498             //int type = getGeneralizedType(namesArray[i]);
499
int type = m_expandedNameTable.getExpandedTypeID(uris[i], names[i], types[i], false);
500             result[type] = type;
501         }
502         return result;
503     }
504
505     /**
506      * Returns the internal type associated with an expanded QName
507      */

508     public int getGeneralizedType(final String JavaDoc name) {
509         return getGeneralizedType(name, true);
510     }
511
512     /**
513      * Returns the internal type associated with an expanded QName
514      */

515     public int getGeneralizedType(final String JavaDoc name, boolean searchOnly) {
516         String JavaDoc lName, ns = null;
517         int index = -1;
518         int code;
519
520         // Is there a prefix?
521
if ((index = name.lastIndexOf(":"))> -1) {
522             ns = name.substring(0, index);
523         }
524
525         // Local part of name is after colon. lastIndexOf returns -1 if
526
// there is no colon, so lNameStartIdx will be zero in that case.
527
int lNameStartIdx = index+1;
528
529         // Distinguish attribute and element names. Attribute has @ before
530
// local part of name.
531
if (name.charAt(lNameStartIdx) == '@') {
532             code = DTM.ATTRIBUTE_NODE;
533             lNameStartIdx++;
534         }
535         else {
536             code = DTM.ELEMENT_NODE;
537         }
538
539         // Extract local name
540
lName = (lNameStartIdx == 0) ? name : name.substring(lNameStartIdx);
541
542         return m_expandedNameTable.getExpandedTypeID(ns, lName, code, searchOnly);
543     }
544
545     /**
546      * Get mapping from DOM element/attribute types to external types
547      */

548     public short[] getMapping(String JavaDoc[] names, String JavaDoc[] uris, int[] types)
549     {
550         // Delegate the work to getMapping2 if the document is not fully built.
551
// Some of the processing has to be different in this case.
552
if (_namesSize < 0) {
553             return getMapping2(names, uris, types);
554         }
555
556         int i;
557         final int namesLength = names.length;
558         final int exLength = m_expandedNameTable.getSize();
559       
560         final short[] result = new short[exLength];
561
562         // primitive types map to themselves
563
for (i = 0; i < DTM.NTYPES; i++) {
564             result[i] = (short)i;
565         }
566         
567         for (i = NTYPES; i < exLength; i++) {
568             result[i] = m_expandedNameTable.getType(i);
569         }
570         
571         // actual mapping of caller requested names
572
for (i = 0; i < namesLength; i++) {
573             int genType = m_expandedNameTable.getExpandedTypeID(uris[i],
574                                                                 names[i],
575                                                                 types[i],
576                                                                 true);
577             if (genType >= 0 && genType < exLength) {
578                 result[genType] = (short)(i + DTM.NTYPES);
579             }
580         }
581
582         return result;
583     }
584
585     /**
586      * Get mapping from external element/attribute types to DOM types
587      */

588     public int[] getReverseMapping(String JavaDoc[] names, String JavaDoc[] uris, int[] types)
589     {
590         int i;
591         final int[] result = new int[names.length + DTM.NTYPES];
592         
593         // primitive types map to themselves
594
for (i = 0; i < DTM.NTYPES; i++) {
595             result[i] = i;
596         }
597         
598         // caller's types map into appropriate dom types
599
for (i = 0; i < names.length; i++) {
600             int type = m_expandedNameTable.getExpandedTypeID(uris[i], names[i], types[i], true);
601             result[i+DTM.NTYPES] = type;
602         }
603         return(result);
604     }
605     
606     /**
607      * Get mapping from DOM element/attribute types to external types.
608      * This method is used when the document is not fully built.
609      */

610     private short[] getMapping2(String JavaDoc[] names, String JavaDoc[] uris, int[] types)
611     {
612         int i;
613         final int namesLength = names.length;
614         final int exLength = m_expandedNameTable.getSize();
615         int[] generalizedTypes = null;
616         if (namesLength > 0) {
617             generalizedTypes = new int[namesLength];
618         }
619
620         int resultLength = exLength;
621
622         for (i = 0; i < namesLength; i++) {
623             // When the document is not fully built, the searchOnly
624
// flag should be set to false. That means we should add
625
// the type if it is not already in the expanded name table.
626
//generalizedTypes[i] = getGeneralizedType(names[i], false);
627
generalizedTypes[i] =
628                 m_expandedNameTable.getExpandedTypeID(uris[i],
629                                                       names[i],
630                                                       types[i],
631                                                       false);
632             if (_namesSize < 0 && generalizedTypes[i] >= resultLength) {
633                 resultLength = generalizedTypes[i] + 1;
634             }
635         }
636
637         final short[] result = new short[resultLength];
638
639         // primitive types map to themselves
640
for (i = 0; i < DTM.NTYPES; i++) {
641             result[i] = (short)i;
642         }
643
644         for (i = NTYPES; i < exLength; i++) {
645             result[i] = m_expandedNameTable.getType(i);
646         }
647
648         // actual mapping of caller requested names
649
for (i = 0; i < namesLength; i++) {
650             int genType = generalizedTypes[i];
651             if (genType >= 0 && genType < resultLength) {
652                 result[genType] = (short)(i + DTM.NTYPES);
653             }
654         }
655
656         return(result);
657     }
658     /**
659      * Get mapping from DOM namespace types to external namespace types
660      */

661     public short[] getNamespaceMapping(String JavaDoc[] namespaces)
662     {
663         int i;
664         final int nsLength = namespaces.length;
665         final int mappingLength = _uriCount;
666
667         final short[] result = new short[mappingLength];
668
669         // Initialize all entries to -1
670
for (i=0; i<mappingLength; i++) {
671             result[i] = (short)(-1);
672         }
673
674         for (i=0; i<nsLength; i++) {
675             int eType = getIdForNamespace(namespaces[i]);
676             Integer JavaDoc type = (Integer JavaDoc)_nsIndex.get(new Integer JavaDoc(eType));
677             if (type != null) {
678                 result[type.intValue()] = (short)i;
679             }
680         }
681
682         return(result);
683     }
684
685     /**
686      * Get mapping from external namespace types to DOM namespace types
687      */

688     public short[] getReverseNamespaceMapping(String JavaDoc[] namespaces)
689     {
690         int i;
691         final int length = namespaces.length;
692         final short[] result = new short[length];
693
694         for (i = 0; i < length; i++) {
695             int eType = getIdForNamespace(namespaces[i]);
696             Integer JavaDoc type = (Integer JavaDoc)_nsIndex.get(new Integer JavaDoc(eType));
697             result[i] = (type == null) ? -1 : type.shortValue();
698         }
699
700         return result;
701     }
702
703     /**
704      * Construct a SAXImpl object using the default block size.
705      */

706     public SAXImpl(XSLTCDTMManager mgr, Source JavaDoc source,
707                    int dtmIdentity, DTMWSFilter whiteSpaceFilter,
708                    XMLStringFactory xstringfactory,
709                    boolean doIndexing, boolean buildIdIndex)
710     {
711         this(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
712             doIndexing, DEFAULT_BLOCKSIZE, buildIdIndex, false);
713     }
714     
715     /**
716      * Construct a SAXImpl object using the given block size.
717      */

718     public SAXImpl(XSLTCDTMManager mgr, Source JavaDoc source,
719                    int dtmIdentity, DTMWSFilter whiteSpaceFilter,
720                    XMLStringFactory xstringfactory,
721                    boolean doIndexing, int blocksize,
722                    boolean buildIdIndex,
723                    boolean newNameTable)
724     {
725         super(mgr, source, dtmIdentity, whiteSpaceFilter, xstringfactory,
726             doIndexing, blocksize, false, buildIdIndex, newNameTable);
727       
728         _dtmManager = mgr;
729         _size = blocksize;
730       
731         // Use a smaller size for the space stack if the blocksize is small
732
_xmlSpaceStack = new int[blocksize <= 64 ? 4 : 64];
733                                   
734         /* From DOMBuilder */
735         _xmlSpaceStack[0] = DTMDefaultBase.ROOTNODE;
736       
737         // If the input source is DOMSource, set the _document field and
738
// create the node2Ids table.
739
if (source instanceof DOMSource JavaDoc) {
740             _hasDOMSource = true;
741             DOMSource JavaDoc domsrc = (DOMSource JavaDoc)source;
742             Node JavaDoc node = domsrc.getNode();
743             if (node instanceof Document JavaDoc) {
744                 _document = (Document JavaDoc)node;
745             }
746             else {
747                 _document = node.getOwnerDocument();
748             }
749             _node2Ids = new Hashtable();
750         }
751     }
752         
753     /**
754     * Migrate a DTM built with an old DTMManager to a new DTMManager.
755     * After the migration, the new DTMManager will treat the DTM as
756     * one that is built by itself.
757     * This is used to support DTM sharing between multiple transformations.
758     * @param manager the DTMManager
759     */

760     public void migrateTo(DTMManager manager) {
761         super.migrateTo(manager);
762         if (manager instanceof XSLTCDTMManager) {
763             _dtmManager = (XSLTCDTMManager)manager;
764         }
765     }
766         
767     /**
768      * Return the node identity for a given id String
769      *
770      * @param idString The id String
771      * @return The identity of the node whose id is the given String.
772      */

773     public int getElementById(String JavaDoc idString)
774     {
775         Node JavaDoc node = _document.getElementById(idString);
776         if (node != null) {
777             Integer JavaDoc id = (Integer JavaDoc)_node2Ids.get(node);
778             return (id != null) ? id.intValue() : DTM.NULL;
779         }
780         else {
781             return DTM.NULL;
782         }
783     }
784     
785     /**
786      * Return true if the input source is DOMSource.
787      */

788     public boolean hasDOMSource()
789     {
790         return _hasDOMSource;
791     }
792
793     /*---------------------------------------------------------------------------*/
794     /* DOMBuilder methods begin */
795     /*---------------------------------------------------------------------------*/
796     
797     /**
798      * Call this when an xml:space attribute is encountered to
799      * define the whitespace strip/preserve settings.
800      */

801     private void xmlSpaceDefine(String JavaDoc val, final int node)
802     {
803         final boolean setting = val.equals(PRESERVE_STRING);
804         if (setting != _preserve) {
805             _xmlSpaceStack[_idx++] = node;
806             _preserve = setting;
807         }
808     }
809
810     /**
811      * Call this from endElement() to revert strip/preserve setting
812      * to whatever it was before the corresponding startElement().
813      */

814     private void xmlSpaceRevert(final int node)
815     {
816         if (node == _xmlSpaceStack[_idx - 1]) {
817             _idx--;
818             _preserve = !_preserve;
819         }
820     }
821
822     /**
823      * Find out whether or not to strip whitespace nodes.
824      *
825      *
826      * @return whether or not to strip whitespace nodes.
827      */

828     protected boolean getShouldStripWhitespace()
829     {
830         return _preserve ? false : super.getShouldStripWhitespace();
831     }
832
833     /**
834      * Creates a text-node and checks if it is a whitespace node.
835      */

836     private void handleTextEscaping() {
837         if (_disableEscaping && _textNodeToProcess != DTM.NULL
838             && _type(_textNodeToProcess) == DTM.TEXT_NODE) {
839             if (_dontEscape == null) {
840                 _dontEscape = new BitArray(_size);
841             }
842           
843             // Resize the _dontEscape BitArray if necessary.
844
if (_textNodeToProcess >= _dontEscape.size()) {
845                 _dontEscape.resize(_dontEscape.size() * 2);
846             }
847           
848             _dontEscape.setBit(_textNodeToProcess);
849             _disableEscaping = false;
850         }
851         _textNodeToProcess = DTM.NULL;
852     }
853
854
855     /****************************************************************/
856     /* SAX Interface Starts Here */
857     /****************************************************************/
858
859     /**
860      * SAX2: Receive notification of character data.
861      */

862     public void characters(char[] ch, int start, int length) throws SAXException JavaDoc
863     {
864         super.characters(ch, start, length);
865         
866         _disableEscaping = !_escaping;
867         _textNodeToProcess = getNumberOfNodes();
868     }
869
870     /**
871      * SAX2: Receive notification of the beginning of a document.
872      */

873     public void startDocument() throws SAXException JavaDoc
874     {
875         super.startDocument();
876
877         _nsIndex.put(new Integer JavaDoc(0), new Integer JavaDoc(_uriCount++));
878         definePrefixAndUri(XML_PREFIX, XML_URI);
879     }
880
881     /**
882      * SAX2: Receive notification of the end of a document.
883      */

884     public void endDocument() throws SAXException JavaDoc
885     {
886         super.endDocument();
887         
888         handleTextEscaping();
889         _namesSize = m_expandedNameTable.getSize();
890     }
891
892     /**
893      * Specialized interface used by DOM2SAX. This one has an extra Node
894      * parameter to build the Node -> id map.
895      */

896     public void startElement(String JavaDoc uri, String JavaDoc localName,
897                              String JavaDoc qname, Attributes JavaDoc attributes,
898                              Node JavaDoc node)
899         throws SAXException JavaDoc
900     {
901         this.startElement(uri, localName, qname, attributes);
902         
903         if (m_buildIdIndex) {
904             _node2Ids.put(node, new Integer JavaDoc(m_parents.peek()));
905         }
906     }
907     
908     /**
909      * SAX2: Receive notification of the beginning of an element.
910      */

911     public void startElement(String JavaDoc uri, String JavaDoc localName,
912                  String JavaDoc qname, Attributes JavaDoc attributes)
913         throws SAXException JavaDoc
914     {
915         super.startElement(uri, localName, qname, attributes);
916         
917         handleTextEscaping();
918
919         if (m_wsfilter != null) {
920             // Look for any xml:space attributes
921
// Depending on the implementation of attributes, this
922
// might be faster than looping through all attributes. ILENE
923
final int index = attributes.getIndex(XMLSPACE_STRING);
924             if (index >= 0) {
925                 xmlSpaceDefine(attributes.getValue(index), m_parents.peek());
926             }
927         }
928     }
929
930     /**
931      * SAX2: Receive notification of the end of an element.
932      */

933     public void endElement(String JavaDoc namespaceURI, String JavaDoc localName, String JavaDoc qname)
934         throws SAXException JavaDoc
935     {
936         super.endElement(namespaceURI, localName, qname);
937         
938         handleTextEscaping();
939
940         // Revert to strip/preserve-space setting from before this element
941
if (m_wsfilter != null) {
942             xmlSpaceRevert(m_previous);
943         }
944     }
945
946     /**
947      * SAX2: Receive notification of a processing instruction.
948      */

949     public void processingInstruction(String JavaDoc target, String JavaDoc data)
950         throws SAXException JavaDoc
951     {
952         super.processingInstruction(target, data);
953         handleTextEscaping();
954     }
955
956     /**
957      * SAX2: Receive notification of ignorable whitespace in element
958      * content. Similar to characters(char[], int, int).
959      */

960     public void ignorableWhitespace(char[] ch, int start, int length)
961         throws SAXException JavaDoc
962     {
963         super.ignorableWhitespace(ch, start, length);
964         _textNodeToProcess = getNumberOfNodes();
965     }
966
967     /**
968      * SAX2: Begin the scope of a prefix-URI Namespace mapping.
969      */

970     public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
971         throws SAXException JavaDoc
972     {
973         super.startPrefixMapping(prefix, uri);
974         handleTextEscaping();
975
976         definePrefixAndUri(prefix, uri);
977     }
978
979     private void definePrefixAndUri(String JavaDoc prefix, String JavaDoc uri)
980         throws SAXException JavaDoc
981     {
982         // Check if the URI already exists before pushing on stack
983
Integer JavaDoc eType = new Integer JavaDoc(getIdForNamespace(uri));
984         if ((Integer JavaDoc)_nsIndex.get(eType) == null) {
985             _nsIndex.put(eType, new Integer JavaDoc(_uriCount++));
986         }
987     }
988  
989     /**
990      * SAX2: Report an XML comment anywhere in the document.
991      */

992     public void comment(char[] ch, int start, int length)
993         throws SAXException JavaDoc
994     {
995         super.comment(ch, start, length);
996         handleTextEscaping();
997     }
998
999     public boolean setEscaping(boolean value) {
1000        final boolean temp = _escaping;
1001        _escaping = value;
1002        return temp;
1003    }
1004   
1005   /*---------------------------------------------------------------------------*/
1006   /* DOMBuilder methods end */
1007   /*---------------------------------------------------------------------------*/
1008
1009    /**
1010     * Prints the whole tree to standard output
1011     */

1012    public void print(int node, int level)
1013    {
1014        switch(getNodeType(node))
1015        {
1016        case DTM.ROOT_NODE:
1017        case DTM.DOCUMENT_NODE:
1018            print(getFirstChild(node), level);
1019            break;
1020        case DTM.TEXT_NODE:
1021        case DTM.COMMENT_NODE:
1022        case DTM.PROCESSING_INSTRUCTION_NODE:
1023            System.out.print(getStringValueX(node));
1024            break;
1025        default:
1026            final String JavaDoc name = getNodeName(node);
1027            System.out.print("<" + name);
1028            for (int a = getFirstAttribute(node); a != DTM.NULL; a = getNextAttribute(a))
1029                {
1030            System.out.print("\n" + getNodeName(a) + "=\"" + getStringValueX(a) + "\"");
1031            }
1032            System.out.print('>');
1033            for (int child = getFirstChild(node); child != DTM.NULL;
1034            child = getNextSibling(child)) {
1035            print(child, level + 1);
1036            }
1037            System.out.println("</" + name + '>');
1038            break;
1039    }
1040    }
1041
1042    /**
1043     * Returns the name of a node (attribute or element).
1044     */

1045    public String JavaDoc getNodeName(final int node)
1046    {
1047    // Get the node type and make sure that it is within limits
1048
int nodeh = node;
1049    final short type = getNodeType(nodeh);
1050    switch(type)
1051        {
1052        case DTM.ROOT_NODE:
1053        case DTM.DOCUMENT_NODE:
1054        case DTM.TEXT_NODE:
1055        case DTM.COMMENT_NODE:
1056            return EMPTYSTRING;
1057        case DTM.NAMESPACE_NODE:
1058        return this.getLocalName(nodeh);
1059        default:
1060            return super.getNodeName(nodeh);
1061    }
1062    }
1063
1064    /**
1065     * Returns the namespace URI to which a node belongs
1066     */

1067    public String JavaDoc getNamespaceName(final int node)
1068    {
1069        if (node == DTM.NULL) {
1070            return "";
1071        }
1072        
1073        String JavaDoc s;
1074        return (s = getNamespaceURI(node)) == null ? EMPTYSTRING : s;
1075    }
1076
1077 
1078    /**
1079     * Returns the attribute node of a given type (if any) for an element
1080     */

1081    public int getAttributeNode(final int type, final int element)
1082    {
1083        for (int attr = getFirstAttribute(element);
1084           attr != DTM.NULL;
1085           attr = getNextAttribute(attr))
1086        {
1087            if (getExpandedTypeID(attr) == type) return attr;
1088        }
1089        return DTM.NULL;
1090    }
1091
1092    /**
1093     * Returns the value of a given attribute type of a given element
1094     */

1095    public String JavaDoc getAttributeValue(final int type, final int element)
1096    {
1097        final int attr = getAttributeNode(type, element);
1098        return (attr != DTM.NULL) ? getStringValueX(attr) : EMPTYSTRING;
1099    }
1100
1101    /**
1102     * This method is for testing/debugging only
1103     */

1104    public String JavaDoc getAttributeValue(final String JavaDoc name, final int element)
1105    {
1106        return getAttributeValue(getGeneralizedType(name), element);
1107    }
1108
1109    /**
1110     * Returns an iterator with all the children of a given node
1111     */

1112    public DTMAxisIterator getChildren(final int node)
1113    {
1114        return (new ChildrenIterator()).setStartNode(node);
1115    }
1116
1117    /**
1118     * Returns an iterator with all children of a specific type
1119     * for a given node (element)
1120     */

1121    public DTMAxisIterator getTypedChildren(final int type)
1122    {
1123        return(new TypedChildrenIterator(type));
1124    }
1125
1126    /**
1127     * This is a shortcut to the iterators that implement the
1128     * supported XPath axes (only namespace::) is not supported.
1129     * Returns a bare-bones iterator that must be initialized
1130     * with a start node (using iterator.setStartNode()).
1131     */

1132    public DTMAxisIterator getAxisIterator(final int axis)
1133    {
1134        switch (axis)
1135        {
1136            case Axis.SELF:
1137                return new SingletonIterator();
1138            case Axis.CHILD:
1139                return new ChildrenIterator();
1140            case Axis.PARENT:
1141                return new ParentIterator();
1142            case Axis.ANCESTOR:
1143                return new AncestorIterator();
1144            case Axis.ANCESTORORSELF:
1145                return (new AncestorIterator()).includeSelf();
1146            case Axis.ATTRIBUTE:
1147                return new AttributeIterator();
1148            case Axis.DESCENDANT:
1149                return new DescendantIterator();
1150            case Axis.DESCENDANTORSELF:
1151                return (new DescendantIterator()).includeSelf();
1152            case Axis.FOLLOWING:
1153                return new FollowingIterator();
1154            case Axis.PRECEDING:
1155                return new PrecedingIterator();
1156            case Axis.FOLLOWINGSIBLING:
1157                return new FollowingSiblingIterator();
1158            case Axis.PRECEDINGSIBLING:
1159                return new PrecedingSiblingIterator();
1160            case Axis.NAMESPACE:
1161                return new NamespaceIterator();
1162            default:
1163                BasisLibrary.runTimeError(BasisLibrary.AXIS_SUPPORT_ERR, Axis.names[axis]);
1164        }
1165        return null;
1166    }
1167
1168    /**
1169     * Similar to getAxisIterator, but this one returns an iterator
1170     * containing nodes of a typed axis (ex.: child::foo)
1171     */

1172    public DTMAxisIterator getTypedAxisIterator(int axis, int type)
1173    {
1174        // Most common case handled first
1175
if (axis == Axis.CHILD) {
1176            return new TypedChildrenIterator(type);
1177        }
1178
1179        if (type == NO_TYPE) {
1180            return(EMPTYITERATOR);
1181        }
1182
1183        switch (axis)
1184        {
1185            case Axis.SELF:
1186                return new TypedSingletonIterator(type);
1187            case Axis.CHILD:
1188                return new TypedChildrenIterator(type);
1189            case Axis.PARENT:
1190                return new ParentIterator().setNodeType(type);
1191            case Axis.ANCESTOR:
1192                return new TypedAncestorIterator(type);
1193            case Axis.ANCESTORORSELF:
1194                return (new TypedAncestorIterator(type)).includeSelf();
1195            case Axis.ATTRIBUTE:
1196                return new TypedAttributeIterator(type);
1197            case Axis.DESCENDANT:
1198                return new TypedDescendantIterator(type);
1199            case Axis.DESCENDANTORSELF:
1200                return (new TypedDescendantIterator(type)).includeSelf();
1201            case Axis.FOLLOWING:
1202                return new TypedFollowingIterator(type);
1203            case Axis.PRECEDING:
1204                return new TypedPrecedingIterator(type);
1205            case Axis.FOLLOWINGSIBLING:
1206                return new TypedFollowingSiblingIterator(type);
1207            case Axis.PRECEDINGSIBLING:
1208                return new TypedPrecedingSiblingIterator(type);
1209            case Axis.NAMESPACE:
1210                return new TypedNamespaceIterator(type);
1211            default:
1212                BasisLibrary.runTimeError(BasisLibrary.TYPED_AXIS_SUPPORT_ERR, Axis.names[axis]);
1213        }
1214        return null;
1215    }
1216
1217    /**
1218     * Do not think that this returns an iterator for the namespace axis.
1219     * It returns an iterator with nodes that belong in a certain namespace,
1220     * such as with <xsl:apply-templates select="blob/foo:*"/>
1221     * The 'axis' specifies the axis for the base iterator from which the
1222     * nodes are taken, while 'ns' specifies the namespace URI type.
1223     */

1224    public DTMAxisIterator getNamespaceAxisIterator(int axis, int ns)
1225    {
1226
1227        DTMAxisIterator iterator = null;
1228
1229        if (ns == NO_TYPE) {
1230            return EMPTYITERATOR;
1231        }
1232        else {
1233            switch (axis) {
1234                case Axis.CHILD:
1235                    return new NamespaceChildrenIterator(ns);
1236                case Axis.ATTRIBUTE:
1237                    return new NamespaceAttributeIterator(ns);
1238                default:
1239                    return new NamespaceWildcardIterator(axis, ns);
1240            }
1241        }
1242    }
1243
1244    /**
1245     * Iterator that handles node tests that test for a namespace, but have
1246     * a wild card for the local name of the node, i.e., node tests of the
1247     * form <axis>::<prefix>:*
1248     */

1249    public final class NamespaceWildcardIterator
1250        extends InternalAxisIteratorBase
1251    {
1252        /**
1253         * The namespace type index.
1254         */

1255        protected int m_nsType;
1256
1257        /**
1258         * A nested typed axis iterator that retrieves nodes of the principal
1259         * node kind for that axis.
1260         */

1261        protected DTMAxisIterator m_baseIterator;
1262
1263        /**
1264         * Constructor NamespaceWildcard
1265         *
1266         * @param axis The axis that this iterator will traverse
1267         * @param nsType The namespace type index
1268         */

1269        public NamespaceWildcardIterator(int axis, int nsType) {
1270            m_nsType = nsType;
1271
1272            // Create a nested iterator that will select nodes of
1273
// the principal node kind for the selected axis.
1274
switch (axis) {
1275                case Axis.ATTRIBUTE: {
1276                    // For "attribute::p:*", the principal node kind is
1277
// attribute
1278
m_baseIterator = getAxisIterator(axis);
1279                }
1280                case Axis.NAMESPACE: {
1281                    // This covers "namespace::p:*". It is syntactically
1282
// correct, though it doesn't make much sense.
1283
m_baseIterator = getAxisIterator(axis);
1284                }
1285                default: {
1286                    // In all other cases, the principal node kind is
1287
// element
1288
m_baseIterator = getTypedAxisIterator(axis,
1289                                                          DTM.ELEMENT_NODE);
1290                }
1291            }
1292        }
1293
1294        /**
1295         * Set start to END should 'close' the iterator,
1296         * i.e. subsequent call to next() should return END.
1297         *
1298         * @param node Sets the root of the iteration.
1299         *
1300         * @return A DTMAxisIterator set to the start of the iteration.
1301         */

1302        public DTMAxisIterator setStartNode(int node) {
1303            if (_isRestartable) {
1304                _startNode = node;
1305                m_baseIterator.setStartNode(node);
1306                resetPosition();
1307            }
1308            return this;
1309        }
1310
1311        /**
1312         * Get the next node in the iteration.
1313         *
1314         * @return The next node handle in the iteration, or END.
1315         */

1316        public int next() {
1317            int node;
1318
1319            while ((node = m_baseIterator.next()) != END) {
1320                // Return only nodes that are in the selected namespace
1321
if (getNSType(node) == m_nsType) {
1322                    return returnNode(node);
1323                }
1324            }
1325
1326            return END;
1327        }
1328
1329        /**
1330         * Returns a deep copy of this iterator. The cloned iterator is not
1331         * reset.
1332         *
1333         * @return a deep copy of this iterator.
1334         */

1335        public DTMAxisIterator cloneIterator() {
1336            try {
1337                DTMAxisIterator nestedClone = m_baseIterator.cloneIterator();
1338                NamespaceWildcardIterator clone =
1339                    (NamespaceWildcardIterator) super.clone();
1340
1341                clone.m_baseIterator = nestedClone;
1342                clone.m_nsType = m_nsType;
1343                clone._isRestartable = false;
1344
1345                return clone;
1346            } catch (CloneNotSupportedException JavaDoc e) {
1347                BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
1348                                          e.toString());
1349                return null;
1350            }
1351        }
1352
1353        /**
1354         * True if this iterator has a reversed axis.
1355         *
1356         * @return <code>true</code> if this iterator is a reversed axis.
1357         */

1358        public boolean isReverse() {
1359            return m_baseIterator.isReverse();
1360        }
1361
1362        public void setMark() {
1363            m_baseIterator.setMark();
1364        }
1365
1366        public void gotoMark() {
1367            m_baseIterator.gotoMark();
1368        }
1369    }
1370
1371    /**
1372     * Iterator that returns children within a given namespace for a
1373     * given node. The functionality chould be achieved by putting a
1374     * filter on top of a basic child iterator, but a specialised
1375     * iterator is used for efficiency (both speed and size of translet).
1376     */

1377    public final class NamespaceChildrenIterator
1378        extends InternalAxisIteratorBase
1379    {
1380
1381        /** The extended type ID being requested. */
1382        private final int _nsType;
1383
1384        /**
1385         * Constructor NamespaceChildrenIterator
1386         *
1387         *
1388         * @param type The extended type ID being requested.
1389         */

1390        public NamespaceChildrenIterator(final int type) {
1391            _nsType = type;
1392        }
1393
1394        /**
1395         * Set start to END should 'close' the iterator,
1396         * i.e. subsequent call to next() should return END.
1397         *
1398         * @param node Sets the root of the iteration.
1399         *
1400         * @return A DTMAxisIterator set to the start of the iteration.
1401         */

1402        public DTMAxisIterator setStartNode(int node) {
1403            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1404
if (node == DTMDefaultBase.ROOTNODE) {
1405                node = getDocument();
1406            }
1407
1408            if (_isRestartable) {
1409                _startNode = node;
1410                _currentNode = (node == DTM.NULL) ? DTM.NULL : NOTPROCESSED;
1411
1412                return resetPosition();
1413            }
1414
1415            return this;
1416        }
1417
1418        /**
1419         * Get the next node in the iteration.
1420         *
1421         * @return The next node handle in the iteration, or END.
1422         */

1423        public int next() {
1424            if (_currentNode != DTM.NULL) {
1425                for (int node = (NOTPROCESSED == _currentNode)
1426                                     ? _firstch(makeNodeIdentity(_startNode))
1427                                     : _nextsib(_currentNode);
1428                     node != END;
1429                     node = _nextsib(node)) {
1430                    int nodeHandle = makeNodeHandle(node);
1431
1432                    if (getNSType(nodeHandle) == _nsType) {
1433                        _currentNode = node;
1434
1435                        return returnNode(nodeHandle);
1436                    }
1437                }
1438            }
1439
1440            return END;
1441        }
1442    } // end of NamespaceChildrenIterator
1443

1444    /**
1445     * Iterator that returns attributes within a given namespace for a node.
1446     */

1447    public final class NamespaceAttributeIterator
1448            extends InternalAxisIteratorBase
1449    {
1450
1451        /** The extended type ID being requested. */
1452        private final int _nsType;
1453
1454        /**
1455         * Constructor NamespaceAttributeIterator
1456         *
1457         *
1458         * @param nsType The extended type ID being requested.
1459         */

1460        public NamespaceAttributeIterator(int nsType) {
1461            super();
1462
1463            _nsType = nsType;
1464        }
1465
1466        /**
1467         * Set start to END should 'close' the iterator,
1468         * i.e. subsequent call to next() should return END.
1469         *
1470         * @param node Sets the root of the iteration.
1471         *
1472         * @return A DTMAxisIterator set to the start of the iteration.
1473         */

1474        public DTMAxisIterator setStartNode(int node) {
1475            //%HZ%: Added reference to DTMDefaultBase.ROOTNODE back in, temporarily
1476
if (node == DTMDefaultBase.ROOTNODE) {
1477                node = getDocument();
1478            }
1479
1480            if (_isRestartable) {
1481                int nsType = _nsType;
1482
1483                _startNode = node;
1484
1485                for (node = getFirstAttribute(node);
1486                     node != END;
1487                     node = getNextAttribute(node)) {
1488                    if (getNSType(node) == nsType) {
1489                        break;
1490                    }
1491                }
1492
1493                _currentNode = node;
1494                return resetPosition();
1495            }
1496
1497            return this;
1498        }
1499
1500        /**
1501         * Get the next node in the iteration.
1502         *
1503         * @return The next node handle in the iteration, or END.
1504         */

1505        public int next() {
1506            int node = _currentNode;
1507            int nsType = _nsType;
1508            int nextNode;
1509
1510            if (node == END) {
1511                return END;
1512            }
1513
1514            for (nextNode = getNextAttribute(node);
1515                 nextNode != END;
1516                 nextNode = getNextAttribute(nextNode)) {
1517                if (getNSType(nextNode) == nsType) {
1518                    break;
1519                }
1520            }
1521
1522            _currentNode = nextNode;
1523
1524            return returnNode(node);
1525        }
1526    } // end of NamespaceAttributeIterator
1527

1528    /**
1529     * Returns an iterator with all descendants of a node that are of
1530     * a given type.
1531     */

1532    public DTMAxisIterator getTypedDescendantIterator(int type)
1533    {
1534        return new TypedDescendantIterator(type);
1535    }
1536
1537    /**
1538     * Returns the nth descendant of a node
1539     */

1540    public DTMAxisIterator getNthDescendant(int type, int n, boolean includeself)
1541    {
1542        DTMAxisIterator source = (DTMAxisIterator) new TypedDescendantIterator(type);
1543        return new NthDescendantIterator(n);
1544    }
1545
1546    /**
1547     * Copy the string value of a node directly to an output handler
1548     */

1549    public void characters(final int node, SerializationHandler handler)
1550        throws TransletException
1551    {
1552        if (node != DTM.NULL) {
1553            try {
1554                dispatchCharactersEvents(node, handler, false);
1555            } catch (SAXException JavaDoc e) {
1556                throw new TransletException(e);
1557            }
1558        }
1559    }
1560    
1561    /**
1562     * Copy a node-set to an output handler
1563     */

1564    public void copy(DTMAxisIterator nodes, SerializationHandler handler)
1565        throws TransletException
1566    {
1567        int node;
1568        while ((node = nodes.next()) != DTM.NULL) {
1569            copy(node, handler);
1570        }
1571    }
1572
1573    /**
1574     * Copy the whole tree to an output handler
1575     */

1576    public void copy(SerializationHandler handler) throws TransletException
1577    {
1578        copy(getDocument(), handler);
1579    }
1580
1581    /**
1582     * Performs a deep copy (ref. XSLs copy-of())
1583     *
1584     * TODO: Copy namespace declarations. Can't be done until we
1585     * add namespace nodes and keep track of NS prefixes
1586     * TODO: Copy comment nodes
1587     */

1588    public void copy(final int node, SerializationHandler handler)
1589        throws TransletException
1590    {
1591        copy(node, handler, false );
1592    }
1593
1594
1595 private final void copy(final int node, SerializationHandler handler, boolean isChild)
1596        throws TransletException
1597    {
1598     int nodeID = makeNodeIdentity(node);
1599        int eType = _exptype2(nodeID);
1600        int type = _exptype2Type(eType);
1601
1602        try {
1603            switch(type)
1604            {
1605                case DTM.ROOT_NODE:
1606                case DTM.DOCUMENT_NODE:
1607                    for(int c = _firstch2(nodeID); c != DTM.NULL; c = _nextsib2(c)) {
1608                        copy(makeNodeHandle(c), handler, true);
1609                    }
1610                    break;
1611                case DTM.PROCESSING_INSTRUCTION_NODE:
1612                    copyPI(node, handler);
1613                    break;
1614                case DTM.COMMENT_NODE:
1615                    handler.comment(getStringValueX(node));
1616                    break;
1617                case DTM.TEXT_NODE:
1618                    boolean oldEscapeSetting = false;
1619                    boolean escapeBit = false;
1620
1621                    if (_dontEscape != null) {
1622                        escapeBit = _dontEscape.getBit(getNodeIdent(node));
1623                        if (escapeBit) {
1624                            oldEscapeSetting = handler.setEscaping(false);
1625                        }
1626                    }
1627                    
1628                    copyTextNode(nodeID, handler);
1629        
1630                    if (escapeBit) {
1631                        handler.setEscaping(oldEscapeSetting);
1632                    }
1633                    break;
1634                case DTM.ATTRIBUTE_NODE:
1635                    copyAttribute(nodeID, eType, handler);
1636                    break;
1637                case DTM.NAMESPACE_NODE:
1638                    handler.namespaceAfterStartElement(getNodeNameX(node), getNodeValue(node));
1639                    break;
1640                default:
1641                    if (type == DTM.ELEMENT_NODE)
1642                    {
1643                        // Start element definition
1644
final String JavaDoc name = copyElement(nodeID, eType, handler);
1645                        //if(isChild) => not to copy any namespaces from parents
1646
// else copy all namespaces in scope
1647
copyNS(nodeID, handler,!isChild);
1648                        copyAttributes(nodeID, handler);
1649                        // Copy element children
1650
for (int c = _firstch2(nodeID); c != DTM.NULL; c = _nextsib2(c)) {
1651                            copy(makeNodeHandle(c), handler, true);
1652                        }
1653          
1654                        // Close element definition
1655
handler.endElement(name);
1656                    }
1657                    // Shallow copy of attribute to output handler
1658
else {
1659                        final String JavaDoc uri = getNamespaceName(node);
1660                        if (uri.length() != 0) {
1661                            final String JavaDoc prefix = getPrefix(node);
1662                            handler.namespaceAfterStartElement(prefix, uri);
1663                        }
1664                        handler.addAttribute(getNodeName(node), getNodeValue(node));
1665                    }
1666                    break;
1667            }
1668        }
1669        catch (Exception JavaDoc e) {
1670            throw new TransletException(e);
1671        }
1672    
1673    }
1674    /**
1675     * Copies a processing instruction node to an output handler
1676     */

1677    private void copyPI(final int node, SerializationHandler handler)
1678    throws TransletException
1679    {
1680        final String JavaDoc target = getNodeName(node);
1681        final String JavaDoc value = getStringValueX(node);
1682      
1683        try {
1684            handler.processingInstruction(target, value);
1685        } catch (Exception JavaDoc e) {
1686            throw new TransletException(e);
1687        }
1688    }
1689
1690    /**
1691     * Performs a shallow copy (ref. XSLs copy())
1692     */

1693    public String JavaDoc shallowCopy(final int node, SerializationHandler handler)
1694        throws TransletException
1695    {
1696        int nodeID = makeNodeIdentity(node);
1697        int exptype = _exptype2(nodeID);
1698        int type = _exptype2Type(exptype);
1699      
1700        try {
1701            switch(type)
1702            {
1703                case DTM.ELEMENT_NODE:
1704                    final String JavaDoc name = copyElement(nodeID, exptype, handler);
1705                    copyNS(nodeID, handler, true);
1706                    return name;
1707                case DTM.ROOT_NODE:
1708                case DTM.DOCUMENT_NODE:
1709                    return EMPTYSTRING;
1710                case DTM.TEXT_NODE:
1711                    copyTextNode(nodeID, handler);
1712                    return null;
1713                case DTM.PROCESSING_INSTRUCTION_NODE:
1714                    copyPI(node, handler);
1715                    return null;
1716                case DTM.COMMENT_NODE:
1717                    handler.comment(getStringValueX(node));
1718                    return null;
1719                case DTM.NAMESPACE_NODE:
1720                    handler.namespaceAfterStartElement(getNodeNameX(node), getNodeValue(node));
1721                    return null;
1722                case DTM.ATTRIBUTE_NODE:
1723                    copyAttribute(nodeID, exptype, handler);
1724                    return null;
1725                default:
1726                    final String JavaDoc uri1 = getNamespaceName(node);
1727                    if (uri1.length() != 0) {
1728                        final String JavaDoc prefix = getPrefix(node);
1729                        handler.namespaceAfterStartElement(prefix, uri1);
1730                    }
1731                    handler.addAttribute(getNodeName(node), getNodeValue(node));
1732                    return null;
1733            }
1734        } catch (Exception JavaDoc e) {
1735            throw new TransletException(e);
1736        }
1737    }
1738    
1739    /**
1740     * Returns a node' defined language for a node (if any)
1741     */

1742    public String JavaDoc getLanguage(int node)
1743    {
1744        int parent = node;
1745        while (DTM.NULL != parent) {
1746            if (DTM.ELEMENT_NODE == getNodeType(parent)) {
1747                int langAttr = getAttributeNode(parent, "http://www.w3.org/XML/1998/namespace", "lang");
1748
1749                if (DTM.NULL != langAttr) {
1750                    return getNodeValue(langAttr);
1751                }
1752            }
1753
1754            parent = getParent(parent);
1755        }
1756        return(null);
1757    }
1758
1759    /**
1760     * Returns an instance of the DOMBuilder inner class
1761     * This class will consume the input document through a SAX2
1762     * interface and populate the tree.
1763     */

1764    public DOMBuilder getBuilder()
1765    {
1766    return this;
1767    }
1768    
1769    /**
1770     * Return a SerializationHandler for output handling.
1771     * This method is used by Result Tree Fragments.
1772     */

1773    public SerializationHandler getOutputDomBuilder()
1774    {
1775        return new ToXMLSAXHandler(this, "UTF-8");
1776    }
1777    
1778    /**
1779     * Return a instance of a DOM class to be used as an RTF
1780     */

1781    public DOM getResultTreeFrag(int initSize, int rtfType)
1782    {
1783        return getResultTreeFrag(initSize, rtfType, true);
1784    }
1785        
1786    /**
1787     * Return a instance of a DOM class to be used as an RTF
1788     *
1789     * @param initSize The initial size of the DOM.
1790     * @param rtfType The type of the RTF
1791     * @param addToManager true if the RTF should be registered with the DTMManager.
1792     * @return The DOM object which represents the RTF.
1793     */

1794    public DOM getResultTreeFrag(int initSize, int rtfType, boolean addToManager)
1795    {
1796        if (rtfType == DOM.SIMPLE_RTF) {
1797            if (addToManager) {
1798                int dtmPos = _dtmManager.getFirstFreeDTMID();
1799                SimpleResultTreeImpl rtf = new SimpleResultTreeImpl(_dtmManager,
1800                                           dtmPos << DTMManager.IDENT_DTM_NODE_BITS);
1801                _dtmManager.addDTM(rtf, dtmPos, 0);
1802                return rtf;
1803            }
1804            else {
1805                return new SimpleResultTreeImpl(_dtmManager, 0);
1806            }
1807        }
1808        else if (rtfType == DOM.ADAPTIVE_RTF) {
1809            if (addToManager) {
1810                int dtmPos = _dtmManager.getFirstFreeDTMID();
1811                AdaptiveResultTreeImpl rtf = new AdaptiveResultTreeImpl(_dtmManager,
1812                                       dtmPos << DTMManager.IDENT_DTM_NODE_BITS,
1813                                       m_wsfilter, initSize, m_buildIdIndex);
1814                _dtmManager.addDTM(rtf, dtmPos, 0);
1815                return rtf;
1816        
1817            }
1818            else {
1819                return new AdaptiveResultTreeImpl(_dtmManager, 0,
1820                                       m_wsfilter, initSize, m_buildIdIndex);
1821            }
1822        }
1823        else {
1824            return (DOM) _dtmManager.getDTM(null, true, m_wsfilter,
1825                                            true, false, false,
1826                                            initSize, m_buildIdIndex);
1827        }
1828    }
1829
1830    /**
1831     * %HZ% Need Javadoc
1832     */

1833    public Hashtable getElementsWithIDs() {
1834        if (m_idAttributes == null) {
1835            return null;
1836        }
1837
1838        // Convert a java.util.Hashtable to an xsltc.runtime.Hashtable
1839
Enumeration JavaDoc idValues = m_idAttributes.keys();
1840        if (!idValues.hasMoreElements()) {
1841            return null;
1842        }
1843
1844        Hashtable idAttrsTable = new Hashtable();
1845
1846        while (idValues.hasMoreElements()) {
1847            Object JavaDoc idValue = idValues.nextElement();
1848
1849            idAttrsTable.put(idValue, m_idAttributes.get(idValue));
1850        }
1851
1852        return idAttrsTable;
1853    }
1854
1855    /**
1856     * The getUnparsedEntityURI function returns the URI of the unparsed
1857     * entity with the specified name in the same document as the context
1858     * node (see [3.3 Unparsed Entities]). It returns the empty string if
1859     * there is no such entity.
1860     */

1861    public String JavaDoc getUnparsedEntityURI(String JavaDoc name)
1862    {
1863        // Special handling for DOM input
1864
if (_document != null) {
1865            String JavaDoc uri = "";
1866            DocumentType JavaDoc doctype = _document.getDoctype();
1867            if (doctype != null) {
1868                NamedNodeMap JavaDoc entities = doctype.getEntities();
1869                
1870                if (entities == null) {
1871                    return uri;
1872                }
1873                
1874                Entity JavaDoc entity = (Entity JavaDoc) entities.getNamedItem(name);
1875                
1876                if (entity == null) {
1877                    return uri;
1878                }
1879                
1880                String JavaDoc notationName = entity.getNotationName();
1881                if (notationName != null) {
1882                    uri = entity.getSystemId();
1883                    if (uri == null) {
1884                        uri = entity.getPublicId();
1885                    }
1886                }
1887            }
1888            return uri;
1889        }
1890        else {
1891            return super.getUnparsedEntityURI(name);
1892        }
1893    }
1894
1895}
1896
Popular Tags