1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the  "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *     http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18/*
19 * $Id: DTMNodeProxy.java 889881 2009-12-12 03:47:15Z zongaro $
20 */
21package org.apache.xml.dtm.ref;
22
23import java.util.Vector;
24
25import org.apache.xml.dtm.DTM;
26import org.apache.xml.dtm.DTMDOMException;
27import org.apache.xpath.NodeSet;
28
29import org.w3c.dom.Attr;
30import org.w3c.dom.CDATASection;
31import org.w3c.dom.Comment;
32import org.w3c.dom.DOMException;
33import org.w3c.dom.DOMImplementation;
34import org.w3c.dom.Document;
35import org.w3c.dom.DocumentFragment;
36import org.w3c.dom.DocumentType;
37import org.w3c.dom.Element;
38import org.w3c.dom.EntityReference;
39import org.w3c.dom.NamedNodeMap;
40import org.w3c.dom.Node;
41import org.w3c.dom.NodeList;
42import org.w3c.dom.ProcessingInstruction;
43import org.w3c.dom.Text;
44
45import org.w3c.dom.UserDataHandler;
46import org.w3c.dom.DOMConfiguration;
47import org.w3c.dom.TypeInfo;
48
49/**
50 * <code>DTMNodeProxy</code> presents a DOM Node API front-end to the DTM model.
51 * <p>
52 * It does _not_ attempt to address the "node identity" question; no effort
53 * is made to prevent the creation of multiple proxies referring to a single
54 * DTM node. Users can create a mechanism for managing this, or relinquish the
55 * use of "==" and use the .sameNodeAs() mechanism, which is under
56 * consideration for future versions of the DOM.
57 * <p>
58 * DTMNodeProxy may be subclassed further to present specific DOM node types.
59 *
60 * @see org.w3c.dom
61 * @xsl.usage internal
62 */
63public class DTMNodeProxy
64  implements Node, Document, Text, Element, Attr,
65                   ProcessingInstruction, Comment, DocumentFragment
66{
67
68  /** The DTM for this node. */
69  public DTM dtm;
70
71  /** The DTM node handle. */
72  int node;
73
74  /** The return value as Empty String. */
75  private static final String EMPTYSTRING = "";
76
77  /** The DOMImplementation object */
78  static final DOMImplementation implementation=new DTMNodeProxyImplementation();
79
80  /**
81   * Create a DTMNodeProxy Node representing a specific Node in a DTM
82   *
83   * @param dtm The DTM Reference, must be non-null.
84   * @param node The DTM node handle.
85   */
86  public DTMNodeProxy(DTM dtm, int node)
87  {
88    this.dtm = dtm;
89    this.node = node;
90  }
91
92  /**
93   * NON-DOM: Return the DTM model
94   *
95   * @return The DTM that this proxy is a representative for.
96   */
97  public final DTM getDTM()
98  {
99    return dtm;
100  }
101
102  /**
103   * NON-DOM: Return the DTM node number
104   *
105   * @return The DTM node handle.
106   */
107  public final int getDTMNodeNumber()
108  {
109    return node;
110  }
111
112  /**
113   * Test for equality based on node number.
114   *
115   * @param node A DTM node proxy reference.
116   *
117   * @return true if the given node has the same handle as this node.
118   */
119  public final boolean equals(Node node)
120  {
121
122    try
123    {
124      DTMNodeProxy dtmp = (DTMNodeProxy) node;
125
126      // return (dtmp.node == this.node);
127      // Patch attributed to Gary L Peskin <garyp@firstech.com>
128      return (dtmp.node == this.node) && (dtmp.dtm == this.dtm);
129    }
130    catch (ClassCastException cce)
131    {
132      return false;
133    }
134  }
135
136  /**
137   * Test for equality based on node number.
138   *
139   * @param node A DTM node proxy reference.
140   *
141   * @return true if the given node has the same handle as this node.
142   */
143  public final boolean equals(Object node)
144  {
145
146    try
147    {
148
149      // DTMNodeProxy dtmp = (DTMNodeProxy)node;
150      // return (dtmp.node == this.node);
151      // Patch attributed to Gary L Peskin <garyp@firstech.com>
152      return equals((Node) node);
153    }
154    catch (ClassCastException cce)
155    {
156      return false;
157    }
158  }
159
160  /**
161   * FUTURE DOM: Test node identity, in lieu of Node==Node
162   *
163   * @param other
164   *
165   * @return true if the given node has the same handle as this node.
166   */
167  public final boolean sameNodeAs(Node other)
168  {
169
170    if (!(other instanceof DTMNodeProxy))
171      return false;
172
173    DTMNodeProxy that = (DTMNodeProxy) other;
174
175    return this.dtm == that.dtm && this.node == that.node;
176  }
177
178  /**
179   *
180   *
181   * @see org.w3c.dom.Node
182   */
183  public final String getNodeName()
184  {
185    return dtm.getNodeName(node);
186  }
187
188  /**
189   * A PI's "target" states what processor channel the PI's data
190   * should be directed to. It is defined differently in HTML and XML.
191   * <p>
192   * In XML, a PI's "target" is the first (whitespace-delimited) token
193   * following the "<?" token that begins the PI.
194   * <p>
195   * In HTML, target is always null.
196   * <p>
197   * Note that getNodeName is aliased to getTarget.
198   *
199   *
200   */
201  public final String getTarget()
202  {
203    return dtm.getNodeName(node);
204  }  // getTarget():String
205
206  /**
207   *
208   *
209   * @see org.w3c.dom.Node as of DOM Level 2
210   */
211  public final String getLocalName()
212  {
213    return dtm.getLocalName(node);
214  }
215
216  /**
217   * @return The prefix for this node.
218   * @see org.w3c.dom.Node as of DOM Level 2
219   */
220  public final String getPrefix()
221  {
222    return dtm.getPrefix(node);
223  }
224
225  /**
226   *
227   * @param prefix
228   *
229   * @throws DOMException
230   * @see org.w3c.dom.Node as of DOM Level 2 -- DTMNodeProxy is read-only
231   */
232  public final void setPrefix(String prefix) throws DOMException
233  {
234    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
235  }
236
237  /**
238   *
239   *
240   * @see org.w3c.dom.Node as of DOM Level 2
241   */
242  public final String getNamespaceURI()
243  {
244    return dtm.getNamespaceURI(node);
245  }
246
247  /** Ask whether we support a given DOM feature.
248   * In fact, we do not _fully_ support any DOM feature -- we're a
249   * read-only subset -- so arguably we should always return false.
250   * Or we could say that we support DOM Core Level 2 but all nodes
251   * are read-only. Unclear which answer is least misleading.
252   *
253   * NON-DOM method. This was present in early drafts of DOM Level 2,
254   * but was renamed isSupported. It's present here only because it's
255   * cheap, harmless, and might help some poor fool who is still trying
256   * to use an early Working Draft of the DOM.
257   *
258   * @param feature
259   * @param version
260   *
261   * @return false
262   */
263  public final boolean supports(String feature, String version)
264  {
265    return implementation.hasFeature(feature,version);
266    //throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
267  }
268
269  /** Ask whether we support a given DOM feature.
270   * In fact, we do not _fully_ support any DOM feature -- we're a
271   * read-only subset -- so arguably we should always return false.
272   *
273   * @param feature
274   * @param version
275   *
276   * @return false
277   * @see org.w3c.dom.Node as of DOM Level 2
278   */
279  public final boolean isSupported(String feature, String version)
280  {
281    return implementation.hasFeature(feature,version);
282    // throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
283  }
284
285  /**
286   *
287   *
288   *
289   * @throws DOMException
290   * @see org.w3c.dom.Node
291   */
292  public final String getNodeValue() throws DOMException
293  {
294    return dtm.getNodeValue(node);
295  }
296
297  /**
298   * @return The string value of the node
299   *
300   * @throws DOMException
301   */
302  public final String getStringValue() throws DOMException
303  {
304  	return dtm.getStringValue(node).toString();
305  }
306
307  /**
308   *
309   * @param nodeValue
310   *
311   * @throws DOMException
312   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
313   */
314  public final void setNodeValue(String nodeValue) throws DOMException
315  {
316    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
317  }
318
319  /**
320   *
321   *
322   * @see org.w3c.dom.Node
323   */
324  public final short getNodeType()
325  {
326    return (short) dtm.getNodeType(node);
327  }
328
329  /**
330   *
331   *
332   * @see org.w3c.dom.Node
333   */
334  public final Node getParentNode()
335  {
336
337    if (getNodeType() == Node.ATTRIBUTE_NODE)
338      return null;
339
340    int newnode = dtm.getParent(node);
341
342    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
343  }
344
345  /**
346   *
347   *
348   * @see org.w3c.dom.Node
349   */
350  public final Node getOwnerNode()
351  {
352
353    int newnode = dtm.getParent(node);
354
355    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
356  }
357
358  /**
359   *
360   *
361   * @see org.w3c.dom.Node
362   */
363  public final NodeList getChildNodes()
364  {
365
366    // Annoyingly, AxisIterators do not currently implement DTMIterator, so
367    // we can't just wap DTMNodeList around an Axis.CHILD iterator.
368    // Instead, we've created a special-case operating mode for that object.
369    return new DTMChildIterNodeList(dtm,node);
370
371    // throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
372  }
373
374  /**
375   *
376   *
377   * @see org.w3c.dom.Node
378   */
379  public final Node getFirstChild()
380  {
381
382    int newnode = dtm.getFirstChild(node);
383
384    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
385  }
386
387  /**
388   *
389   *
390   * @see org.w3c.dom.Node
391   */
392  public final Node getLastChild()
393  {
394
395    int newnode = dtm.getLastChild(node);
396
397    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
398  }
399
400  /**
401   *
402   *
403   * @see org.w3c.dom.Node
404   */
405  public final Node getPreviousSibling()
406  {
407
408    int newnode = dtm.getPreviousSibling(node);
409
410    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
411  }
412
413  /**
414   *
415   *
416   * @see org.w3c.dom.Node
417   */
418  public final Node getNextSibling()
419  {
420
421    // Attr's Next is defined at DTM level, but not at DOM level.
422    if (dtm.getNodeType(node) == Node.ATTRIBUTE_NODE)
423      return null;
424
425    int newnode = dtm.getNextSibling(node);
426
427    return (newnode == DTM.NULL) ? null : dtm.getNode(newnode);
428  }
429
430  // DTMNamedNodeMap m_attrs;
431
432  /**
433   *
434   *
435   * @see org.w3c.dom.Node
436   */
437  public final NamedNodeMap getAttributes()
438  {
439
440    return new DTMNamedNodeMap(dtm, node);
441  }
442
443  /**
444   * Method hasAttribute
445   *
446   *
447   * @param name
448   *
449   *
450   */
451  public boolean hasAttribute(String name)
452  {
453    return DTM.NULL != dtm.getAttributeNode(node,null,name);
454  }
455
456  /**
457   * Method hasAttributeNS
458   *
459   *
460   * @param namespaceURI
461   * @param localName
462   *
463   *
464   */
465  public boolean hasAttributeNS(String namespaceURI, String localName)
466  {
467    return DTM.NULL != dtm.getAttributeNode(node,namespaceURI,localName);
468  }
469
470  /**
471   *
472   *
473   * @see org.w3c.dom.Node
474   */
475  public final Document getOwnerDocument()
476  {
477  	// Note that this uses the DOM-compatable version of the call
478	return (Document)(dtm.getNode(dtm.getOwnerDocument(node)));
479  }
480
481  /**
482   *
483   * @param newChild
484   * @param refChild
485   *
486   *
487   *
488   * @throws DOMException
489   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
490   */
491  public final Node insertBefore(Node newChild, Node refChild)
492    throws DOMException
493  {
494    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
495  }
496
497  /**
498   *
499   * @param newChild
500   * @param oldChild
501   *
502   *
503   *
504   * @throws DOMException
505   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
506   */
507  public final Node replaceChild(Node newChild, Node oldChild)
508    throws DOMException
509  {
510    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
511  }
512
513  /**
514   *
515   * @param oldChild
516   *
517   *
518   *
519   * @throws DOMException
520   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
521   */
522  public final Node removeChild(Node oldChild) throws DOMException
523  {
524    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
525  }
526
527  /**
528   *
529   * @param newChild
530   *
531   *
532   *
533   * @throws DOMException
534   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
535   */
536  public final Node appendChild(Node newChild) throws DOMException
537  {
538    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
539  }
540
541  /**
542   *
543   *
544   * @see org.w3c.dom.Node
545   */
546  public final boolean hasChildNodes()
547  {
548    return (DTM.NULL != dtm.getFirstChild(node));
549  }
550
551  /**
552   *
553   * @param deep
554   *
555   *
556   * @see org.w3c.dom.Node -- DTMNodeProxy is read-only
557   */
558  public final Node cloneNode(boolean deep)
559  {
560    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
561  }
562
563  /**
564   *
565   *
566   * @see org.w3c.dom.Document
567   */
568  public final DocumentType getDoctype()
569  {
570    return null;
571  }
572
573  /**
574   *
575   *
576   * @see org.w3c.dom.Document
577   */
578  public final DOMImplementation getImplementation()
579  {
580    return implementation;
581  }
582
583  /** This is a bit of a problem in DTM, since a DTM may be a Document
584   * Fragment and hence not have a clear-cut Document Element. We can
585   * make it work in the well-formed cases but would that be confusing for others?
586   *
587   *
588   * @see org.w3c.dom.Document
589   */
590  public final Element getDocumentElement()
591  {
592		int dochandle=dtm.getDocument();
593		int elementhandle=DTM.NULL;
594		for(int kidhandle=dtm.getFirstChild(dochandle);
595				kidhandle!=DTM.NULL;
596				kidhandle=dtm.getNextSibling(kidhandle))
597		{
598			switch(dtm.getNodeType(kidhandle))
599			{
600			case Node.ELEMENT_NODE:
601				if(elementhandle!=DTM.NULL)
602				{
603					elementhandle=DTM.NULL; // More than one; ill-formed.
604					kidhandle=dtm.getLastChild(dochandle); // End loop
605				}
606				else
607					elementhandle=kidhandle;
608				break;
609
610			// These are harmless; document is still wellformed
611			case Node.COMMENT_NODE:
612			case Node.PROCESSING_INSTRUCTION_NODE:
613			case Node.DOCUMENT_TYPE_NODE:
614				break;
615
616			default:
617				elementhandle=DTM.NULL; // ill-formed
618				kidhandle=dtm.getLastChild(dochandle); // End loop
619				break;
620			}
621		}
622		if(elementhandle==DTM.NULL)
623			throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
624		else
625			return (Element)(dtm.getNode(elementhandle));
626  }
627
628  /**
629   *
630   * @param tagName
631   *
632   *
633   *
634   * @throws DOMException
635   * @see org.w3c.dom.Document
636   */
637  public final Element createElement(String tagName) throws DOMException
638  {
639    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
640  }
641
642  /**
643   *
644   *
645   * @see org.w3c.dom.Document
646   */
647  public final DocumentFragment createDocumentFragment()
648  {
649    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
650  }
651
652  /**
653   *
654   * @param data
655   *
656   *
657   * @see org.w3c.dom.Document
658   */
659  public final Text createTextNode(String data)
660  {
661    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
662  }
663
664  /**
665   *
666   * @param data
667   *
668   *
669   * @see org.w3c.dom.Document
670   */
671  public final Comment createComment(String data)
672  {
673    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
674  }
675
676  /**
677   *
678   * @param data
679   *
680   *
681   *
682   * @throws DOMException
683   * @see org.w3c.dom.Document
684   */
685  public final CDATASection createCDATASection(String data)
686    throws DOMException
687  {
688    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
689  }
690
691  /**
692   *
693   * @param target
694   * @param data
695   *
696   *
697   *
698   * @throws DOMException
699   * @see org.w3c.dom.Document
700   */
701  public final ProcessingInstruction createProcessingInstruction(
702                                                                 String target, String data) throws DOMException
703  {
704    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
705  }
706
707  /**
708   *
709   * @param name
710   *
711   *
712   *
713   * @throws DOMException
714   * @see org.w3c.dom.Document
715   */
716  public final Attr createAttribute(String name) throws DOMException
717  {
718    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
719  }
720
721  /**
722   *
723   * @param name
724   *
725   *
726   *
727   * @throws DOMException
728   * @see org.w3c.dom.Document
729   */
730  public final EntityReference createEntityReference(String name)
731    throws DOMException
732  {
733    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
734  }
735
736  /**
737   *
738   * @param tagname
739   *
740   *
741   * @see org.w3c.dom.Document
742   */
743  public final NodeList getElementsByTagName(String tagname)
744  {
745       Vector listVector = new Vector();
746       Node retNode = dtm.getNode(node);
747       if (retNode != null)
748       {
749         boolean isTagNameWildCard = "*".equals(tagname);
750         if (DTM.ELEMENT_NODE == retNode.getNodeType())
751         {
752           NodeList nodeList = retNode.getChildNodes();
753           for (int i = 0; i < nodeList.getLength(); i++)
754           {
755             traverseChildren(listVector, nodeList.item(i), tagname,
756                              isTagNameWildCard);
757           }
758         } else if (DTM.DOCUMENT_NODE == retNode.getNodeType()) {
759           traverseChildren(listVector, dtm.getNode(node), tagname,
760                            isTagNameWildCard);
761         }
762       }
763       int size = listVector.size();
764       NodeSet nodeSet = new NodeSet(size);
765       for (int i = 0; i < size; i++)
766       {
767         nodeSet.addNode((Node) listVector.elementAt(i));
768       }
769       return (NodeList) nodeSet;
770  }
771  /**
772   *
773   * @param listVector
774   * @param tempNode
775   * @param tagname
776   * @param isTagNameWildCard
777   *
778   *
779   * Private method to be used for recursive iterations to obtain elements by tag name.
780   */
781  private final void traverseChildren
782  (
783    Vector listVector,
784    Node tempNode,
785    String tagname,
786    boolean isTagNameWildCard) {
787    if (tempNode == null)
788    {
789      return;
790    }
791    else
792    {
793      if (tempNode.getNodeType() == DTM.ELEMENT_NODE
794            && (isTagNameWildCard || tempNode.getNodeName().equals(tagname)))
795      {
796        listVector.add(tempNode);
797      }
798      if(tempNode.hasChildNodes())
799      {
800        NodeList nodeList = tempNode.getChildNodes();
801        for (int i = 0; i < nodeList.getLength(); i++)
802        {
803          traverseChildren(listVector, nodeList.item(i), tagname,
804                           isTagNameWildCard);
805        }
806      }
807    }
808  }
809
810  /**
811   *
812   * @param importedNode
813   * @param deep
814   *
815   *
816   *
817   * @throws DOMException
818   * @see org.w3c.dom.Document as of DOM Level 2 -- DTMNodeProxy is read-only
819   */
820  public final Node importNode(Node importedNode, boolean deep)
821    throws DOMException
822  {
823    throw new DTMDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
824  }
825
826  /**
827   *
828   * @param namespaceURI
829   * @param qualifiedName
830   *
831   *
832   *
833   * @throws DOMException
834   * @see org.w3c.dom.Document as of DOM Level 2
835   */
836  public final Element createElementNS(
837                                       String namespaceURI, String qualifiedName) throws DOMException
838  {
839    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
840  }
841
842  /**
843   *
844   * @param namespaceURI
845   * @param qualifiedName
846   *
847   *
848   *
849   * @throws DOMException
850   * @see org.w3c.dom.Document as of DOM Level 2
851   */
852  public final Attr createAttributeNS(
853                                      String namespaceURI, String qualifiedName) throws DOMException
854  {
855    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
856  }
857
858  /**
859   *
860   * @param namespaceURI
861   * @param localName
862   *
863   *
864   * @see org.w3c.dom.Document as of DOM Level 2
865   */
866  public final NodeList getElementsByTagNameNS(String namespaceURI,
867                                               String localName)
868  {
869    Vector listVector = new Vector();
870    Node retNode = dtm.getNode(node);
871    if (retNode != null)
872    {
873      boolean isNamespaceURIWildCard = "*".equals(namespaceURI);
874      boolean isLocalNameWildCard    = "*".equals(localName);
875      if (DTM.ELEMENT_NODE == retNode.getNodeType())
876      {
877        NodeList nodeList = retNode.getChildNodes();
878        for(int i = 0; i < nodeList.getLength(); i++)
879        {
880          traverseChildren(listVector, nodeList.item(i), namespaceURI, localName, isNamespaceURIWildCard, isLocalNameWildCard);
881        }
882      }
883      else if(DTM.DOCUMENT_NODE == retNode.getNodeType())
884      {
885        traverseChildren(listVector, dtm.getNode(node), namespaceURI, localName, isNamespaceURIWildCard, isLocalNameWildCard);
886      }
887    }
888    int size = listVector.size();
889    NodeSet nodeSet = new NodeSet(size);
890    for (int i = 0; i < size; i++)
891    {
892      nodeSet.addNode((Node)listVector.elementAt(i));
893    }
894    return (NodeList) nodeSet;
895  }
896  /**
897   *
898   * @param listVector
899   * @param tempNode
900   * @param namespaceURI
901   * @param localname
902   * @param isNamespaceURIWildCard
903   * @param isLocalNameWildCard
904   *
905   * Private method to be used for recursive iterations to obtain elements by tag name
906   * and namespaceURI.
907   */
908  private final void traverseChildren
909  (
910   Vector listVector,
911   Node tempNode,
912   String namespaceURI,
913   String localname,
914   boolean isNamespaceURIWildCard,
915   boolean isLocalNameWildCard)
916   {
917    if (tempNode == null)
918    {
919      return;
920    }
921    else
922    {
923      if (tempNode.getNodeType() == DTM.ELEMENT_NODE
924              && (isLocalNameWildCard
925                      || tempNode.getLocalName().equals(localname)))
926      {
927        String nsURI = tempNode.getNamespaceURI();
928        if ((namespaceURI == null && nsURI == null)
929               || isNamespaceURIWildCard
930               || (namespaceURI != null && namespaceURI.equals(nsURI)))
931        {
932          listVector.add(tempNode);
933        }
934      }
935      if(tempNode.hasChildNodes())
936      {
937        NodeList nl = tempNode.getChildNodes();
938        for(int i = 0; i < nl.getLength(); i++)
939        {
940          traverseChildren(listVector, nl.item(i), namespaceURI, localname,
941                           isNamespaceURIWildCard, isLocalNameWildCard);
942        }
943      }
944    }
945  }
946  /**
947   *
948   * @param elementId
949   *
950   *
951   * @see org.w3c.dom.Document as of DOM Level 2
952   */
953  public final Element getElementById(String elementId)
954  {
955       return (Element) dtm.getNode(dtm.getElementById(elementId));
956  }
957
958  /**
959   *
960   * @param offset
961   *
962   *
963   *
964   * @throws DOMException
965   * @see org.w3c.dom.Text
966   */
967  public final Text splitText(int offset) throws DOMException
968  {
969    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
970  }
971
972  /**
973   *
974   *
975   *
976   * @throws DOMException
977   * @see org.w3c.dom.CharacterData
978   */
979  public final String getData() throws DOMException
980  {
981    return dtm.getNodeValue(node);
982  }
983
984  /**
985   *
986   * @param data
987   *
988   * @throws DOMException
989   * @see org.w3c.dom.CharacterData
990   */
991  public final void setData(String data) throws DOMException
992  {
993    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
994  }
995
996  /**
997   *
998   *
999   * @see org.w3c.dom.CharacterData
1000   */
1001  public final int getLength()
1002  {
1003    // %OPT% This should do something smarter?
1004    return dtm.getNodeValue(node).length();
1005  }
1006
1007  /**
1008   *
1009   * @param offset
1010   * @param count
1011   *
1012   *
1013   *
1014   * @throws DOMException
1015   * @see org.w3c.dom.CharacterData
1016   */
1017  public final String substringData(int offset, int count) throws DOMException
1018  {
1019    return getData().substring(offset,offset+count);
1020  }
1021
1022  /**
1023   *
1024   * @param arg
1025   *
1026   * @throws DOMException
1027   * @see org.w3c.dom.CharacterData
1028   */
1029  public final void appendData(String arg) throws DOMException
1030  {
1031    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1032  }
1033
1034  /**
1035   *
1036   * @param offset
1037   * @param arg
1038   *
1039   * @throws DOMException
1040   * @see org.w3c.dom.CharacterData
1041   */
1042  public final void insertData(int offset, String arg) throws DOMException
1043  {
1044    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1045  }
1046
1047  /**
1048   *
1049   * @param offset
1050   * @param count
1051   *
1052   * @throws DOMException
1053   * @see org.w3c.dom.CharacterData
1054   */
1055  public final void deleteData(int offset, int count) throws DOMException
1056  {
1057    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1058  }
1059
1060  /**
1061   *
1062   * @param offset
1063   * @param count
1064   * @param arg
1065   *
1066   * @throws DOMException
1067   * @see org.w3c.dom.CharacterData
1068   */
1069  public final void replaceData(int offset, int count, String arg)
1070    throws DOMException
1071  {
1072    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1073  }
1074
1075  /**
1076   *
1077   *
1078   * @see org.w3c.dom.Element
1079   */
1080  public final String getTagName()
1081  {
1082    return dtm.getNodeName(node);
1083  }
1084
1085  /**
1086   *
1087   * @param name
1088   *
1089   *
1090   * @see org.w3c.dom.Element
1091   */
1092  public final String getAttribute(String name)
1093  {
1094
1095    DTMNamedNodeMap  map = new DTMNamedNodeMap(dtm, node);
1096    Node node = map.getNamedItem(name);
1097    return (null == node) ? EMPTYSTRING : node.getNodeValue();
1098  }
1099
1100  /**
1101   *
1102   * @param name
1103   * @param value
1104   *
1105   * @throws DOMException
1106   * @see org.w3c.dom.Element
1107   */
1108  public final void setAttribute(String name, String value)
1109    throws DOMException
1110  {
1111    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1112  }
1113
1114  /**
1115   *
1116   * @param name
1117   *
1118   * @throws DOMException
1119   * @see org.w3c.dom.Element
1120   */
1121  public final void removeAttribute(String name) throws DOMException
1122  {
1123    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1124  }
1125
1126  /**
1127   *
1128   * @param name
1129   *
1130   *
1131   * @see org.w3c.dom.Element
1132   */
1133  public final Attr getAttributeNode(String name)
1134  {
1135
1136    DTMNamedNodeMap  map = new DTMNamedNodeMap(dtm, node);
1137    return (Attr)map.getNamedItem(name);
1138  }
1139
1140  /**
1141   *
1142   * @param newAttr
1143   *
1144   *
1145   *
1146   * @throws DOMException
1147   * @see org.w3c.dom.Element
1148   */
1149  public final Attr setAttributeNode(Attr newAttr) throws DOMException
1150  {
1151    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1152  }
1153
1154  /**
1155   *
1156   * @param oldAttr
1157   *
1158   *
1159   *
1160   * @throws DOMException
1161   * @see org.w3c.dom.Element
1162   */
1163  public final Attr removeAttributeNode(Attr oldAttr) throws DOMException
1164  {
1165    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1166  }
1167
1168  /**
1169   * Introduced in DOM Level 2.
1170   *
1171   *
1172   */
1173  public boolean hasAttributes()
1174  {
1175    return DTM.NULL != dtm.getFirstAttribute(node);
1176  }
1177
1178  /** @see org.w3c.dom.Element */
1179  public final void normalize()
1180  {
1181    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1182  }
1183
1184  /**
1185   *
1186   * @param namespaceURI
1187   * @param localName
1188   *
1189   *
1190   * @see org.w3c.dom.Element
1191   */
1192  public final String getAttributeNS(String namespaceURI, String localName)
1193  {
1194       Node retNode = null;
1195       int n = dtm.getAttributeNode(node,namespaceURI,localName);
1196       if(n != DTM.NULL)
1197               retNode = dtm.getNode(n);
1198       return (null == retNode) ? EMPTYSTRING : retNode.getNodeValue();
1199  }
1200
1201  /**
1202   *
1203   * @param namespaceURI
1204   * @param qualifiedName
1205   * @param value
1206   *
1207   * @throws DOMException
1208   * @see org.w3c.dom.Element
1209   */
1210  public final void setAttributeNS(
1211                                   String namespaceURI, String qualifiedName, String value)
1212    throws DOMException
1213  {
1214    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1215  }
1216
1217  /**
1218   *
1219   * @param namespaceURI
1220   * @param localName
1221   *
1222   * @throws DOMException
1223   * @see org.w3c.dom.Element
1224   */
1225  public final void removeAttributeNS(String namespaceURI, String localName)
1226    throws DOMException
1227  {
1228    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1229  }
1230
1231  /**
1232   *
1233   * @param namespaceURI
1234   * @param localName
1235   *
1236   *
1237   * @see org.w3c.dom.Element
1238   */
1239  public final Attr getAttributeNodeNS(String namespaceURI, String localName)
1240  {
1241       Attr retAttr = null;
1242       int n = dtm.getAttributeNode(node,namespaceURI,localName);
1243       if(n != DTM.NULL)
1244               retAttr = (Attr) dtm.getNode(n);
1245       return retAttr;
1246  }
1247
1248  /**
1249   *
1250   * @param newAttr
1251   *
1252   *
1253   *
1254   * @throws DOMException
1255   * @see org.w3c.dom.Element
1256   */
1257  public final Attr setAttributeNodeNS(Attr newAttr) throws DOMException
1258  {
1259    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1260  }
1261
1262  /**
1263   *
1264   *
1265   * @see org.w3c.dom.Attr
1266   */
1267  public final String getName()
1268  {
1269    return dtm.getNodeName(node);
1270  }
1271
1272  /**
1273   *
1274   *
1275   * @see org.w3c.dom.Attr
1276   */
1277  public final boolean getSpecified()
1278  {
1279    // We really don't know which attributes might have come from the
1280    // source document versus from the DTD. Treat them all as having
1281    // been provided by the user.
1282    // %REVIEW% if/when we become aware of DTDs/schemae.
1283    return true;
1284  }
1285
1286  /**
1287   *
1288   *
1289   * @see org.w3c.dom.Attr
1290   */
1291  public final String getValue()
1292  {
1293    return dtm.getNodeValue(node);
1294  }
1295
1296  /**
1297   *
1298   * @param value
1299   * @see org.w3c.dom.Attr
1300   */
1301  public final void setValue(String value)
1302  {
1303    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1304  }
1305
1306  /**
1307   * Get the owner element of an attribute.
1308   *
1309   *
1310   * @see org.w3c.dom.Attr as of DOM Level 2
1311   */
1312  public final Element getOwnerElement()
1313  {
1314    if (getNodeType() != Node.ATTRIBUTE_NODE)
1315      return null;
1316    // In XPath and DTM data models, unlike DOM, an Attr's parent is its
1317    // owner element.
1318    int newnode = dtm.getParent(node);
1319    return (newnode == DTM.NULL) ? null : (Element)(dtm.getNode(newnode));
1320  }
1321
1322  /**
1323   * NEEDSDOC Method adoptNode
1324   *
1325   *
1326   * NEEDSDOC @param source
1327   *
1328   *
1329   *
1330   * @throws DOMException
1331   */
1332  public Node adoptNode(Node source) throws DOMException
1333  {
1334
1335    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1336  }
1337
1338  /**
1339   * <p>Based on the <a
1340   * href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407'>Document
1341   * Object Model (DOM) Level 3 Core Specification of 07 April 2004.</a>.
1342   * <p>
1343   * An attribute specifying, as part of the XML declaration, the encoding
1344   * of this document. This is <code>null</code> when unspecified.
1345   * @since DOM Level 3
1346   *
1347   *
1348   */
1349  public String getInputEncoding()
1350  {
1351
1352    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1353  }
1354
1355  /**
1356   * <p>Based on the <a
1357   * href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407'>Document
1358   * Object Model (DOM) Level 3 Core Specification of 07 April 2004.</a>.
1359   * <p>
1360   * An attribute specifying whether errors checking is enforced or not.
1361   * When set to <code>false</code>, the implementation is free to not
1362   * test every possible error case normally defined on DOM operations,
1363   * and not raise any <code>DOMException</code>. In case of error, the
1364   * behavior is undefined. This attribute is <code>true</code> by
1365   * defaults.
1366   * @since DOM Level 3
1367   *
1368   *
1369   */
1370  public boolean getStrictErrorChecking()
1371  {
1372
1373    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1374  }
1375
1376  /**
1377   * <p>Based on the <a
1378   * href='http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407'>Document
1379   * Object Model (DOM) Level 3 Core Specification of 07 April 2004.</a>.
1380   * <p>
1381   * An attribute specifying whether errors checking is enforced or not.
1382   * When set to <code>false</code>, the implementation is free to not
1383   * test every possible error case normally defined on DOM operations,
1384   * and not raise any <code>DOMException</code>. In case of error, the
1385   * behavior is undefined. This attribute is <code>true</code> by
1386   * defaults.
1387   * @since DOM Level 3
1388   *
1389   * NEEDSDOC @param strictErrorChecking
1390   */
1391  public void setStrictErrorChecking(boolean strictErrorChecking)
1392  {
1393    throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1394  }
1395
1396  /** Inner class to support getDOMImplementation.
1397   */
1398  static class DTMNodeProxyImplementation implements DOMImplementation
1399  {
1400    public DocumentType createDocumentType(String qualifiedName,String publicId, String systemId)
1401    {
1402      throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1403    }
1404    public Document createDocument(String namespaceURI,String qualfiedName,DocumentType doctype)
1405    {
1406      // Could create a DTM... but why, when it'd have to be permanantly empty?
1407      throw new DTMDOMException(DOMException.NOT_SUPPORTED_ERR);
1408    }
1409    /** Ask whether we support a given DOM feature.
1410     *
1411     * In fact, we do not _fully_ support any DOM feature -- we're a
1412     * read-only subset -- so arguably we should always return false.
1413     * On the other hand, it may be more practically useful to return
1414     * true and simply treat the whole DOM as read-only, failing on the
1415     * methods we can't support. I'm not sure which would be more useful
1416     * to the caller.
1417     */
1418    public boolean hasFeature(String feature,String version)
1419    {
1420      if( ("CORE".equals(feature.toUpperCase()) || "XML".equals(feature.toUpperCase()))
1421					&&
1422          ("1.0".equals(version) || "2.0".equals(version))
1423          )
1424        return true;
1425      return false;
1426    }
1427
1428    /**
1429     *  This method returns a specialized object which implements the
1430     * specialized APIs of the specified feature and version. The
1431     * specialized object may also be obtained by using binding-specific
1432     * casting methods but is not necessarily expected to, as discussed in Mixed DOM implementations
1433.
1434     * @param feature The name of the feature requested (case-insensitive).
1435     * @param version  This is the version number of the feature to test. If
1436     *   the version is <code>null</code> or the empty string, supporting
1437     *   any version of the feature will cause the method to return an
1438     *   object that supports at least one version of the feature.
1439     * @return  Returns an object which implements the specialized APIs of
1440     *   the specified feature and version, if any, or <code>null</code> if
1441     *   there is no object which implements interfaces associated with that
1442     *   feature. If the <code>DOMObject</code> returned by this method
1443     *   implements the <code>Node</code> interface, it must delegate to the
1444     *   primary core <code>Node</code> and not return results inconsistent
1445     *   with the primary core <code>Node</code> such as attributes,
1446     *   childNodes, etc.
1447     * @since DOM Level 3
1448     */
1449    public Object getFeature(String feature, String version) {
1450        // we don't have any alternate node, either this node does the job
1451        // or we don't have anything that does
1452        //return hasFeature(feature, version) ? this : null;
1453        return null; //PENDING
1454    }
1455
1456  }
1457
1458
1459    //RAMESH : Pending proper implementation of DOM Level 3
1460
1461    public Object setUserData(String key,
1462                              Object data,
1463                              UserDataHandler handler) {
1464        return getOwnerDocument().setUserData( key, data, handler);
1465    }
1466
1467    /**
1468     * Retrieves the object associated to a key on a this node. The object
1469     * must first have been set to this node by calling
1470     * <code>setUserData</code> with the same key.
1471     * @param key The key the object is associated to.
1472     * @return Returns the <code>DOMObject</code> associated to the given key
1473     *   on this node, or <code>null</code> if there was none.
1474     * @since DOM Level 3
1475     */
1476    public Object getUserData(String key) {
1477        return getOwnerDocument().getUserData( key);
1478    }
1479
1480    /**
1481     *  This method returns a specialized object which implements the
1482     * specialized APIs of the specified feature and version. The
1483     * specialized object may also be obtained by using binding-specific
1484     * casting methods but is not necessarily expected to, as discussed in Mixed DOM implementations.
1485     * @param feature The name of the feature requested (case-insensitive).
1486     * @param version  This is the version number of the feature to test. If
1487     *   the version is <code>null</code> or the empty string, supporting
1488     *   any version of the feature will cause the method to return an
1489     *   object that supports at least one version of the feature.
1490     * @return  Returns an object which implements the specialized APIs of
1491     *   the specified feature and version, if any, or <code>null</code> if
1492     *   there is no object which implements interfaces associated with that
1493     *   feature. If the <code>DOMObject</code> returned by this method
1494     *   implements the <code>Node</code> interface, it must delegate to the
1495     *   primary core <code>Node</code> and not return results inconsistent
1496     *   with the primary core <code>Node</code> such as attributes,
1497     *   childNodes, etc.
1498     * @since DOM Level 3
1499     */
1500    public Object getFeature(String feature, String version) {
1501        // we don't have any alternate node, either this node does the job
1502        // or we don't have anything that does
1503        return isSupported(feature, version) ? this : null;
1504    }
1505
1506    /**
1507     * Tests whether two nodes are equal.
1508     * <br>This method tests for equality of nodes, not sameness (i.e.,
1509     * whether the two nodes are references to the same object) which can be
1510     * tested with <code>Node.isSameNode</code>. All nodes that are the same
1511     * will also be equal, though the reverse may not be true.
1512     * <br>Two nodes are equal if and only if the following conditions are
1513     * satisfied: The two nodes are of the same type.The following string
1514     * attributes are equal: <code>nodeName</code>, <code>localName</code>,
1515     * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
1516     * , <code>baseURI</code>. This is: they are both <code>null</code>, or
1517     * they have the same length and are character for character identical.
1518     * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
1519     * This is: they are both <code>null</code>, or they have the same
1520     * length and for each node that exists in one map there is a node that
1521     * exists in the other map and is equal, although not necessarily at the
1522     * same index.The <code>childNodes</code> <code>NodeLists</code> are
1523     * equal. This is: they are both <code>null</code>, or they have the
1524     * same length and contain equal nodes at the same index. This is true
1525     * for <code>Attr</code> nodes as for any other type of node. Note that
1526     * normalization can affect equality; to avoid this, nodes should be
1527     * normalized before being compared.
1528     * <br>For two <code>DocumentType</code> nodes to be equal, the following
1529     * conditions must also be satisfied: The following string attributes
1530     * are equal: <code>publicId</code>, <code>systemId</code>,
1531     * <code>internalSubset</code>.The <code>entities</code>
1532     * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
1533     * <code>NamedNodeMaps</code> are equal.
1534     * <br>On the other hand, the following do not affect equality: the
1535     * <code>ownerDocument</code> attribute, the <code>specified</code>
1536     * attribute for <code>Attr</code> nodes, the
1537     * <code>isWhitespaceInElementContent</code> attribute for
1538     * <code>Text</code> nodes, as well as any user data or event listeners
1539     * registered on the nodes.
1540     * @param arg The node to compare equality with.
1541     * @param deep If <code>true</code>, recursively compare the subtrees; if
1542     *   <code>false</code>, compare only the nodes themselves (and its
1543     *   attributes, if it is an <code>Element</code>).
1544     * @return If the nodes, and possibly subtrees are equal,
1545     *   <code>true</code> otherwise <code>false</code>.
1546     * @since DOM Level 3
1547     */
1548    public boolean isEqualNode(Node arg) {
1549        if (arg == this) {
1550            return true;
1551        }
1552        if (arg.getNodeType() != getNodeType()) {
1553            return false;
1554        }
1555        // in theory nodeName can't be null but better be careful
1556        // who knows what other implementations may be doing?...
1557        if (getNodeName() == null) {
1558            if (arg.getNodeName() != null) {
1559                return false;
1560            }
1561        }
1562        else if (!getNodeName().equals(arg.getNodeName())) {
1563            return false;
1564        }
1565
1566        if (getLocalName() == null) {
1567            if (arg.getLocalName() != null) {
1568                return false;
1569            }
1570        }
1571        else if (!getLocalName().equals(arg.getLocalName())) {
1572            return false;
1573        }
1574
1575        if (getNamespaceURI() == null) {
1576            if (arg.getNamespaceURI() != null) {
1577                return false;
1578            }
1579        }
1580        else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
1581            return false;
1582        }
1583
1584        if (getPrefix() == null) {
1585            if (arg.getPrefix() != null) {
1586                return false;
1587            }
1588        }
1589        else if (!getPrefix().equals(arg.getPrefix())) {
1590            return false;
1591        }
1592
1593        if (getNodeValue() == null) {
1594            if (arg.getNodeValue() != null) {
1595                return false;
1596            }
1597        }
1598        else if (!getNodeValue().equals(arg.getNodeValue())) {
1599            return false;
1600        }
1601    /*
1602        if (getBaseURI() == null) {
1603            if (((NodeImpl) arg).getBaseURI() != null) {
1604                return false;
1605            }
1606        }
1607        else if (!getBaseURI().equals(((NodeImpl) arg).getBaseURI())) {
1608            return false;
1609        }
1610*/
1611        return true;
1612    }
1613
1614    /**
1615     * DOM Level 3:
1616     * Look up the namespace URI associated to the given prefix, starting from this node.
1617     * Use lookupNamespaceURI(null) to lookup the default namespace
1618     *
1619     * @param namespaceURI
1620     * @return th URI for the namespace
1621     * @since DOM Level 3
1622     */
1623    public String lookupNamespaceURI(String specifiedPrefix) {
1624        short type = this.getNodeType();
1625        switch (type) {
1626        case Node.ELEMENT_NODE : {
1627
1628                String namespace = this.getNamespaceURI();
1629                String prefix = this.getPrefix();
1630                if (namespace !=null) {
1631                    // REVISIT: is it possible that prefix is empty string?
1632                    if (specifiedPrefix== null && prefix==specifiedPrefix) {
1633                        // looking for default namespace
1634                        return namespace;
1635                    } else if (prefix != null && prefix.equals(specifiedPrefix)) {
1636                        // non default namespace
1637                        return namespace;
1638                    }
1639                }
1640                if (this.hasAttributes()) {
1641                    NamedNodeMap map = this.getAttributes();
1642                    int length = map.getLength();
1643                    for (int i=0;i<length;i++) {
1644                        Node attr = map.item(i);
1645                        String attrPrefix = attr.getPrefix();
1646                        String value = attr.getNodeValue();
1647                        namespace = attr.getNamespaceURI();
1648                        if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
1649                            // at this point we are dealing with DOM Level 2 nodes only
1650                            if (specifiedPrefix == null &&
1651                                attr.getNodeName().equals("xmlns")) {
1652                                // default namespace
1653                                return value;
1654                            } else if (attrPrefix !=null &&
1655                                       attrPrefix.equals("xmlns") &&
1656                                       attr.getLocalName().equals(specifiedPrefix)) {
1657                 // non default namespace
1658                                return value;
1659                            }
1660                        }
1661                    }
1662                }
1663		/*
1664                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1665                if (ancestor != null) {
1666                    return ancestor.lookupNamespaceURI(specifiedPrefix);
1667                }
1668		*/
1669                return null;
1670            }
1671/*
1672        case Node.DOCUMENT_NODE : {
1673                return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix) ;
1674            }
1675*/
1676        case Node.ENTITY_NODE :
1677        case Node.NOTATION_NODE:
1678        case Node.DOCUMENT_FRAGMENT_NODE:
1679        case Node.DOCUMENT_TYPE_NODE:
1680            // type is unknown
1681            return null;
1682        case Node.ATTRIBUTE_NODE:{
1683                if (this.getOwnerElement().getNodeType() == Node.ELEMENT_NODE) {
1684                    return getOwnerElement().lookupNamespaceURI(specifiedPrefix);
1685                }
1686                return null;
1687            }
1688        default:{
1689	   /*
1690                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1691                if (ancestor != null) {
1692                    return ancestor.lookupNamespaceURI(specifiedPrefix);
1693                }
1694             */
1695                return null;
1696            }
1697
1698        }
1699    }
1700
1701    /**
1702     *  DOM Level 3:
1703     *  This method checks if the specified <code>namespaceURI</code> is the
1704     *  default namespace or not.
1705     *  @param namespaceURI The namespace URI to look for.
1706     *  @return  <code>true</code> if the specified <code>namespaceURI</code>
1707     *   is the default namespace, <code>false</code> otherwise.
1708     * @since DOM Level 3
1709     */
1710    public boolean isDefaultNamespace(String namespaceURI){
1711       /*
1712        // REVISIT: remove casts when DOM L3 becomes REC.
1713        short type = this.getNodeType();
1714        switch (type) {
1715        case Node.ELEMENT_NODE: {
1716            String namespace = this.getNamespaceURI();
1717            String prefix = this.getPrefix();
1718
1719            // REVISIT: is it possible that prefix is empty string?
1720            if (prefix == null || prefix.length() == 0) {
1721                if (namespaceURI == null) {
1722                    return (namespace == namespaceURI);
1723                }
1724                return namespaceURI.equals(namespace);
1725            }
1726            if (this.hasAttributes()) {
1727                ElementImpl elem = (ElementImpl)this;
1728                NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
1729                if (attr != null) {
1730                    String value = attr.getNodeValue();
1731                    if (namespaceURI == null) {
1732                        return (namespace == value);
1733                    }
1734                    return namespaceURI.equals(value);
1735                }
1736            }
1737
1738            NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1739            if (ancestor != null) {
1740                return ancestor.isDefaultNamespace(namespaceURI);
1741            }
1742            return false;
1743        }
1744        case Node.DOCUMENT_NODE:{
1745                return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
1746            }
1747
1748        case Node.ENTITY_NODE :
1749          case Node.NOTATION_NODE:
1750        case Node.DOCUMENT_FRAGMENT_NODE:
1751        case Node.DOCUMENT_TYPE_NODE:
1752            // type is unknown
1753            return false;
1754        case Node.ATTRIBUTE_NODE:{
1755                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1756                    return ownerNode.isDefaultNamespace(namespaceURI);
1757
1758                }
1759                return false;
1760            }
1761        default:{
1762                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1763                if (ancestor != null) {
1764                    return ancestor.isDefaultNamespace(namespaceURI);
1765                }
1766                return false;
1767            }
1768
1769        }
1770*/
1771        return false;
1772    }
1773
1774    /**
1775     * DOM Level 3:
1776     * Look up the prefix associated to the given namespace URI, starting from this node.
1777     *
1778     * @param namespaceURI
1779     * @return the prefix for the namespace
1780     */
1781    public String lookupPrefix(String namespaceURI){
1782
1783        // REVISIT: When Namespaces 1.1 comes out this may not be true
1784        // Prefix can't be bound to null namespace
1785        if (namespaceURI == null) {
1786            return null;
1787        }
1788
1789        short type = this.getNodeType();
1790
1791        switch (type) {
1792/*
1793        case Node.ELEMENT_NODE: {
1794
1795                String namespace = this.getNamespaceURI(); // to flip out children
1796                return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
1797            }
1798
1799        case Node.DOCUMENT_NODE:{
1800                return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
1801            }
1802*/
1803        case Node.ENTITY_NODE :
1804        case Node.NOTATION_NODE:
1805        case Node.DOCUMENT_FRAGMENT_NODE:
1806        case Node.DOCUMENT_TYPE_NODE:
1807            // type is unknown
1808            return null;
1809        case Node.ATTRIBUTE_NODE:{
1810                if (this.getOwnerElement().getNodeType() == Node.ELEMENT_NODE) {
1811                    return getOwnerElement().lookupPrefix(namespaceURI);
1812
1813                }
1814                return null;
1815            }
1816        default:{
1817/*
1818                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1819                if (ancestor != null) {
1820                    return ancestor.lookupPrefix(namespaceURI);
1821                }
1822*/
1823                return null;
1824            }
1825         }
1826    }
1827
1828    /**
1829     * Returns whether this node is the same node as the given one.
1830     * <br>This method provides a way to determine whether two
1831     * <code>Node</code> references returned by the implementation reference
1832     * the same object. When two <code>Node</code> references are references
1833     * to the same object, even if through a proxy, the references may be
1834     * used completely interchangably, such that all attributes have the
1835     * same values and calling the same DOM method on either reference
1836     * always has exactly the same effect.
1837     * @param other The node to test against.
1838     * @return Returns <code>true</code> if the nodes are the same,
1839     *   <code>false</code> otherwise.
1840     * @since DOM Level 3
1841     */
1842    public boolean isSameNode(Node other) {
1843        // we do not use any wrapper so the answer is obvious
1844        return this == other;
1845    }
1846
1847    /**
1848     * This attribute returns the text content of this node and its
1849     * descendants. When it is defined to be null, setting it has no effect.
1850     * When set, any possible children this node may have are removed and
1851     * replaced by a single <code>Text</code> node containing the string
1852     * this attribute is set to. On getting, no serialization is performed,
1853     * the returned string does not contain any markup. No whitespace
1854     * normalization is performed, the returned string does not contain the
1855     * element content whitespaces . Similarly, on setting, no parsing is
1856     * performed either, the input string is taken as pure textual content.
1857     * <br>The string returned is made of the text content of this node
1858     * depending on its type, as defined below:
1859     * <table border='1'>
1860     * <tr>
1861     * <th>Node type</th>
1862     * <th>Content</th>
1863     * </tr>
1864     * <tr>
1865     * <td valign='top' rowspan='1' colspan='1'>
1866     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1867     * DOCUMENT_FRAGMENT_NODE</td>
1868     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1869     * attribute value of every child node, excluding COMMENT_NODE and
1870     * PROCESSING_INSTRUCTION_NODE nodes</td>
1871     * </tr>
1872     * <tr>
1873     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1874     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1875     * <td valign='top' rowspan='1' colspan='1'>
1876     * <code>nodeValue</code></td>
1877     * </tr>
1878     * <tr>
1879     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1880     * <td valign='top' rowspan='1' colspan='1'>
1881     * null</td>
1882     * </tr>
1883     * </table>
1884     * @exception DOMException
1885     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1886     * @exception DOMException
1887     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1888     *   fit in a <code>DOMString</code> variable on the implementation
1889     *   platform.
1890     * @since DOM Level 3
1891     */
1892    public void setTextContent(String textContent)
1893        throws DOMException {
1894        setNodeValue(textContent);
1895    }
1896
1897    /**
1898     * This attribute returns the text content of this node and its
1899     * descendants. When it is defined to be null, setting it has no effect.
1900     * When set, any possible children this node may have are removed and
1901     * replaced by a single <code>Text</code> node containing the string
1902     * this attribute is set to. On getting, no serialization is performed,
1903     * the returned string does not contain any markup. No whitespace
1904     * normalization is performed, the returned string does not contain the
1905     * element content whitespaces . Similarly, on setting, no parsing is
1906     * performed either, the input string is taken as pure textual content.
1907     * <br>The string returned is made of the text content of this node
1908     * depending on its type, as defined below:
1909     * <table border='1'>
1910     * <tr>
1911     * <th>Node type</th>
1912     * <th>Content</th>
1913     * </tr>
1914     * <tr>
1915     * <td valign='top' rowspan='1' colspan='1'>
1916     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1917     * DOCUMENT_FRAGMENT_NODE</td>
1918     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1919     * attribute value of every child node, excluding COMMENT_NODE and
1920     * PROCESSING_INSTRUCTION_NODE nodes</td>
1921     * </tr>
1922     * <tr>
1923     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1924     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1925     * <td valign='top' rowspan='1' colspan='1'>
1926     * <code>nodeValue</code></td>
1927     * </tr>
1928     * <tr>
1929     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1930     * <td valign='top' rowspan='1' colspan='1'>
1931     * null</td>
1932     * </tr>
1933     * </table>
1934     * @exception DOMException
1935     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1936     * @exception DOMException
1937     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1938     *   fit in a <code>DOMString</code> variable on the implementation
1939     *   platform.
1940     * @since DOM Level 3
1941     */
1942    public String getTextContent() throws DOMException {
1943        return dtm.getStringValue(node).toString();
1944    }
1945
1946    /**
1947     * Compares a node with this node with regard to their position in the
1948     * document.
1949     * @param other The node to compare against this node.
1950     * @return Returns how the given node is positioned relatively to this
1951     *   node.
1952     * @since DOM Level 3
1953     */
1954    public short compareDocumentPosition(Node other) throws DOMException {
1955        return 0;
1956    }
1957
1958    /**
1959     * The absolute base URI of this node or <code>null</code> if undefined.
1960     * This value is computed according to . However, when the
1961     * <code>Document</code> supports the feature "HTML" , the base URI is
1962     * computed using first the value of the href attribute of the HTML BASE
1963     * element if any, and the value of the <code>documentURI</code>
1964     * attribute from the <code>Document</code> interface otherwise.
1965     * <br> When the node is an <code>Element</code>, a <code>Document</code>
1966     * or a a <code>ProcessingInstruction</code>, this attribute represents
1967     * the properties [base URI] defined in . When the node is a
1968     * <code>Notation</code>, an <code>Entity</code>, or an
1969     * <code>EntityReference</code>, this attribute represents the
1970     * properties [declaration base URI] in the . How will this be affected
1971     * by resolution of relative namespace URIs issue?It's not.Should this
1972     * only be on Document, Element, ProcessingInstruction, Entity, and
1973     * Notation nodes, according to the infoset? If not, what is it equal to
1974     * on other nodes? Null? An empty string? I think it should be the
1975     * parent's.No.Should this be read-only and computed or and actual
1976     * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
1977     * teleconference 30 May 2001).If the base HTML element is not yet
1978     * attached to a document, does the insert change the Document.baseURI?
1979     * Yes. (F2F 26 Sep 2001)
1980     * @since DOM Level 3
1981     */
1982    public String getBaseURI() {
1983        return null;
1984    }
1985
1986    /**
1987     * DOM Level 3
1988     * Renaming node
1989     */
1990    public Node renameNode(Node n,
1991                           String namespaceURI,
1992                           String name)
1993                           throws DOMException{
1994        return n;
1995    }
1996
1997    /**
1998     *  DOM Level 3
1999     *  Normalize document.
2000     */
2001    public void normalizeDocument(){
2002
2003    }
2004
2005    /**
2006     *  The configuration used when <code>Document.normalizeDocument</code> is
2007     * invoked.
2008     * @since DOM Level 3
2009     */
2010    public DOMConfiguration getDomConfig(){
2011       return null;
2012    }
2013
2014    /** DOM Level 3 feature: documentURI */
2015    protected String fDocumentURI;
2016
2017    /**
2018     * DOM Level 3
2019     */
2020    public void setDocumentURI(String documentURI){
2021
2022        fDocumentURI= documentURI;
2023    }
2024
2025    /**
2026     * DOM Level 3
2027     * The location of the document or <code>null</code> if undefined.
2028     * <br>Beware that when the <code>Document</code> supports the feature
2029     * "HTML" , the href attribute of the HTML BASE element takes precedence
2030     * over this attribute.
2031     * @since DOM Level 3
2032     */
2033    public String getDocumentURI(){
2034        return fDocumentURI;
2035    }
2036
2037    /** DOM Level 3 feature: Document actualEncoding */
2038    protected String actualEncoding;
2039
2040    /**
2041     * DOM Level 3
2042     * An attribute specifying the actual encoding of this document. This is
2043     * <code>null</code> otherwise.
2044     * <br> This attribute represents the property [character encoding scheme]
2045     * defined in .
2046     * @since DOM Level 3
2047     */
2048    public String getActualEncoding() {
2049        return actualEncoding;
2050    }
2051
2052    /**
2053     * DOM Level 3
2054     * An attribute specifying the actual encoding of this document. This is
2055     * <code>null</code> otherwise.
2056     * <br> This attribute represents the property [character encoding scheme]
2057     * defined in .
2058     * @since DOM Level 3
2059     */
2060    public void setActualEncoding(String value) {
2061        actualEncoding = value;
2062    }
2063
2064   /**
2065    * DOM Level 3
2066    */
2067    public Text replaceWholeText(String content)
2068                                 throws DOMException{
2069/*
2070
2071        if (needsSyncData()) {
2072            synchronizeData();
2073        }
2074
2075        // make sure we can make the replacement
2076        if (!canModify(nextSibling)) {
2077            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
2078                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null));
2079        }
2080
2081        Node parent = this.getParentNode();
2082        if (content == null || content.length() == 0) {
2083            // remove current node
2084            if (parent !=null) { // check if node in the tree
2085                parent.removeChild(this);
2086                return null;
2087            }
2088        }
2089        Text currentNode = null;
2090        if (isReadOnly()){
2091            Text newNode = this.ownerDocument().createTextNode(content);
2092            if (parent !=null) { // check if node in the tree
2093                parent.insertBefore(newNode, this);
2094                parent.removeChild(this);
2095                currentNode = newNode;
2096            } else {
2097                return newNode;
2098            }
2099        }  else {
2100            this.setData(content);
2101            currentNode = this;
2102        }
2103        Node sibling =  currentNode.getNextSibling();
2104        while ( sibling !=null) {
2105            parent.removeChild(sibling);
2106            sibling = currentNode.getNextSibling();
2107        }
2108
2109        return currentNode;
2110*/
2111        return null; //Pending
2112    }
2113
2114    /**
2115     * DOM Level 3
2116     * Returns all text of <code>Text</code> nodes logically-adjacent text
2117     * nodes to this node, concatenated in document order.
2118     * @since DOM Level 3
2119     */
2120    public String getWholeText(){
2121
2122/*
2123        if (needsSyncData()) {
2124            synchronizeData();
2125        }
2126        if (nextSibling == null) {
2127            return data;
2128        }
2129        StringBuffer buffer = new StringBuffer();
2130        if (data != null && data.length() != 0) {
2131            buffer.append(data);
2132        }
2133        getWholeText(nextSibling, buffer);
2134        return buffer.toString();
2135*/
2136        return null; // PENDING
2137    }
2138
2139    /**
2140     * DOM Level 3
2141     * Returns whether this text node contains whitespace in element content,
2142     * often abusively called "ignorable whitespace".
2143     */
2144    public boolean isElementContentWhitespace(){
2145        return false;
2146    }
2147
2148    /**
2149     * NON-DOM: set the type of this attribute to be ID type.
2150     *
2151     * @param id
2152     */
2153    public void setIdAttribute(boolean id){
2154        //PENDING
2155    }
2156
2157    /**
2158     * DOM Level 3: register the given attribute node as an ID attribute
2159     */
2160    public void setIdAttribute(String name, boolean makeId) {
2161        //PENDING
2162    }
2163
2164
2165    /**
2166     * DOM Level 3: register the given attribute node as an ID attribute
2167     */
2168    public void setIdAttributeNode(Attr at, boolean makeId) {
2169        //PENDING
2170    }
2171
2172    /**
2173     * DOM Level 3: register the given attribute node as an ID attribute
2174     */
2175    public void setIdAttributeNS(String namespaceURI, String localName,
2176                                    boolean makeId) {
2177        //PENDING
2178    }
2179
2180    public TypeInfo getSchemaTypeInfo(){
2181      return null; //PENDING
2182    }
2183
2184    public boolean isId() {
2185        return false; //PENDING
2186    }
2187
2188
2189    private String xmlEncoding;
2190
2191    public String getXmlEncoding( ) {
2192        return xmlEncoding;
2193    }
2194
2195    public void setXmlEncoding( String xmlEncoding ) {
2196        this.xmlEncoding = xmlEncoding;
2197    }
2198
2199    private boolean xmlStandalone;
2200
2201    public boolean getXmlStandalone() {
2202        return xmlStandalone;
2203    }
2204
2205    public void setXmlStandalone(boolean xmlStandalone) throws DOMException {
2206        this.xmlStandalone = xmlStandalone;
2207    }
2208
2209    private String xmlVersion;
2210
2211    public String getXmlVersion() {
2212        return xmlVersion;
2213    }
2214
2215    public void setXmlVersion(String xmlVersion) throws DOMException {
2216        this.xmlVersion = xmlVersion;
2217    }
2218}
2219