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