KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > tree > ParentNodeImpl


1 package com.icl.saxon.tree;
2 import com.icl.saxon.om.NodeInfo;
3 import com.icl.saxon.om.AxisEnumeration;
4 import com.icl.saxon.om.EmptyEnumeration;
5 import com.icl.saxon.om.SingletonEnumeration;
6 import com.icl.saxon.expr.NodeSetExtent;
7 import com.icl.saxon.expr.XPathException;
8 import com.icl.saxon.output.Outputter;
9 import com.icl.saxon.pattern.NodeTest;
10 import com.icl.saxon.pattern.AnyNodeTest;
11 import com.icl.saxon.sort.LocalOrderComparer;
12
13 import javax.xml.transform.TransformerException JavaDoc;
14
15 import org.w3c.dom.Node JavaDoc;
16 import org.w3c.dom.NodeList JavaDoc;
17
18 /**
19   * ParentNodeImpl is an implementation of a non-leaf node (specifically, an Element node
20   * or a Document node)
21   * @author Michael H. Kay (mhkay@iclway.co.uk)
22   */

23   
24
25 abstract class ParentNodeImpl extends NodeImpl {
26
27     private Object JavaDoc children = null; // null for no children
28
// a NodeInfo for a single child
29
// a NodeInfo[] for >1 child
30

31     protected int sequence;
32
33     /**
34     * Get the node sequence number (in document order). Sequence numbers are monotonic but not
35     * consecutive. In the current implementation, parent nodes (elements and roots) have a zero
36     * least-significant word, while namespaces, attributes, text nodes, comments, and PIs have
37     * the top word the same as their owner and the bottom half reflecting their relative position.
38     */

39
40     protected final long getSequenceNumber() {
41         return ((long)sequence)<<32;
42     }
43
44     /**
45     * Determine if the node has any children.
46     */

47
48     public final boolean hasChildNodes() {
49         return (children!=null);
50     }
51
52     /**
53     * Get an enumeration of the children of this node
54     */

55
56     public final AxisEnumeration enumerateChildren(NodeTest test) {
57         if (children==null) {
58             return EmptyEnumeration.getInstance();
59         } else if (children instanceof NodeImpl) {
60             NodeImpl child = (NodeImpl)children;
61             if (test.matches(child)) {
62                 return new SingletonEnumeration(child);
63             } else {
64                 return EmptyEnumeration.getInstance();
65             }
66         } else {
67             if (test instanceof AnyNodeTest) {
68                 return new ArrayEnumeration((NodeImpl[])children);
69             } else {
70                 return new ChildEnumeration(this, test);
71             }
72         }
73     }
74
75
76     /**
77     * Get the first child node of the element
78     * @return the first child node of the required type, or null if there are no children
79     */

80
81     public final Node JavaDoc getFirstChild() {
82         if (children==null) return null;
83         if (children instanceof NodeImpl) return (NodeImpl)children;
84         return ((NodeImpl[])children)[0];
85     }
86
87     /**
88     * Get the last child node of the element
89     * @return the last child of the element, or null if there are no children
90     */

91
92     public final Node JavaDoc getLastChild() {
93         if (children==null) return null;
94         if (children instanceof NodeImpl) return (NodeImpl)children;
95         NodeImpl[] n = (NodeImpl[])children;
96         return n[n.length-1];
97     }
98
99     /**
100      * Return a <code>NodeList</code> that contains all children of this node. If
101      * there are no children, this is a <code>NodeList</code> containing no
102      * nodes.
103      */

104      
105     public final NodeList JavaDoc getChildNodes() {
106         if (hasChildNodes()) {
107             try {
108                 return new NodeSetExtent(
109                                 enumerateChildren(AnyNodeTest.getInstance()),
110                                 LocalOrderComparer.getInstance());
111             } catch (XPathException err) {
112                 return super.getChildNodes();
113             }
114         } else {
115             return super.getChildNodes();
116         }
117     }
118
119     /**
120     * Get the nth child node of the element (numbering from 0)
121     * @return the last child of the element, or null if there is no n'th child
122     */

123
124     protected final NodeImpl getNthChild(int n) {
125         if (children==null) return null;
126         if (children instanceof NodeImpl) {
127             return (n==0 ? (NodeImpl)children : null);
128         }
129         NodeImpl[] nodes = (NodeImpl[])children;
130         if (n<0 || n>=nodes.length) return null;
131         return nodes[n];
132     }
133
134
135     /**
136     * Return the string-value of the node, that is, the concatenation
137     * of the character content of all descendent elements and text nodes.
138     * @return the accumulated character content of the element, including descendant elements.
139     */

140
141     public String JavaDoc getStringValue() {
142         StringBuffer JavaDoc sb = null;
143
144         NodeImpl next = (NodeImpl)getFirstChild();
145         while (next!=null) {
146             if (next instanceof TextImpl) {
147                 if (sb==null) {
148                     sb = new StringBuffer JavaDoc();
149                 }
150                 sb.append(next.getStringValue());
151             }
152             next = next.getNextInDocument(this);
153         }
154         if (sb==null) return "";
155         return sb.toString();
156     }
157
158     /**
159     * Copy the string-value of this node to a given outputter
160     */

161
162     public void copyStringValue(Outputter out) throws TransformerException JavaDoc {
163         NodeImpl next = (NodeImpl)getFirstChild();
164         while (next!=null) {
165             if (next.getNodeType()==NodeInfo.TEXT) {
166                 next.copyStringValue(out);
167             }
168             next = next.getNextInDocument(this);
169         }
170     }
171
172     /**
173     * Supply an array to be used for the array of children. For system use only.
174     */

175
176     public void useChildrenArray(NodeImpl[] array) {
177         children = array;
178     }
179
180     /**
181     * Add a child node to this node. For system use only. Note: normalizing adjacent text nodes
182     * is the responsibility of the caller.
183     */

184
185     public void addChild(NodeImpl node, int index) {
186         NodeImpl[] c;
187         if (children == null) {
188             c = new NodeImpl[10];
189         } else if (children instanceof NodeImpl) {
190             c = new NodeImpl[10];
191             c[0] = (NodeImpl)children;
192         } else {
193             c = (NodeImpl[])children;
194         }
195         if (index >= c.length) {
196             NodeImpl[] kids = new NodeImpl[c.length * 2];
197             System.arraycopy(c, 0, kids, 0, c.length);
198             c = kids;
199         }
200         c[index] = node;
201         node.parent = this;
202         node.index = index;
203         children = c;
204     }
205
206     /**
207     * Remove node at given index. Will always be followed by a renumberChildren().
208     */

209
210     public void removeChild(int index) {
211         if (children instanceof NodeImpl) {
212             children = null;
213         } else {
214             ((NodeImpl[])children)[index] = null;
215         }
216     }
217
218     /**
219     * Renumber the children of a given parent node. For system use only
220     */

221
222     public void renumberChildren() {
223         int j = 0;
224         if (children==null) {
225             return;
226         } else if (children instanceof NodeImpl) {
227             ((NodeImpl)children).parent = this;
228             ((NodeImpl)children).index = 0;
229         } else {
230             NodeImpl[] c = (NodeImpl[])children;
231             for (int i=0; i<c.length; i++) {
232                 if (c[i]!=null) {
233                     c[i].parent = this;
234                     c[i].index = j;
235                     c[j] = c[i];
236                     j++;
237                 }
238             }
239             compact(j);
240         }
241     }
242
243     /**
244     * Drop a branch of the tree. The target element remains in the tree, but its children are
245     * disconnected from the parent. Unless there are other references to the children (e.g. in
246     * a variable) they will be deleted from memory next time the garbage collector comes round.
247     */

248
249     public void dropChildren() {
250         // truncate the string buffer to remove any string content
251
NodeImpl n = getNextInDocument(this);
252         while (n!=null) {
253             if (n instanceof TextImpl) {
254                 ((TextImpl)n).truncateToStart();
255                 break;
256             }
257             n = n.getNextInDocument(this);
258         }
259         // now remove all the child nodes
260
children = null;
261     }
262
263     /**
264     * Compact the space used by this node
265     */

266
267     public void compact(int size) {
268         if (size==0) {
269             children = null;
270         } else if (size==1) {
271             if (children instanceof NodeImpl[]) {
272                 children = ((NodeImpl[])children)[0];
273             }
274         } else {
275             NodeImpl[] kids = new NodeImpl[size];
276             System.arraycopy(children, 0, kids, 0, size);
277             children = kids;
278         }
279     }
280
281     /**
282     * Get the node value as defined in the DOM. This is not the same as the XPath string-value.
283     */

284
285     public String JavaDoc getNodeValue() {
286         return null;
287     }
288 }
289
290
291 //
292
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
293
// you may not use this file except in compliance with the License. You may obtain a copy of the
294
// License at http://www.mozilla.org/MPL/
295
//
296
// Software distributed under the License is distributed on an "AS IS" basis,
297
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
298
// See the License for the specific language governing rights and limitations under the License.
299
//
300
// The Original Code is: all this file.
301
//
302
// The Initial Developer of the Original Code is
303
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
304
//
305
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
306
//
307
// Contributor(s): none.
308
//
309
Popular Tags