KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > tree > DocumentImpl


1 package net.sf.saxon.tree;
2 import net.sf.saxon.Configuration;
3 import net.sf.saxon.event.Receiver;
4 import net.sf.saxon.om.*;
5 import net.sf.saxon.trans.XPathException;
6 import net.sf.saxon.type.Type;
7
8 import java.util.ArrayList JavaDoc;
9 import java.util.HashMap JavaDoc;
10
11 /**
12   * A node in the XML parse tree representing the Document itself (or equivalently, the root
13   * node of the Document).<P>
14   * @author Michael H. Kay
15   */

16
17 public final class DocumentImpl extends ParentNodeImpl
18     implements DocumentInfo {
19
20     //private static int nextDocumentNumber = 0;
21

22     private ElementImpl documentElement;
23
24     private HashMap JavaDoc idTable = null;
25     private int documentNumber;
26     private HashMap JavaDoc entityTable = null;
27     private HashMap JavaDoc elementList = null;
28     //private StringBuffer characterBuffer;
29
private Configuration config;
30     private LineNumberMap lineNumberMap;
31     private SystemIdMap systemIdMap = new SystemIdMap();
32
33     public DocumentImpl() {
34         parent = null;
35     }
36
37     /**
38     * Set the Configuration that contains this document
39     */

40
41     public void setConfiguration(Configuration config) {
42         this.config = config;
43         documentNumber = config.getDocumentNumberAllocator().allocateDocumentNumber();
44     }
45
46     /**
47      * Get the configuration previously set using setConfiguration
48      */

49
50     public Configuration getConfiguration() {
51         return config;
52     }
53
54     /**
55     * Get the name pool used for the names in this document
56     */

57
58     public NamePool getNamePool() {
59         return config.getNamePool();
60     }
61
62     /**
63     * Get the unique document number
64     */

65
66     public int getDocumentNumber() {
67         return documentNumber;
68     }
69
70     /**
71     * Set the top-level element of the document (variously called the root element or the
72     * document element). Note that a DocumentImpl may represent the root of a result tree
73     * fragment, in which case there is no document element.
74     * @param e the top-level element
75     */

76
77     void setDocumentElement(ElementImpl e) {
78         documentElement = e;
79     }
80
81     /**
82     * Set the system id of this node
83     */

84
85     public void setSystemId(String JavaDoc uri) {
86         if (uri==null) {
87             uri = "";
88         }
89         systemIdMap.setSystemId(sequence, uri);
90     }
91
92     /**
93     * Get the system id of this root node
94     */

95
96     public String JavaDoc getSystemId() {
97         return systemIdMap.getSystemId(sequence);
98     }
99
100     /**
101     * Get the base URI of this root node. For a root node the base URI is the same as the
102     * System ID.
103     */

104
105     public String JavaDoc getBaseURI() {
106         return getSystemId();
107     }
108
109     /**
110     * Set the system id of an element in the document
111     */

112
113     void setSystemId(int seq, String JavaDoc uri) {
114         if (uri==null) {
115             uri = "";
116         }
117         systemIdMap.setSystemId(seq, uri);
118     }
119
120
121     /**
122     * Get the system id of an element in the document
123     */

124
125     String JavaDoc getSystemId(int seq) {
126         return systemIdMap.getSystemId(seq);
127     }
128
129
130     /**
131     * Set line numbering on
132     */

133
134     public void setLineNumbering() {
135         lineNumberMap = new LineNumberMap();
136         lineNumberMap.setLineNumber(sequence, 0);
137     }
138
139     /**
140     * Set the line number for an element. Ignored if line numbering is off.
141     */

142
143     void setLineNumber(int sequence, int line) {
144         if (lineNumberMap != null) {
145             lineNumberMap.setLineNumber(sequence, line);
146         }
147     }
148
149     /**
150     * Get the line number for an element. Return -1 if line numbering is off.
151     */

152
153     int getLineNumber(int sequence) {
154         if (lineNumberMap != null) {
155             return lineNumberMap.getLineNumber(sequence);
156         }
157         return -1;
158     }
159
160     /**
161     * Get the line number of this root node.
162     * @return 0 always
163     */

164
165     public int getLineNumber() {
166         return 0;
167     }
168
169     /**
170     * Return the type of node.
171     * @return Type.DOCUMENT (always)
172     */

173
174     public final int getNodeKind() {
175         return Type.DOCUMENT;
176     }
177
178     /**
179     * Get next sibling - always null
180     * @return null
181     */

182
183     public final NodeInfo getNextSibling() {
184         return null;
185     }
186
187     /**
188     * Get previous sibling - always null
189     * @return null
190     */

191
192     public final NodeInfo getPreviousSibling() {
193         return null;
194     }
195
196     /**
197      * Get the root (outermost) element.
198      * @return the Element node for the outermost element of the document.
199      */

200
201     public ElementImpl getDocumentElement() {
202         return documentElement;
203     }
204
205     /**
206     * Get the root node
207     * @return the NodeInfo representing the root of this tree
208     */

209
210     public NodeInfo getRoot() {
211         return this;
212     }
213
214     /**
215     * Get the root (document) node
216     * @return the DocumentInfo representing this document
217     */

218
219     public DocumentInfo getDocumentRoot() {
220         return this;
221     }
222
223     /**
224     * Get a character string that uniquely identifies this node
225     * @return a string based on the document number
226     */

227
228     public String JavaDoc generateId() {
229         return "d"+documentNumber;
230     }
231
232     /**
233     * Get a list of all elements with a given name fingerprint
234     */

235
236     AxisIterator getAllElements(int fingerprint) {
237         Integer JavaDoc elkey = new Integer JavaDoc(fingerprint);
238         if (elementList==null) {
239             elementList = new HashMap JavaDoc(500);
240         }
241         ArrayList JavaDoc list = (ArrayList JavaDoc)elementList.get(elkey);
242         if (list==null) {
243             list = new ArrayList JavaDoc(500);
244             NodeImpl next = getNextInDocument(this);
245             while (next!=null) {
246                 if (next.getNodeKind()==Type.ELEMENT &&
247                         next.getFingerprint() == fingerprint) {
248                     list.add(next);
249                 }
250                 next = next.getNextInDocument(this);
251             }
252             elementList.put(elkey, list);
253         }
254         return new ListIterator(list);
255     }
256
257     /**
258     * Index all the ID attributes. This is done the first time the id() function
259     * is used on this document
260     */

261
262     private void indexIDs() {
263         if (idTable!=null) return; // ID's are already indexed
264
idTable = new HashMap JavaDoc(256);
265
266         NodeImpl curr = this;
267         NodeImpl root = curr;
268         while(curr!=null) {
269             if (curr.getNodeKind()==Type.ELEMENT) {
270                 ElementImpl e = (ElementImpl)curr;
271                 AttributeCollection atts = e.getAttributeList();
272                 for (int i=0; i<atts.getLength(); i++) {
273                     if (atts.isId(i) && XMLChar.isValidNCName(atts.getValue(i).trim())) {
274                         // don't index any invalid IDs - these can arise when using a non-validating parser
275
registerID(e, atts.getValue(i).trim());
276                     }
277                 }
278             }
279             curr = curr.getNextInDocument(root);
280         }
281     }
282
283     /**
284     * Register a unique element ID. Fails if there is already an element with that ID.
285     * @param e The Element having a particular unique ID value
286     * @param id The unique ID value
287     */

288
289     private void registerID(NodeInfo e, String JavaDoc id) {
290         // the XPath spec (5.2.1) says ignore the second ID if it's not unique
291
Object JavaDoc old = idTable.get(id);
292         if (old==null) {
293             idTable.put(id, e);
294         }
295
296     }
297
298     /**
299     * Get the element with a given ID.
300     * @param id The unique ID of the required element, previously registered using registerID()
301     * @return The NodeInfo for the given ID if one has been registered, otherwise null.
302     */

303
304     public NodeInfo selectID(String JavaDoc id) {
305         if (idTable==null) indexIDs();
306         return (NodeInfo)idTable.get(id);
307     }
308
309     /**
310     * Set an unparsed entity URI associated with this document. For system use only, while
311     * building the document.
312     */

313
314     void setUnparsedEntity(String JavaDoc name, String JavaDoc uri, String JavaDoc publicId) {
315         // System.err.println("setUnparsedEntity( " + name + "," + uri + ")");
316
if (entityTable==null) {
317             entityTable = new HashMap JavaDoc(10);
318         }
319         String JavaDoc[] ids = new String JavaDoc[2];
320         ids[0] = uri;
321         ids[1] = publicId;
322         entityTable.put(name, ids);
323     }
324
325     /**
326     * Get the unparsed entity with a given name
327     * @param name the name of the entity
328     * @return if the entity exists, return an array of two Strings, the first holding the system ID
329     * of the entity, the second holding the public ID if there is one, or null if not. If the entity
330     * does not exist, return null. * @return the URI of the entity if there is one, or empty string if not
331     */

332
333     public String JavaDoc[] getUnparsedEntity(String JavaDoc name) {
334         if (entityTable==null) {
335             return null;
336         }
337         return (String JavaDoc[])entityTable.get(name);
338     }
339
340     /**
341     * Copy this node to a given outputter
342     */

343
344     public void copy(Receiver out, int whichNamespaces, boolean copyAnnotations, int locationId) throws XPathException {
345         out.startDocument(0);
346         NodeImpl next = (NodeImpl)getFirstChild();
347         while (next!=null) {
348             next.copy(out, whichNamespaces, copyAnnotations, locationId);
349             next = (NodeImpl)next.getNextSibling();
350         }
351         out.endDocument();
352     }
353
354 }
355
356 //
357
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
358
// you may not use this file except in compliance with the License. You may obtain a copy of the
359
// License at http://www.mozilla.org/MPL/
360
//
361
// Software distributed under the License is distributed on an "AS IS" basis,
362
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
363
// See the License for the specific language governing rights and limitations under the License.
364
//
365
// The Original Code is: all this file
366
//
367
// The Initial Developer of the Original Code is Michael H. Kay.
368
//
369
// Contributor(s):
370
//
371
Popular Tags