001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: DTMNodeProxy.java 889881 2009-12-12 03:47:15Z zongaro $
020     */
021    package org.apache.xml.dtm.ref;
022    
023    import java.util.Vector;
024    
025    import org.apache.xml.dtm.DTM;
026    import org.apache.xml.dtm.DTMDOMException;
027    import org.apache.xpath.NodeSet;
028    
029    import org.w3c.dom.Attr;
030    import org.w3c.dom.CDATASection;
031    import org.w3c.dom.Comment;
032    import org.w3c.dom.DOMException;
033    import org.w3c.dom.DOMImplementation;
034    import org.w3c.dom.Document;
035    import org.w3c.dom.DocumentFragment;
036    import org.w3c.dom.DocumentType;
037    import org.w3c.dom.Element;
038    import org.w3c.dom.EntityReference;
039    import org.w3c.dom.NamedNodeMap;
040    import org.w3c.dom.Node;
041    import org.w3c.dom.NodeList;
042    import org.w3c.dom.ProcessingInstruction;
043    import org.w3c.dom.Text;
044    
045    import org.w3c.dom.UserDataHandler;
046    import org.w3c.dom.DOMConfiguration;
047    import org.w3c.dom.TypeInfo;
048    
049    /**
050     * <code>DTMNodeProxy</code> presents a DOM Node API front-end to the DTM model.
051     * <p>
052     * It does _not_ attempt to address the "node identity" question; no effort
053     * is made to prevent the creation of multiple proxies referring to a single
054     * DTM node. Users can create a mechanism for managing this, or relinquish the
055     * use of "==" and use the .sameNodeAs() mechanism, which is under
056     * consideration for future versions of the DOM.
057     * <p>
058     * DTMNodeProxy may be subclassed further to present specific DOM node types.
059     *
060     * @see org.w3c.dom
061     * @xsl.usage internal
062     */
063    public class DTMNodeProxy
064      implements Node, Document, Text, Element, Attr,
065                       ProcessingInstruction, Comment, DocumentFragment
066    {
067    
068      /** The DTM for this node. */
069      public DTM dtm;
070    
071      /** The DTM node handle. */
072      int node;
073      
074      /** The return value as Empty String. */
075      private static final String EMPTYSTRING = "";
076              
077      /** The DOMImplementation object */
078      static final DOMImplementation implementation=new DTMNodeProxyImplementation();
079    
080      /**
081       * Create a DTMNodeProxy Node representing a specific Node in a DTM
082       *
083       * @param dtm The DTM Reference, must be non-null.
084       * @param node The DTM node handle.
085       */
086      public DTMNodeProxy(DTM dtm, int node)
087      {
088        this.dtm = dtm;
089        this.node = node;
090      }
091    
092      /**
093       * NON-DOM: Return the DTM model
094       *
095       * @return The DTM that this proxy is a representative for.
096       */
097      public final DTM getDTM()
098      {
099        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    }