KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xdm > nodes > NodeImpl


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.xdm.nodes;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.LinkedHashMap JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Map JavaDoc;
27 import javax.xml.XMLConstants JavaDoc;
28 //import org.netbeans.modules.xml.spi.dom.NamedNodeMapImpl;
29
import org.netbeans.modules.xml.spi.dom.NodeListImpl;
30 import org.netbeans.modules.xml.xdm.XDMModel;
31 import org.netbeans.modules.xml.xdm.visitor.PathFromRootVisitor;
32 import org.w3c.dom.*;
33
34 /**
35  * This class provides base implementation of Node Interface.
36  * @author Ajit
37  */

38 public abstract class NodeImpl implements Node, Cloneable JavaDoc {
39     
40     public static final String JavaDoc XMLNS = "xmlns"; // NOI18N
41

42     /* flag indicating if in tree */
43     private boolean inTree;
44     
45     /* The model to which the node belongs */
46     private XDMModel model;
47     
48     /* id of this node */
49     private int id;
50     
51     /* tokens */
52     private List JavaDoc<Token> tokens;
53     
54     /* child nodes */
55     private List JavaDoc<Node> children;
56     
57     /* attributes */
58     private List JavaDoc<Attribute> attributes = null;
59
60     /** Creates a new instance of BaseNode. sets id during creation */
61     NodeImpl() {
62         model = null;
63         inTree = false;
64         id = -1;
65     }
66     
67     /**
68      * Returns the id of this node
69      * @return id - the id of this node
70      */

71     public final int getId() {
72         return id;
73     }
74     
75     /**
76      * sets the id of this node
77      * @param id - the id of this node
78      */

79     private void setId(int nodeId) {
80         id = nodeId;
81     }
82     
83     @Override JavaDoc
84             public int hashCode() {
85         return (int) getId();
86     }
87     
88     /**
89      * Determines if the node is any tree
90      * @return Returns true is in tree, false otherwise
91      */

92     public final boolean isInTree() {
93         return inTree && getModel()!=null;
94     }
95     
96     /**
97      * Marks the node and all its children added to a tree.
98      */

99     public void addedToTree(XDMModel model) {
100         if (!isInTree()) {
101             inTree = true;
102             if(getModel() != model) {
103                 setModel(model);
104                 setId(model.getNextNodeId());
105             } else {
106                 if(getId() == -1)
107                     setId(model.getNextNodeId());
108             }
109             for (Node n: getChildren()) {
110                 n.addedToTree(model);
111             }
112             for (Node n: getAttributesForRead()) {
113                 n.addedToTree(model);
114             }
115         }
116     }
117     
118     private static interface UniqueId {
119         int nextId();
120     }
121     
122     private UniqueId createUniqueId() {
123         return new UniqueId() {
124             private int lastId = -1;
125             public int nextId() {
126                 return ++lastId;
127             }
128         };
129     }
130     
131     /**
132      * Recursively assigns node id's.
133      */

134     public void assignNodeIdRecursively() {
135         assignNodeId(createUniqueId());
136     }
137     
138     public void assignNodeId(UniqueId id) {
139         assert ! isInTree();
140         setId(id.nextId());
141         for (Node n: getChildren()) {
142             ((NodeImpl)n).assignNodeId(id);
143         }
144         for (Node n: getAttributesForRead()) {
145             ((NodeImpl)n).assignNodeId(id);
146         }
147     }
148     
149     public void assignNodeId(int id) {
150         assert ! isInTree();
151         setId(id);
152         for (Node n: getChildren()) {
153             ((NodeImpl)n).assignNodeId(id);
154         }
155         for (Node n: getAttributesForRead()) {
156             ((NodeImpl)n).assignNodeId(id);
157         }
158     }
159     
160     protected XDMModel getModel() {
161         return model;
162     }
163     
164     private void setModel(XDMModel xdmModel) {
165         assert xdmModel != null;
166         model = xdmModel;
167     }
168     
169     /**
170      * @return true the passed node has same id and belongs to same model.
171      * @param node Node to compare
172      */

173     public boolean isEquivalentNode(Node node){
174         return (this==node) || getClass().isInstance(node) &&
175                 getModel()!=null && getModel()==((NodeImpl)node).getModel() &&
176                 getId() != -1 && getId()==node.getId();
177     }
178     
179     /**
180      * Validation whether a node is in a tree
181      * @throws IllegalStateException if a node has already been added to a tree.
182      */

183     final void checkNotInTree() {
184         if (isInTree()) {
185             throw new IllegalStateException JavaDoc("mutations cannot occur on nodes already added to a tree");
186         }
187     }
188
189     // DOM Node impl
190
public boolean isSupported(String JavaDoc feature, String JavaDoc version) {
191         return "1.0".equals(version);
192     }
193     
194     /**
195      * This api clones the node object and returns the clone. A node object has
196      * content, attributes and children. The api will allow or disallow
197      * modification of this underlying data based on the input.
198      * @param cloneContent If true the content of clone can be modified.
199      * @param cloneAttributes If true the attributes of the clone can be modified.
200      * @param cloneChildren If true the children of the clone can be modified.
201      * @return returns the clone of this node
202      */

203     public Node clone(boolean cloneContent, boolean cloneAttributes, boolean cloneChildren) {
204         try {
205             NodeImpl clone = (NodeImpl)super.clone();
206             clone.inTree = false;
207             if(cloneContent) {
208                 clone.setTokens(new ArrayList JavaDoc<Token>(getTokens()));
209             } else {
210                 clone.setTokens(getTokens());
211             }
212             if(cloneAttributes) {
213                 clone.setAttributes(new ArrayList JavaDoc<Attribute>(getAttributesForRead()));
214             } else {
215                 clone.setAttributes(getAttributesForRead());
216             }
217             if(cloneChildren) {
218                 clone.setChildren(new ArrayList JavaDoc<Node>(getChildren()));
219             } else {
220                 clone.setChildren(getChildren());
221             }
222             return clone;
223         } catch (CloneNotSupportedException JavaDoc cne) {
224             throw new RuntimeException JavaDoc(cne);
225         }
226     }
227     /**
228      * Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes.
229      * @param deep - If true, recursively clone the subtree under the specified node;
230      * if false, clone only the node itself
231      * @return the clone
232      */

233     public Node cloneNode(boolean deep) {
234         return cloneNode(deep, true);
235     }
236     
237     public Node cloneNode(boolean deep, boolean cloneNamespacePrefix) {
238         Document root = isInTree() ? (Document) getOwnerDocument() : null;
239         Map JavaDoc<Integer JavaDoc,String JavaDoc> allNamespaces = null;
240         if (cloneNamespacePrefix && root != null) {
241             allNamespaces = root.getNamespaceMap();
242         }
243         Map JavaDoc<String JavaDoc,String JavaDoc> clonePrefixes = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
244         return cloneNode(deep, allNamespaces, clonePrefixes);
245     }
246     
247     public Node cloneNode(boolean deep, Map JavaDoc<Integer JavaDoc,String JavaDoc> allNS, Map JavaDoc<String JavaDoc,String JavaDoc> clonePrefixes) {
248         try {
249             NodeImpl clone = (NodeImpl)super.clone();
250             clone.inTree = false;
251             clone.model = null;
252             clone.setTokens(new ArrayList JavaDoc<Token>(getTokens()));
253             if(deep) {
254                 List JavaDoc<Node> cloneChildren = new ArrayList JavaDoc<Node>(getChildren().size());
255                 for (Node c : getChildren()) {
256                     NodeImpl child = (NodeImpl) c;
257                     NodeImpl cloneChild = (NodeImpl)child.cloneNode(deep, allNS, clonePrefixes);
258                     cloneChildren.add(cloneChild);
259                 }
260                 clone.setChildren(cloneChildren);
261             }
262
263             //whether deep or not, attributes are always cloned
264
List JavaDoc<Attribute> cloneAttributes = new ArrayList JavaDoc<Attribute>(getAttributesForRead().size());
265             for (Attribute attribute:getAttributesForRead()) {
266                 cloneAttributes.add((Attribute)attribute.cloneNode(deep, allNS, clonePrefixes));
267             }
268             clone.setAttributes(cloneAttributes);
269             
270             cloneNamespacePrefixes(allNS, clonePrefixes);
271             return clone;
272         } catch (CloneNotSupportedException JavaDoc cne) {
273             throw new RuntimeException JavaDoc(cne);
274         }
275     }
276     
277     protected void cloneNamespacePrefixes(Map JavaDoc<Integer JavaDoc,String JavaDoc> allNS, Map JavaDoc<String JavaDoc,String JavaDoc> prefixes) {
278         if (allNS == null) return;
279         
280         String JavaDoc namespace = allNS.get(getId());
281         if (namespace != null) {
282             String JavaDoc prefix = getPrefix();
283             if (prefix != null) {
284                 prefixes.put(prefix, namespace);
285             } else {
286                 prefixes.put(XMLConstants.DEFAULT_NS_PREFIX, namespace);
287             }
288         }
289     }
290     
291     public Node cloneShallowWithModelContext() {
292         try {
293             NodeImpl clone = (NodeImpl)super.clone();
294             clone.inTree = false;
295             clone.setTokens(new ArrayList JavaDoc<Token>(getTokens()));
296             if(hasChildNodes()) clone.setChildren(new ArrayList JavaDoc<Node>(getChildren()));
297             if(hasAttributes()) clone.setAttributes(new ArrayList JavaDoc<Attribute>(getAttributesForRead()));
298             return clone;
299         } catch (CloneNotSupportedException JavaDoc cne) {
300             throw new RuntimeException JavaDoc(cne);
301         }
302     }
303     
304     /**
305      * Returns whether this node has any children.
306      * @return Returns true if this node has any children, false otherwise.
307      */

308     public boolean hasChildNodes() {
309         return !getChildren().isEmpty();
310     }
311     
312     /**
313      * A NodeList that contains all children of this node.
314      * @return Returns nodelist containing children
315      */

316     public NodeList getChildNodes() {
317         if (!hasChildNodes()) return NodeListImpl.EMPTY;
318         return new NodeListImpl(getChildren());
319     }
320     
321     /**
322      * The first child of this node. If there is no such node, this returns null.
323      * @return first child
324      */

325     public Node getFirstChild() {
326         if (!hasChildNodes()) return null;
327         return getChildren().get(0);
328     }
329     
330     /**
331      * The last child of this node. If there is no such node, this returns null.
332      * @return last child
333      */

334     public Node getLastChild() {
335         if (!hasChildNodes()) return null;
336         return getChildren().get(getChildren().size()-1);
337     }
338     
339     public int getIndexOfChild(Node n) {
340         if (n == null) return -1;
341         List JavaDoc<Node> childs = getChildren();
342         for (int i = 0; i < childs.size(); i++) {
343             if (childs.get(i) == n ||
344                     (childs.get(i).getId() == n.getId() &&
345                         n.getId() != -1)) {
346                 return i;
347             }
348         }
349         return -1;
350     }
351     
352     /**
353      * Adds the node newChild to the end of the list of children of this node.
354      * Since the model is immutable checks if current node and node being added
355      * are not already in tree.
356      * @param newChild - The node to add.
357      * @return The node added.
358      */

359     public Node appendChild(org.w3c.dom.Node JavaDoc node) {
360         checkNotInTree();
361         if(node instanceof Node) {
362             NodeImpl nodeImpl = (NodeImpl) node;
363             nodeImpl.checkNotInTree();
364             getChildrenForWrite().add(nodeImpl);
365             return nodeImpl;
366         } else {
367             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,node.getClass().getName());
368         }
369     }
370     
371     /**
372      * Repalces the node oldNode with newNode.
373      * Since the model is immutable checks if current node
374      * and the node being put, are not already in tree.
375      * @param newChild - The new node to put in the child list.
376      * @param oldChild - The node being replaced in the list.
377      * @return The node replaced.
378      */

379     public Node replaceChild(org.w3c.dom.Node JavaDoc newNode, org.w3c.dom.Node JavaDoc oldNode) {
380         checkNotInTree();
381         if(newNode instanceof Node && oldNode instanceof Node) {
382             NodeImpl newNodeImpl = (NodeImpl) newNode;
383             NodeImpl oldNodeImpl = (NodeImpl) oldNode;
384             newNodeImpl.checkNotInTree();
385             int oldIndex = getIndexOfChild(oldNodeImpl);
386             if(oldIndex!=-1) {
387                 return getChildrenForWrite().set(oldIndex, newNodeImpl);
388             } else {
389                 throw new DOMException(DOMException.NOT_FOUND_ERR,null);
390             }
391         } else {
392             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,null);
393         }
394     }
395     
396     /**
397      * Moves child node to new position.
398      * @param child - The node being reordered in the list.
399      * @return The node moved.
400      */

401     public Node reorderChild(org.w3c.dom.Node JavaDoc child, int index) {
402         checkNotInTree();
403         if (child instanceof Node) {
404             NodeImpl n = (NodeImpl) child;
405             if (! n.isInTree()) {
406                 throw new IllegalArgumentException JavaDoc("Node is not in tree");
407             }
408             int currentIndex = getIndexOfChild(n);
409             if (index == currentIndex) {
410                 return n;
411             }
412             if (! getChildrenForWrite().remove(n)) {
413                 throw new IllegalArgumentException JavaDoc("Node is not in children");
414             }
415             index = index > currentIndex ? index-1 : index;
416             getChildrenForWrite().add(index, n);
417             return n;
418         } else {
419             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,null);
420         }
421     }
422
423     /**
424      * Rearranges children list to the given permutaion.
425      * @param permutation integer array with index represents current index and
426      * value is final index after reordered.
427      */

428     public void reorderChildren(int[] permutation) {
429         checkNotInTree();
430
431         List JavaDoc<Node> copy = new ArrayList JavaDoc<Node>(getChildren());
432         if (permutation.length != copy.size()) {
433             throw new IllegalArgumentException JavaDoc(
434                 "Permutation length: "+permutation.length+" " +
435                 "is different than children size: "+copy.size());
436         }
437         List JavaDoc writableChildren = getChildrenForWrite();
438         for (int i = 0; i < copy.size(); i++ ) {
439             Node child = copy.get(i);
440             writableChildren.set(permutation[i], child);
441         }
442     }
443
444     /**
445      * Removes the node from children list.
446      * Since the model is immutable checks if current node is not already in tree.
447      * @param node - The node being removed from the list.
448      * @return The node removed.
449      */

450     public Node removeChild(org.w3c.dom.Node JavaDoc node) {
451         checkNotInTree();
452         if(node instanceof Attribute) {
453             if(getAttributesForWrite().remove(node)) {
454                 return (Node) node;
455             }
456         } else if(node instanceof Node) {
457             if(getChildrenForWrite().remove(node)) {
458                 return (Node)node;
459             }
460         }
461         throw new DOMException(DOMException.TYPE_MISMATCH_ERR,null);
462     }
463     
464     /**
465      * Inserts the node newChild before the existing child node refChild.
466      * If refChild is null, insert newChild at the end of the list of children.
467      * Since the model is immutable checks if current node
468      * and node being inserted are not already in tree.
469      * @param newChild - The node to insert.
470      * @param refChild - The reference node, i.e., the node before which the new node must be inserted.
471      * @return The node being inserted.
472      */

473     public Node insertBefore(org.w3c.dom.Node JavaDoc newChild, org.w3c.dom.Node JavaDoc refChild) throws DOMException {
474         if(refChild == null)
475             return appendChild(newChild);
476         checkNotInTree();
477         if(newChild instanceof Node && refChild instanceof Node) {
478             NodeImpl newChildImpl = (NodeImpl) newChild;
479             newChildImpl.checkNotInTree();
480             int index = getIndexOfChild((NodeImpl)refChild);
481             if(index <0)
482                 throw new DOMException(DOMException.NOT_FOUND_ERR, null);
483             getChildrenForWrite().add(index,newChildImpl);
484             return newChildImpl;
485         } else {
486             throw new DOMException(DOMException.TYPE_MISMATCH_ERR,null);
487         }
488     }
489     
490     /**
491      * Returns whether this node has any attributes.
492      * @return Returns true if this node has any attributes, false otherwise.
493      */

494     public boolean hasAttributes() {
495         return !getAttributesForRead().isEmpty();
496     }
497     
498     /**
499      * A NamedNodeMap that contains all attributes of this node.
500      * @return Returns NamedNodeMap containing attributes
501      */

502     public NamedNodeMap getAttributes() {
503         if(attributes == null || attributes.isEmpty()) return NamedNodeMapImpl.EMPTY;
504         return new NamedNodeMapImpl(attributes);
505     }
506     
507     /**
508      * The Document object associated with this node.
509      * @return the document object
510      */

511     public org.w3c.dom.Document JavaDoc getOwnerDocument() {
512         return getModel().getDocument();
513     }
514     
515     public Node getParentNode() {
516         if (!isInTree()) return null;
517         PathFromRootVisitor pfrv = new PathFromRootVisitor();
518         List JavaDoc<Node> path = pfrv.findPath(getModel().getDocument(),this);
519         if(path == null || path.size()<2) return null;
520         return path.get(1);
521     }
522     
523     public Node getNextSibling() {
524         if (!isInTree()) return null;
525         PathFromRootVisitor pfrv = new PathFromRootVisitor();
526         List JavaDoc<Node> path = pfrv.findPath(getModel().getDocument(),this);
527         if(path == null || path.size()<2) return null;
528         NodeImpl parent = (NodeImpl)path.get(1);
529         NodeImpl node = (NodeImpl)path.get(0);
530         int nextIndex = parent.getIndexOfChild(node)+1;
531         if(nextIndex>=parent.getChildren().size()) return null;
532         return parent.getChildren().get(nextIndex);
533     }
534     
535     public Node getPreviousSibling() {
536         if (!isInTree()) return null;
537         PathFromRootVisitor pfrv = new PathFromRootVisitor();
538         List JavaDoc<Node> path = pfrv.findPath(getModel().getDocument(),this);
539         if(path == null || path.size()<2) return null;
540         NodeImpl parent = (NodeImpl)path.get(1);
541         NodeImpl node = (NodeImpl)path.get(0);
542         int prevIndex = parent.getIndexOfChild(node)-1;
543         if(prevIndex<0) return null;
544         return parent.getChildren().get(prevIndex);
545     }
546     
547     /*
548      * A code representing the type of the underlying object
549      * abstract and to be implemented in subclasses
550      */

551     public abstract short getNodeType();
552     
553     /*
554      * The name of this node, depending on its type
555      * abstract and to be implemented in subclasses
556      */

557     public abstract String JavaDoc getNodeName();
558     
559     public String JavaDoc getNodeValue() throws DOMException {
560         return null;
561     }
562     
563     public void setNodeValue(String JavaDoc str) throws DOMException {
564     }
565     
566     public String JavaDoc getLocalName() {
567         return null;
568     }
569     
570     public String JavaDoc getNamespaceURI(Document document) {
571         assert document != null;
572         return document.getNamespaceURI(this);
573     }
574     
575     public String JavaDoc getNamespaceURI() {
576         String JavaDoc namespace = lookupNamespaceLocally(getPrefix());
577         if (namespace != null) return namespace;
578         if (isInTree()) {
579             return getModel().getDocument().getNamespaceURI(this);
580         } else {
581             return lookupNamespaceURI(getPrefix());
582         }
583     }
584     
585     public String JavaDoc lookupNamespaceURI(String JavaDoc prefix) {
586         if(prefix == null) prefix = "";
587         String JavaDoc namespace = lookupNamespaceLocally(prefix);
588         if (namespace == null && isInTree()) {
589             List JavaDoc<Node> pathToRoot = new PathFromRootVisitor().findPath(getModel(). getDocument(), this);
590             namespace = lookupNamespace(prefix, pathToRoot);
591         }
592         return namespace;
593     }
594
595     public static String JavaDoc lookupNamespace(String JavaDoc prefix, List JavaDoc<Node> path) {
596         if (path == null) return null;
597         if(prefix == null) prefix = "";
598         for (Node node : path) {
599             String JavaDoc namespace = ((NodeImpl)node).lookupNamespaceLocally(prefix);
600             if (namespace != null) {
601                 return namespace;
602             }
603         }
604         return null;
605     }
606     
607     String JavaDoc lookupNamespaceLocally(String JavaDoc prefix) {
608         if(prefix == null) prefix = "";
609         if(hasAttributes()) {
610             for (Attribute attribute:getAttributesForRead()) {
611                 if(attribute.isXmlnsAttribute()) {
612                     String JavaDoc key = attribute.getPrefix() == null ? "" : attribute.getLocalName();
613                     if(key.equals(prefix)) {
614                         return attribute.getValue();
615                     }
616                 }
617             }
618         }
619         return null;
620     }
621     
622     String JavaDoc lookupPrefixLocally(String JavaDoc uri) {
623         if(hasAttributes()) {
624             String JavaDoc defaultNamespace = null;
625             for (Attribute attribute:getAttributesForRead()) {
626                 String JavaDoc attrName = attribute.getName();
627                 if (attrName.startsWith(XMLNS)) {
628                     if (attrName.length() == 5) {
629                         defaultNamespace = attribute.getValue();
630                     } else if (attrName.charAt(5) == ':' && uri.equals(attribute.getValue())) {
631                         return attrName.substring(6);
632                     }
633                 }
634             }
635             if (uri.equals(defaultNamespace)) {
636                 return "";
637             }
638         }
639         return null;
640     }
641     
642     public String JavaDoc lookupPrefix(String JavaDoc uri) {
643         if(uri == null) return null;
644         if(isInTree()) {
645             PathFromRootVisitor pfrv = new PathFromRootVisitor();
646             List JavaDoc<Node> path = pfrv.findPath(getModel().getDocument(),this);
647             if (path != null && ! path.isEmpty()) {
648                 return lookupPrefix(uri, path);
649             }
650         }
651         return lookupPrefixLocally(uri);
652     }
653
654     public static String JavaDoc lookupPrefix(String JavaDoc uri, List JavaDoc<Node> path) {
655         if (path == null) return null;
656         for(Node node : path) {
657             NodeImpl n = (NodeImpl) node;
658             String JavaDoc prefix = n.lookupPrefixLocally(uri);
659             if (prefix != null) {
660                 return prefix;
661             }
662         }
663         return null;
664     }
665     
666     public String JavaDoc getPrefix() {
667         return null; // some client determines DOM1 by NoSuchMethodError
668
}
669     
670     public void setPrefix(String JavaDoc str) throws DOMException {
671     }
672     
673     public void normalize() {
674     }
675     // DOM level 3
676
public short compareDocumentPosition(org.w3c.dom.Node JavaDoc a) {
677         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
678     }
679     
680     public String JavaDoc getBaseURI() {
681         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
682     }
683     public Object JavaDoc getFeature(String JavaDoc a, String JavaDoc b) {
684         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
685     }
686     public String JavaDoc getTextContent() {
687         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
688     }
689     public Object JavaDoc getUserData(String JavaDoc a) {
690         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
691     }
692     public boolean isDefaultNamespace(String JavaDoc a) {
693         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
694     }
695     public boolean isEqualNode(org.w3c.dom.Node JavaDoc a) {
696         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
697     }
698     public boolean isSameNode(org.w3c.dom.Node JavaDoc a) {
699         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
700     }
701     public void setTextContent(String JavaDoc a) {
702         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
703     }
704     public Object JavaDoc setUserData(String JavaDoc a, Object JavaDoc b, UserDataHandler c) {
705         throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "This read-only implementation supports DOM level 1 Core and XML module.");
706     }
707     
708     /*
709      * Used by DiffMerger to merge token changes
710      *
711      * @param newNode
712      */

713     public void copyTokens(Node newNode) {
714         checkNotInTree();
715         setTokens(((NodeImpl)newNode).getTokens());
716     }
717     
718     /**
719      * Returns a List of all children of this node.
720      * @return Returns a unmodifiable List of all children of this node.
721      */

722     private List JavaDoc<Node> getChildren() {
723         return createUnmodifiableListIfNeeded(children);
724     }
725     
726     /**
727      * Returns a List of all children of this node for updates.
728      * @return Returns a modifiable List of all children of this node.
729      */

730     private List JavaDoc<Node> getChildrenForWrite() {
731         checkNotInTree();
732         if (children == null) {
733             children = new ArrayList JavaDoc<Node>(0);
734         }
735         return children;
736     }
737     
738     /**
739      * Sets the children of this node
740      * @param newChildren - The list of children.
741      */

742     private void setChildren(List JavaDoc<Node> newChildren) {
743         checkNotInTree();
744         children = newChildren;
745     }
746
747     /**
748      * Returns a readonly List of all attributes of this node.
749      * @return Returns a unmodifiable List of all attributes of this node.
750      */

751     protected List JavaDoc<Attribute> getAttributesForRead() {
752         return createUnmodifiableListIfNeeded(attributes);
753     }
754     
755     /**
756      * Returns a modifiable List of all attributes of this node for updates.
757      * @return Returns a modifiable List of all attributes of this node.
758      */

759     protected List JavaDoc<Attribute> getAttributesForWrite() {
760         checkNotInTree();
761         if (attributes == null) {
762             attributes = new ArrayList JavaDoc<Attribute>(0);
763         }
764         return attributes;
765     }
766     
767     /**
768      * Sets the attributes of this node
769      * @param newAttributes - The list of attributes.
770      */

771     private void setAttributes(List JavaDoc<Attribute> newAttributes) {
772         checkNotInTree();
773         attributes = newAttributes;
774     }
775
776     /**
777      * Returns the readonly lexical tokens associated with this node.
778      * @return The unmodifiable list of lexical tokens.
779      */

780     public List JavaDoc<Token> getTokens() {
781         return createUnmodifiableListIfNeeded(tokens);
782     }
783
784     /**
785      * Returns the lexical tokens associated with this node for updates.
786      * @return The modifiable list of lexical tokens.
787      */

788     List JavaDoc<Token> getTokensForWrite() {
789         checkNotInTree();
790         if (tokens == null) {
791             tokens = new ArrayList JavaDoc<Token>(0);
792         }
793         return tokens;
794     }
795     
796     /**
797      * Sets the lexical tokens associated with this node
798      * @param newTokens - The list of lexical tokens.
799      */

800     void setTokens(List JavaDoc<Token> newTokens) {
801         tokens = newTokens;
802     }
803     
804     /**
805      * Returns a duplicate of this node, i.e., serves as a generic copy constructor for nodes.
806      * Used during Copy/Paste, Cut/Paste operation
807      * @return the clone
808      */

809     public Node copy() {
810         NodeImpl clone = (NodeImpl) cloneNode(true);
811         clone.assignNodeId(-1);
812         return clone;
813     }
814     
815     /**
816      * Wraps given list in unmodifiable list if needed.
817      * This will be called by getters in read mode, and is intended to be called
818      * from, r/o getters for internal data stuctures like children, attributes,
819      * and tokens.
820      * This api does not wrap list which is already wrapped, to avoid recursive
821      * wrapping, when nodes are cloned several times.
822      * Since there is no easy api to check for unmodifiable list in Collections
823      * framework, we rely on instanceof ArrayList as potential candidate for
824      * wrapping.
825      */

826     private <E extends Object JavaDoc> List JavaDoc<E> createUnmodifiableListIfNeeded(List JavaDoc<E> objects) {
827         // initialize unmodifiableObjects as objects as they may already be wrapped
828
List JavaDoc<E> unmodifiableObjects = objects;
829         if(objects == null) {
830             // if null, return empty list
831
unmodifiableObjects = Collections.emptyList();
832         } else if (objects instanceof ArrayList JavaDoc) {
833             // objects seem to be modifiable, so wrap it
834
unmodifiableObjects = Collections.unmodifiableList(objects);
835         }
836         return unmodifiableObjects;
837     }
838 }
839
Popular Tags