001: package net.sf.saxon.tinytree;
002:
003: import net.sf.saxon.Configuration;
004: import net.sf.saxon.sort.IntHashMap;
005: import net.sf.saxon.event.Receiver;
006: import net.sf.saxon.om.*;
007: import net.sf.saxon.trans.XPathException;
008: import net.sf.saxon.type.Type;
009:
010: import java.util.ArrayList;
011: import java.util.HashMap;
012: import java.util.List;
013:
014: /**
015: * A node in the XML parse tree representing the Document itself (or equivalently, the root
016: * node of the Document).<P>
017: */
018:
019: public final class TinyDocumentImpl extends TinyParentNodeImpl
020: implements DocumentInfo {
021:
022: private HashMap idTable = null;
023: private IntHashMap elementList = null;
024: private HashMap entityTable = null;
025:
026: public TinyDocumentImpl(TinyTree tree) {
027: this .tree = tree;
028: }
029:
030: /**
031: * Get the tree containing this node
032: */
033:
034: public TinyTree getTree() {
035: return tree;
036: }
037:
038: /**
039: * Set the Configuration that contains this document
040: */
041:
042: public void setConfiguration(Configuration config) {
043: if (config != tree.getConfiguration()) {
044: throw new IllegalArgumentException(
045: "Configuration of document differs from that of the supporting TinyTree");
046: }
047: }
048:
049: /**
050: * Get the configuration previously set using setConfiguration
051: */
052:
053: public Configuration getConfiguration() {
054: return tree.getConfiguration();
055: }
056:
057: /**
058: * Set the system id of this node
059: */
060:
061: public void setSystemId(String uri) {
062: tree.setSystemId(nodeNr, uri);
063: }
064:
065: /**
066: * Get the system id of this root node
067: */
068:
069: public String getSystemId() {
070: return tree.getSystemId(nodeNr);
071: }
072:
073: /**
074: * Get the base URI of this root node. For a root node the base URI is the same as the
075: * System ID.
076: */
077:
078: public String getBaseURI() {
079: return getSystemId();
080: }
081:
082: /**
083: * Get the line number of this root node.
084: * @return 0 always
085: */
086:
087: public int getLineNumber() {
088: return 0;
089: }
090:
091: /**
092: * Return the type of node.
093: * @return Type.DOCUMENT (always)
094: */
095:
096: public final int getNodeKind() {
097: return Type.DOCUMENT;
098: }
099:
100: /**
101: * Find the parent node of this node.
102: * @return The Node object describing the containing element or root node.
103: */
104:
105: public NodeInfo getParent() {
106: return null;
107: }
108:
109: /**
110: * Get the root node
111: * @return the NodeInfo that is the root of the tree - not necessarily a document node
112: */
113:
114: public NodeInfo getRoot() {
115: return this ;
116: }
117:
118: /**
119: * Get the root (document) node
120: * @return the DocumentInfo representing the document node, or null if the
121: * root of the tree is not a document node
122: */
123:
124: public DocumentInfo getDocumentRoot() {
125: return this ;
126: }
127:
128: /**
129: * Get a character string that uniquely identifies this node
130: * @return an identifier based on the document number
131: */
132:
133: public String generateId() {
134: return "d" + getDocumentNumber();
135: }
136:
137: /**
138: * Get a list of all elements with a given name. This is implemented
139: * as a memo function: the first time it is called for a particular
140: * element type, it remembers the result for next time.
141: */
142:
143: AxisIterator getAllElements(int fingerprint) {
144: //Integer key = new Integer(fingerprint);
145: if (elementList == null) {
146: elementList = new IntHashMap(20);
147: }
148: List list = (List) elementList.get(fingerprint);
149: if (list == null) {
150: list = getElementList(fingerprint);
151: elementList.put(fingerprint, list);
152: }
153: return new ListIterator(list);
154: }
155:
156: /**
157: * Get a list containing all the elements with a given element name
158: * @param fingerprint the fingerprint of the element name
159: * @return list a List containing the TinyElementImpl objects
160: */
161:
162: List getElementList(int fingerprint) {
163: List list = new ArrayList(tree.getNumberOfNodes() / 20);
164: int i = nodeNr + 1;
165: while (tree.depth[i] != 0) {
166: if (tree.nodeKind[i] == Type.ELEMENT
167: && (tree.nameCode[i] & 0xfffff) == fingerprint) {
168: list.add(tree.getNode(i));
169: }
170: i++;
171: }
172: return list;
173: }
174:
175: /**
176: * Register a unique element ID. Fails if there is already an element with that ID.
177: * @param e The NodeInfo (always an element) having a particular unique ID value
178: * @param id The unique ID value. The caller is responsible for checking that this
179: * is a valid NCName.
180: */
181:
182: void registerID(NodeInfo e, String id) {
183: if (idTable == null) {
184: idTable = new HashMap(256);
185: }
186:
187: // the XPath spec (5.2.1) says ignore the second ID if it's not unique
188: NodeInfo old = (NodeInfo) idTable.get(id);
189: if (old == null) {
190: idTable.put(id, e);
191: }
192:
193: }
194:
195: /**
196: * Get the element with a given ID.
197: * @param id The unique ID of the required element, previously registered using registerID()
198: * @return The NodeInfo (always an Element) for the given ID if one has been registered,
199: * otherwise null.
200: */
201:
202: public NodeInfo selectID(String id) {
203: if (idTable == null)
204: return null; // no ID values found
205: return (NodeInfo) idTable.get(id);
206: }
207:
208: /**
209: * Set an unparsed entity URI associated with this document. For system use only, while
210: * building the document.
211: */
212:
213: void setUnparsedEntity(String name, String uri, String publicId) {
214: if (entityTable == null) {
215: entityTable = new HashMap(20);
216: }
217: String[] ids = new String[2];
218: ids[0] = uri;
219: ids[1] = publicId;
220: entityTable.put(name, ids);
221: }
222:
223: /**
224: * Get the unparsed entity with a given nameID if there is one, or null if not. If the entity
225: * does not exist, return null.
226: * @param name the name of the entity
227: * @return if the entity exists, return an array of two Strings, the first holding the system ID
228: * of the entity, the second holding the public
229: */
230:
231: public String[] getUnparsedEntity(String name) {
232: if (entityTable == null) {
233: return null;
234: }
235: return (String[]) entityTable.get(name);
236: }
237:
238: /**
239: * Copy this node to a given outputter
240: */
241:
242: public void copy(Receiver out, int whichNamespaces,
243: boolean copyAnnotations, int locationId)
244: throws XPathException {
245:
246: out.startDocument(0);
247:
248: // output the children
249:
250: AxisIterator children = iterateAxis(Axis.CHILD);
251: while (true) {
252: NodeInfo n = (NodeInfo) children.next();
253: if (n == null) {
254: break;
255: }
256: n.copy(out, whichNamespaces, copyAnnotations, locationId);
257: }
258:
259: out.endDocument();
260: }
261:
262: public void showSize() {
263: tree.showSize();
264: }
265:
266: }
267:
268: //
269: // The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
270: // you may not use this file except in compliance with the License. You may obtain a copy of the
271: // License at http://www.mozilla.org/MPL/
272: //
273: // Software distributed under the License is distributed on an "AS IS" basis,
274: // WITHOUT WARRANTY OF ANY KIND, either express or implied.
275: // See the License for the specific language governing rights and limitations under the License.
276: //
277: // The Original Code is: all this file
278: //
279: // The Initial Developer of the Original Code is Michael H. Kay.
280: //
281: // Contributor(s):
282: //
|