KickJava   Java API By Example, From Geeks To Geeks.

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


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: MultiDOM.java,v 1.31 2004/02/16 22:54:59 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.dom;
21
22 import org.apache.xalan.xsltc.DOM;
23 import org.apache.xalan.xsltc.StripFilter;
24 import org.apache.xml.serializer.SerializationHandler;
25 import org.apache.xalan.xsltc.TransletException;
26 import org.apache.xalan.xsltc.runtime.BasisLibrary;
27 import org.apache.xalan.xsltc.runtime.Hashtable;
28 import org.apache.xml.dtm.DTM;
29 import org.apache.xml.dtm.DTMAxisIterator;
30 import org.apache.xml.dtm.DTMManager;
31 import org.apache.xml.dtm.ref.DTMAxisIteratorBase;
32 import org.apache.xml.dtm.ref.DTMDefaultBase;
33 import org.apache.xml.utils.SuballocatedIntVector;
34
35 import org.w3c.dom.Node JavaDoc;
36 import org.w3c.dom.NodeList JavaDoc;
37
38 /**
39  * @author Jacek Ambroziak
40  * @author Morten Jorgensen
41  * @author Erwin Bolwidt <ejb@klomp.org>
42  */

43 public final class MultiDOM implements DOM {
44
45     private static final int NO_TYPE = DOM.FIRST_TYPE - 2;
46     private static final int INITIAL_SIZE = 4;
47     
48     private DOM[] _adapters;
49     private DOMAdapter _main;
50     private DTMManager _dtmManager;
51     private int _free;
52     private int _size;
53
54     private Hashtable _documents = new Hashtable();
55
56     private final class AxisIterator extends DTMAxisIteratorBase {
57         // constitutive data
58
private final int _axis;
59         private final int _type;
60         // implementation mechanism
61
private DTMAxisIterator _source;
62         private int _dtmId = -1;
63
64         public AxisIterator(final int axis, final int type) {
65             _axis = axis;
66             _type = type;
67         }
68
69         public int next() {
70             if (_source == null) {
71                 return(END);
72             }
73             return _source.next();
74         }
75
76
77         public void setRestartable(boolean flag) {
78             if (_source != null) {
79                 _source.setRestartable(flag);
80             }
81         }
82
83         public DTMAxisIterator setStartNode(final int node) {
84             if (node == DTM.NULL) {
85                 return this;
86             }
87
88             int dom = node >>> DTMManager.IDENT_DTM_NODE_BITS;
89
90             // Get a new source first time and when mask changes
91
if (_source == null || _dtmId != dom) {
92                 if (_type == NO_TYPE) {
93                     _source = _adapters[dom].getAxisIterator(_axis);
94                 } else if (_axis == Axis.CHILD) {
95                     _source = _adapters[dom].getTypedChildren(_type);
96                 } else {
97                     _source = _adapters[dom].getTypedAxisIterator(_axis, _type);
98                 }
99             }
100
101             _dtmId = dom;
102             _source.setStartNode(node);
103             return this;
104         }
105
106         public DTMAxisIterator reset() {
107             if (_source != null) {
108                 _source.reset();
109             }
110             return this;
111         }
112     
113         public int getLast() {
114             if (_source != null) {
115                 return _source.getLast();
116             }
117             else {
118                 return END;
119             }
120         }
121
122         public int getPosition() {
123             if (_source != null) {
124                 return _source.getPosition();
125             }
126             else {
127                 return END;
128             }
129         }
130     
131         public boolean isReverse() {
132         return Axis.isReverse[_axis];
133         }
134     
135         public void setMark() {
136             if (_source != null) {
137                 _source.setMark();
138             }
139         }
140     
141         public void gotoMark() {
142             if (_source != null) {
143                 _source.gotoMark();
144             }
145         }
146     
147         public DTMAxisIterator cloneIterator() {
148             final AxisIterator clone = new AxisIterator(_axis, _type);
149             if (_source != null) {
150                 clone._source = _source.cloneIterator();
151             }
152             clone._dtmId = _dtmId;
153             return clone;
154         }
155     } // end of AxisIterator
156

157
158     /**************************************************************
159      * This is a specialised iterator for predicates comparing node or
160      * attribute values to variable or parameter values.
161      */

162     private final class NodeValueIterator extends DTMAxisIteratorBase {
163
164         private DTMAxisIterator _source;
165         private String JavaDoc _value;
166         private boolean _op;
167         private final boolean _isReverse;
168         private int _returnType = RETURN_PARENT;
169
170         public NodeValueIterator(DTMAxisIterator source, int returnType,
171                                  String JavaDoc value, boolean op) {
172             _source = source;
173             _returnType = returnType;
174             _value = value;
175             _op = op;
176             _isReverse = source.isReverse();
177         }
178
179         public boolean isReverse() {
180             return _isReverse;
181         }
182     
183         public DTMAxisIterator cloneIterator() {
184             try {
185                 NodeValueIterator clone = (NodeValueIterator)super.clone();
186                 clone._source = _source.cloneIterator();
187                 clone.setRestartable(false);
188                 return clone.reset();
189             }
190             catch (CloneNotSupportedException JavaDoc e) {
191                 BasisLibrary.runTimeError(BasisLibrary.ITERATOR_CLONE_ERR,
192                                           e.toString());
193                 return null;
194             }
195         }
196
197
198         public void setRestartable(boolean isRestartable) {
199             _isRestartable = isRestartable;
200             _source.setRestartable(isRestartable);
201         }
202
203         public DTMAxisIterator reset() {
204             _source.reset();
205             return resetPosition();
206         }
207
208         public int next() {
209
210             int node;
211             while ((node = _source.next()) != END) {
212                 String JavaDoc val = getStringValueX(node);
213                 if (_value.equals(val) == _op) {
214                     if (_returnType == RETURN_CURRENT)
215                         return returnNode(node);
216                     else
217                         return returnNode(getParent(node));
218                 }
219             }
220             return END;
221         }
222
223         public DTMAxisIterator setStartNode(int node) {
224             if (_isRestartable) {
225                 _source.setStartNode(_startNode = node);
226                 return resetPosition();
227             }
228             return this;
229         }
230
231         public void setMark() {
232             _source.setMark();
233         }
234
235         public void gotoMark() {
236             _source.gotoMark();
237         }
238     }
239
240     public MultiDOM(DOM main) {
241         _size = INITIAL_SIZE;
242         _free = 1;
243         _adapters = new DOM[INITIAL_SIZE];
244         DOMAdapter adapter = (DOMAdapter)main;
245         _adapters[0] = adapter;
246         _main = adapter;
247         DOM dom = adapter.getDOMImpl();
248         if (dom instanceof DTMDefaultBase) {
249             _dtmManager = ((DTMDefaultBase)dom).getManager();
250         }
251
252         // %HZ% %REVISIT% Is this the right thing to do here? In the old
253
// %HZ% %REVISIT% version, the main document did not get added through
254
// %HZ% %REVISIT% a call to addDOMAdapter, which meant it couldn't be
255
// %HZ% %REVISIT% found by a call to getDocumentMask. The problem is
256
// %HZ% %REVISIT% TransformerHandler is typically constructed with a
257
// %HZ% %REVISIT% system ID equal to the stylesheet's URI; with SAX
258
// %HZ% %REVISIT% input, it ends up giving that URI to the document.
259
// %HZ% %REVISIT% Then, any references to document('') are resolved
260
// %HZ% %REVISIT% using the stylesheet's URI.
261
// %HZ% %REVISIT% MultiDOM.getDocumentMask is called to verify that
262
// %HZ% %REVISIT% a document associated with that URI has not been
263
// %HZ% %REVISIT% encountered, and that method ends up returning the
264
// %HZ% %REVISIT% mask of the main document, when what we really what
265
// %HZ% %REVISIT% is to read the stylesheet itself!
266
addDOMAdapter(adapter, false);
267     }
268
269     public int nextMask() {
270         return _free;
271     }
272
273     public void setupMapping(String JavaDoc[] names, String JavaDoc[] uris, int[] types, String JavaDoc[] namespaces) {
274         // This method only has a function in DOM adapters
275
}
276
277     public int addDOMAdapter(DOMAdapter adapter) {
278         return addDOMAdapter(adapter, true);
279     }
280
281     private int addDOMAdapter(DOMAdapter adapter, boolean indexByURI) {
282         // Add the DOM adapter to the array of DOMs
283
DOM dom = adapter.getDOMImpl();
284         
285         int domNo = 1;
286         int dtmSize = 1;
287         SuballocatedIntVector dtmIds = null;
288         if (dom instanceof DTMDefaultBase) {
289             DTMDefaultBase dtmdb = (DTMDefaultBase)dom;
290             dtmIds = dtmdb.getDTMIDs();
291             dtmSize = dtmIds.size();
292             domNo = dtmIds.elementAt(dtmSize-1) >>> DTMManager.IDENT_DTM_NODE_BITS;
293         }
294         else if (dom instanceof SimpleResultTreeImpl) {
295             SimpleResultTreeImpl simpleRTF = (SimpleResultTreeImpl)dom;
296             domNo = simpleRTF.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS;
297         }
298                   
299         if (domNo >= _size) {
300             int oldSize = _size;
301             do {
302                 _size *= 2;
303             } while (_size <= domNo);
304             
305             final DOMAdapter[] newArray = new DOMAdapter[_size];
306             System.arraycopy(_adapters, 0, newArray, 0, oldSize);
307             _adapters = newArray;
308         }
309         
310         _free = domNo + 1;
311         
312         if (dtmSize == 1) {
313             _adapters[domNo] = adapter;
314         }
315         else if (dtmIds != null) {
316             int domPos = 0;
317             for (int i = dtmSize - 1; i >= 0; i--) {
318                 domPos = dtmIds.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS;
319                 _adapters[domPos] = adapter;
320             }
321             domNo = domPos;
322         }
323
324         // Store reference to document (URI) in hashtable
325
if (indexByURI) {
326             String JavaDoc uri = adapter.getDocumentURI(0);
327             _documents.put(uri, new Integer JavaDoc(domNo));
328         }
329         
330         // If the dom is an AdaptiveResultTreeImpl, we need to create a
331
// DOMAdapter around its nested dom object (if it is non-null) and
332
// add the DOMAdapter to the list.
333
if (dom instanceof AdaptiveResultTreeImpl) {
334             AdaptiveResultTreeImpl adaptiveRTF = (AdaptiveResultTreeImpl)dom;
335             DOM nestedDom = adaptiveRTF.getNestedDOM();
336             if (nestedDom != null) {
337                 DOMAdapter newAdapter = new DOMAdapter(nestedDom,
338                                                        adapter.getNamesArray(),
339                                                        adapter.getUrisArray(),
340                                                        adapter.getTypesArray(),
341                                                        adapter.getNamespaceArray());
342                 addDOMAdapter(newAdapter);
343             }
344         }
345         
346         return domNo;
347     }
348         
349     public int getDocumentMask(String JavaDoc uri) {
350         Integer JavaDoc domIdx = (Integer JavaDoc)_documents.get(uri);
351         if (domIdx == null) {
352             return(-1);
353         } else {
354             return domIdx.intValue();
355         }
356     }
357     
358     public DOM getDOMAdapter(String JavaDoc uri) {
359         Integer JavaDoc domIdx = (Integer JavaDoc)_documents.get(uri);
360         if (domIdx == null) {
361             return(null);
362         } else {
363             return(_adapters[domIdx.intValue()]);
364         }
365     }
366     
367     public int getDocument()
368     {
369         return _main.getDocument();
370     }
371
372     public DTMManager getDTMManager() {
373         return _dtmManager;
374     }
375
376     /**
377       * Returns singleton iterator containing the document root
378       */

379     public DTMAxisIterator getIterator() {
380         // main source document @ 0
381
return _main.getIterator();
382     }
383     
384     public String JavaDoc getStringValue() {
385         return _main.getStringValue();
386     }
387     
388     public DTMAxisIterator getChildren(final int node) {
389         return _adapters[getDTMId(node)].getChildren(node);
390     }
391     
392     public DTMAxisIterator getTypedChildren(final int type) {
393         return new AxisIterator(Axis.CHILD, type);
394     }
395     
396     public DTMAxisIterator getAxisIterator(final int axis) {
397         return new AxisIterator(axis, NO_TYPE);
398     }
399     
400     public DTMAxisIterator getTypedAxisIterator(final int axis, final int type)
401     {
402         return new AxisIterator(axis, type);
403     }
404
405     public DTMAxisIterator getNthDescendant(int node, int n,
406                                             boolean includeself)
407     {
408         return _adapters[getDTMId(node)].getNthDescendant(node, n, includeself);
409     }
410
411     public DTMAxisIterator getNodeValueIterator(DTMAxisIterator iterator,
412                                                 int type, String JavaDoc value,
413                                                 boolean op)
414     {
415         return(new NodeValueIterator(iterator, type, value, op));
416     }
417
418     public DTMAxisIterator getNamespaceAxisIterator(final int axis,
419                                                     final int ns)
420     {
421         DTMAxisIterator iterator = _main.getNamespaceAxisIterator(axis, ns);
422         return(iterator);
423     }
424
425     public DTMAxisIterator orderNodes(DTMAxisIterator source, int node) {
426         return _adapters[getDTMId(node)].orderNodes(source, node);
427     }
428
429     public int getExpandedTypeID(final int node) {
430         if (node != DTM.NULL) {
431             return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getExpandedTypeID(node);
432         }
433         else {
434             return DTM.NULL;
435         }
436     }
437
438     public int getNamespaceType(final int node) {
439         return _adapters[getDTMId(node)].getNamespaceType(node);
440     }
441     
442     public int getNSType(int node)
443    {
444         return _adapters[getDTMId(node)].getNSType(node);
445    }
446     
447     public int getParent(final int node) {
448         if (node == DTM.NULL) {
449             return DTM.NULL;
450         }
451         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getParent(node);
452     }
453     
454     public int getAttributeNode(final int type, final int el) {
455         if (el == DTM.NULL) {
456             return DTM.NULL;
457         }
458         return _adapters[el >>> DTMManager.IDENT_DTM_NODE_BITS].getAttributeNode(type, el);
459     }
460     
461     public String JavaDoc getNodeName(final int node) {
462         if (node == DTM.NULL) {
463             return "";
464         }
465         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeName(node);
466     }
467     
468     public String JavaDoc getNodeNameX(final int node) {
469         if (node == DTM.NULL) {
470             return "";
471         }
472         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeNameX(node);
473     }
474
475     public String JavaDoc getNamespaceName(final int node) {
476         if (node == DTM.NULL) {
477             return "";
478         }
479         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getNamespaceName(node);
480     }
481     
482     public String JavaDoc getStringValueX(final int node) {
483         if (node == DTM.NULL) {
484             return "";
485         }
486         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getStringValueX(node);
487     }
488     
489     public void copy(final int node, SerializationHandler handler)
490         throws TransletException
491     {
492         if (node != DTM.NULL) {
493             _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
494         }
495     }
496     
497     public void copy(DTMAxisIterator nodes, SerializationHandler handler)
498             throws TransletException
499     {
500         int node;
501         while ((node = nodes.next()) != DTM.NULL) {
502             _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].copy(node, handler);
503         }
504     }
505
506
507     public String JavaDoc shallowCopy(final int node, SerializationHandler handler)
508             throws TransletException
509     {
510         if (node == DTM.NULL) {
511             return "";
512         }
513         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].shallowCopy(node, handler);
514     }
515     
516     public boolean lessThan(final int node1, final int node2) {
517         if (node1 == DTM.NULL) {
518             return true;
519         }
520         if (node2 == DTM.NULL) {
521             return false;
522         }
523         final int dom1 = getDTMId(node1);
524         final int dom2 = getDTMId(node2);
525         return dom1 == dom2 ? _adapters[dom1].lessThan(node1, node2)
526                             : dom1 < dom2;
527     }
528     
529     public void characters(final int textNode, SerializationHandler handler)
530                  throws TransletException
531     {
532         if (textNode != DTM.NULL) {
533             _adapters[textNode >>> DTMManager.IDENT_DTM_NODE_BITS].characters(textNode, handler);
534         }
535     }
536
537     public void setFilter(StripFilter filter) {
538         for (int dom=0; dom<_free; dom++) {
539             if (_adapters[dom] != null) {
540                 _adapters[dom].setFilter(filter);
541             }
542         }
543     }
544
545     public Node JavaDoc makeNode(int index) {
546         if (index == DTM.NULL) {
547             return null;
548         }
549         return _adapters[getDTMId(index)].makeNode(index);
550     }
551
552     public Node JavaDoc makeNode(DTMAxisIterator iter) {
553         // TODO: gather nodes from all DOMs ?
554
return _main.makeNode(iter);
555     }
556
557     public NodeList JavaDoc makeNodeList(int index) {
558         if (index == DTM.NULL) {
559             return null;
560         }
561         return _adapters[getDTMId(index)].makeNodeList(index);
562     }
563
564     public NodeList JavaDoc makeNodeList(DTMAxisIterator iter) {
565         // TODO: gather nodes from all DOMs ?
566
return _main.makeNodeList(iter);
567     }
568
569     public String JavaDoc getLanguage(int node) {
570         return _adapters[getDTMId(node)].getLanguage(node);
571     }
572
573     public int getSize() {
574         int size = 0;
575         for (int i=0; i<_size; i++) {
576             size += _adapters[i].getSize();
577         }
578         return(size);
579     }
580
581     public String JavaDoc getDocumentURI(int node) {
582         if (node == DTM.NULL) {
583             node = DOM.NULL;
584         }
585         return _adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].getDocumentURI(0);
586     }
587
588     public boolean isElement(final int node) {
589         if (node == DTM.NULL) {
590             return false;
591         }
592         return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isElement(node));
593     }
594
595     public boolean isAttribute(final int node) {
596         if (node == DTM.NULL) {
597             return false;
598         }
599         return(_adapters[node >>> DTMManager.IDENT_DTM_NODE_BITS].isAttribute(node));
600     }
601     
602     public int getDTMId(int nodeHandle)
603     {
604         if (nodeHandle == DTM.NULL)
605             return 0;
606         
607         int id = nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS;
608         while (id >= 2 && _adapters[id] == _adapters[id-1]) {
609             id--;
610         }
611         return id;
612     }
613     
614     public int getNodeIdent(int nodeHandle)
615     {
616         return _adapters[nodeHandle >>> DTMManager.IDENT_DTM_NODE_BITS].getNodeIdent(nodeHandle);
617     }
618     
619     public int getNodeHandle(int nodeId)
620     {
621         return _main.getNodeHandle(nodeId);
622     }
623     
624     public DOM getResultTreeFrag(int initSize, int rtfType)
625     {
626         return _main.getResultTreeFrag(initSize, rtfType);
627     }
628     
629     public DOM getResultTreeFrag(int initSize, int rtfType, boolean addToManager)
630     {
631         return _main.getResultTreeFrag(initSize, rtfType, addToManager);
632     }
633     
634     public DOM getMain()
635     {
636         return _main;
637     }
638     
639     /**
640      * Returns a DOMBuilder class wrapped in a SAX adapter.
641      */

642     public SerializationHandler getOutputDomBuilder()
643     {
644         return _main.getOutputDomBuilder();
645     }
646
647     public String JavaDoc lookupNamespace(int node, String JavaDoc prefix)
648         throws TransletException
649     {
650         return _main.lookupNamespace(node, prefix);
651     }
652
653     // %HZ% Does this method make any sense here???
654
public String JavaDoc getUnparsedEntityURI(String JavaDoc entity) {
655         return _main.getUnparsedEntityURI(entity);
656     }
657
658     // %HZ% Does this method make any sense here???
659
public Hashtable getElementsWithIDs() {
660         return _main.getElementsWithIDs();
661     }
662 }
663
Popular Tags