1 /*
2 * Copyright (C) 2002 Carsten Krebs (Team-Konzept GmbH & Co.KG)
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 package com.teamkonzept.dom4jb.saxon;
19
20 import java.util.Hashtable;
21
22 import javax.xml.transform.TransformerException;
23
24
25 import com.icl.saxon.KeyManager;
26 import com.icl.saxon.om.Axis;
27 import com.icl.saxon.om.AxisEnumeration;
28 import com.icl.saxon.om.DocumentInfo;
29 import com.icl.saxon.om.EmptyEnumeration;
30 import com.icl.saxon.om.NamePool;
31 import com.icl.saxon.om.NodeInfo;
32 import com.icl.saxon.om.SingletonEnumeration;
33 import com.icl.saxon.output.Outputter;
34 import com.icl.saxon.pattern.AnyNodeTest;
35 import com.icl.saxon.pattern.NodeTest;
36 import com.teamkonzept.dom4jb.schema.AttributeDescriptor;
37 import com.teamkonzept.dom4jb.schema.ElementDescriptor;
38 import com.teamkonzept.dom4jb.schema.TextDescriptor;
39
40 public class Document
41 extends com.teamkonzept.dom4jb.dom.Document
42 implements DocumentInfo, AxisNode {
43
44 private DescendantAxis axis;
45 private int position;
46 private Namespace[] namespaces = new Namespace[0];
47
48 protected String baseURI;
49 protected NamePool namePool;
50 protected Hashtable keyTable = new Hashtable();
51
52 public Document(final String baseURI) {
53 this.baseURI = baseURI == null ? "" : baseURI;
54 }
55
56 public com.teamkonzept.dom4jb.dom.Element createElement(
57 final ElementDescriptor descriptor,
58 final Object bean) {
59
60 return new Element(this, descriptor, bean);
61 }
62
63 public com.teamkonzept.dom4jb.dom.Element createElement(
64 final String name,
65 final Object bean) {
66
67 return new Element(this, name, bean);
68 }
69
70 public com.teamkonzept.dom4jb.dom.Attribute createAttribute(
71 final AttributeDescriptor descriptor,
72 final Object bean) {
73
74 return new Attribute(this, descriptor, bean);
75 }
76
77 public com.teamkonzept.dom4jb.dom.Text createText(
78 final TextDescriptor descriptor,
79 final Object bean) {
80
81 return new Text(this, descriptor, bean);
82 }
83
84 public void attachAxis(final int position, final DescendantAxis axis) {
85 this.axis = axis;
86 this.position = position;
87 }
88
89 public DescendantAxis getAxis() {
90 return axis;
91 }
92
93 public int getPosition() {
94 return position;
95 }
96
97 /***
98 * Return the string value of the node. The interpretation of this depends
99 * on the type of node. For an element it is the accumulated character
100 * content of the element, including descendant elements.
101 * @return the string value of the node
102 */
103 public String getStringValue() {
104 final StringBuffer sb = new StringBuffer();
105 expandStringValue(getChildNodes(), sb);
106 return sb.toString();
107 }
108
109 private void expandStringValue(
110 final org.w3c.dom.NodeList list,
111 final StringBuffer sb) {
112 int i = 0;
113 for (org.w3c.dom.Node node = list.item(i);
114 node != null;
115 node = list.item(++i)) {
116 expandStringValue(node.getChildNodes(), sb);
117 }
118 }
119
120 /***
121 * Get the display name of this node. For elements and attributes
122 * this is [prefix:]localname. For unnamed nodes, it is an empty string.
123 * @return The display name of this node.
124 * For a node with no name, return an empty string.
125 */
126 public String getDisplayName() {
127 return "";
128 }
129
130 /***
131 * Find the value of a given attribute of this node. <BR>
132 * This method is defined on all nodes to meet XSL requirements,
133 * but for nodes other than elements it will always return null.
134 * @param uri the namespace uri of an attribute ("" if no namespace)
135 * @param localname the local name of the attribute
136 * @return the value of the attribute, if it exists, otherwise null
137 */
138
139 public String getAttributeValue(final String uri, final String localName) {
140 return "";
141 }
142
143 /***
144 * Get the value of a given attribute of this node
145 * @param fingerprint The fingerprint of the attribute name
146 * @return the attribute value if it exists or null if not
147 */
148 public String getAttributeValue(final int fingerprint) {
149 return null;
150 }
151
152 /***
153 * Get a character string that uniquely identifies this node.<br />
154 * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b)
155 * @return a string that uniquely identifies this node, within this
156 * document. The calling code prepends information to make the result
157 * unique across all documents.
158 */
159 public String generateId() {
160 final StringBuffer buf = new StringBuffer("j");
161 buf.append(hashCode());
162 return buf.toString();
163 }
164
165 /***
166 * Copy this node to a given outputter (deep copy)
167 */
168 public void copy(final Outputter out) throws TransformerException {
169 final AxisEnumeration children0 =
170 getEnumeration(Axis.CHILD, AnyNodeTest.getInstance());
171 while (children0.hasMoreElements()) {
172 children0.nextElement().copy(out);
173 }
174 return;
175 }
176
177 /***
178 * Output all namespace nodes associated with this element. Does nothing if
179 * the node is not an element.
180 * @param out The relevant outputter
181 * @param includeAncestors True if namespaces declared on ancestor
182 * elements must be output; false if it is known that these are already
183 * on the result tree
184 */
185 public void outputNamespaceNodes(
186 final Outputter out,
187 final boolean includeAncestors)
188 throws TransformerException {
189 }
190
191 public void expandStringValue(final StringBuffer sb) {
192 }
193
194 public Namespace[] getNamespaces() {
195 return namespaces;
196 }
197
198 /***
199 * Set the name pool used for all names in this document
200 */
201 public void setNamePool(final NamePool pool) {
202 namePool = pool;
203 }
204
205 /***
206 * Get the name pool used for the names in this document
207 */
208 public NamePool getNamePool() {
209 return namePool;
210 }
211
212 public String getSystemId() {
213 return this.baseURI;
214 }
215
216 /***
217 * Set the system identifier for this Source.
218 *
219 * <p>The system identifier is optional if the source does not
220 * get its data from a URL, but it may still be useful to provide one.
221 * The application can use a system identifier, for example, to resolve
222 * relative URIs and to include in error messages and warnings.</p>
223 *
224 * @param systemId The system identifier as a URL string.
225 */
226 public void setSystemId(final String systemId) {
227 this.baseURI = systemId;
228 }
229
230 /***
231 * Get the element with a given ID, if any
232 * @param id the required ID value
233 * @return null: not yet implemented
234 */
235
236 public NodeInfo selectID(final String id) {
237 return null;
238 }
239
240 /***
241 * Get the index for a given key
242 * @param keyManager The key manager managing this key
243 * @param fingerprint The fingerprint of the name of the key
244 * (unique with the key manager)
245 * @return The index, if one has been built, in the form of a
246 * Hashtable that maps the key value to a list of nodes having that key
247 * value. If no index
248 * has been built, returns null.
249 */
250 public Hashtable getKeyIndex(
251 final KeyManager keyManager,
252 final int fingerprint) {
253 return (Hashtable) keyTable.get(getKey(keyManager, fingerprint));
254 }
255
256 /***
257 * Set the index for a given key
258 * @param keyManager The key manager managing this key
259 * @param fingerprint The fingerprint of the name of the key
260 * (unique with the key manager)
261 * @param index the index, in the form of a Hashtable that
262 * maps the key value to a list of nodes having that key value
263 */
264 public void setKeyIndex(
265 final KeyManager keyManager,
266 final int fingerprint,
267 final Hashtable index) {
268 keyTable.put(getKey(keyManager, fingerprint), index);
269 }
270
271 /***
272 * Get the unparsed entity with a given name
273 * @param name the name of the entity
274 * @return null: not yet implemented
275 */
276 public String getUnparsedEntity(String name) {
277 return null;
278 }
279
280 private static String getKey(
281 final KeyManager keyManager,
282 final int fingerprint) {
283 final StringBuffer buf =
284 new StringBuffer(Integer.toString(keyManager.hashCode()));
285 buf.append('#');
286 buf.append(fingerprint);
287 return buf.toString();
288 }
289
290 // ------- GENERAL stuff -------
291
292 /***
293 * Get the Base URI for the node, that is, the URI used for resolving a
294 * relative URI contained in the node. This will be the same as the
295 * System ID unless xml:base has been used.
296 */
297 public String getBaseURI() {
298 return getSystemId();
299 }
300
301 /***
302 * Get line number
303 * @return the line number of the node in its original source document;
304 * or -1 if not available
305 */
306 public int getLineNumber() {
307 return -1;
308 }
309
310 /***
311 * Get name code. The name code is a coded form of the node name: two nodes
312 * with the same name code have the same namespace URI, the same local name,
313 * and the same prefix. By masking the name code with &0xfffff, you get a
314 * fingerprint: two nodes with the same fingerprint have the same local name
315 * and namespace URI.
316 * @see com.icl.saxon.om.NamePool#allocate allocate
317 */
318 public int getNameCode() {
319 return -1;
320 }
321
322 /***
323 * Get fingerprint. The fingerprint is a coded form of the expanded name
324 * of the node: two nodes
325 * with the same name code have the same namespace URI and the same
326 * local name. A fingerprint of -1 should be returned for a node with
327 * no name.
328 */
329 public int getFingerprint() {
330 return -1;
331 }
332
333 /***
334 * Get the URI part of the name of this node. This is the URI corresponding
335 * to the prefix, or the URI of the default namespace if appropriate.
336 * @return The URI of the namespace of this node. For an unnamed node,
337 * return null. For a node with an empty prefix, return an empty string.
338 */
339 public String getURI() {
340 return this.getNamespaceURI();
341 }
342
343 /***
344 * Get the NodeInfo object representing the parent of this node
345 */
346 public NodeInfo getParent() {
347 return null;
348 }
349
350 /***
351 * Get the root (document) node
352 * @return the DocumentInfo representing the containing document
353 */
354 public DocumentInfo getDocumentRoot() {
355 return this;
356 }
357
358 /***
359 * Copy the string-value of this node to a given outputter
360 */
361 public void copyStringValue(final Outputter out)
362 throws TransformerException {
363 out.writeContent(getStringValue());
364 }
365
366 /***
367 * Return an enumeration over the nodes reached by the given axis from
368 * this node The value NodeInfo.NODE means include any type of node.
369 * @param nodeTest A pattern to be matched by the returned nodes
370 * @return a NodeEnumeration that scans the nodes reached by the axis
371 * in turn.
372 */
373 public AxisEnumeration getEnumeration(
374 final byte axisNumber,
375 final NodeTest nodeTest) {
376 switch (axisNumber) {
377 case Axis.ANCESTOR :
378 case Axis.ANCESTOR_OR_SELF :
379 case Axis.ATTRIBUTE :
380 return EmptyEnumeration.getInstance();
381
382 case Axis.CHILD :
383 if (hasChildNodes()) {
384 return new FilterEnumeration(
385 new ChildEnumeration(this),
386 nodeTest);
387 } else {
388 return EmptyEnumeration.getInstance();
389 }
390
391 case Axis.DESCENDANT :
392 if (hasChildNodes()) {
393 return new FilterEnumeration(
394 new DescendantEnumeration(this, false),
395 nodeTest);
396 } else {
397 return EmptyEnumeration.getInstance();
398 }
399
400 case Axis.DESCENDANT_OR_SELF :
401 return new FilterEnumeration(
402 new DescendantEnumeration(this, true),
403 nodeTest);
404
405 case Axis.FOLLOWING :
406 return new FilterEnumeration(
407 new FollowingEnumeration(this),
408 nodeTest);
409
410 case Axis.FOLLOWING_SIBLING :
411 case Axis.NAMESPACE :
412 case Axis.PARENT :
413 case Axis.PRECEDING :
414 case Axis.PRECEDING_SIBLING :
415 case Axis.PRECEDING_OR_ANCESTOR :
416 return EmptyEnumeration.getInstance();
417
418 case Axis.SELF :
419 if (nodeTest.matches(this))
420 return new SingletonEnumeration(this);
421 return EmptyEnumeration.getInstance();
422
423 default :
424 throw new IllegalArgumentException(
425 "Unknown axis number " + axisNumber);
426 }
427 }
428
429 /***
430 * Determine the relative position of this node and another node, in
431 * document order. The other node will always be in the same document.
432 * @param other The other node, whose position is to be compared with
433 * this node
434 * @return -1 if this node precedes the other node, +1 if it follows the
435 * other node, or 0 if they are the same node. (In this case, isSameNode()
436 * will always return true, and the two nodes will produce the same result
437 * for generateId())
438 */
439 public int compareOrder(final NodeInfo other) {
440 if (other != this) {
441 return 1;
442 }
443 // are they the same node?
444 if (this == other || this.isSameNode(other)) {
445 return 0;
446 }
447 return 1;
448 }
449
450 /***
451 * Determine whether this is the same node as another node. <br />
452 * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b)
453 * @return true if this Node object and the supplied Node object
454 * represent the same node in the tree.
455 */
456 public boolean isSameNode(final NodeInfo other) {
457 return this == other;
458 }
459
460 }
This page was automatically generated by Maven