View Javadoc
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 javax.xml.transform.TransformerException; 21 22 import com.icl.saxon.om.Axis; 23 import com.icl.saxon.om.AxisEnumeration; 24 import com.icl.saxon.om.DocumentInfo; 25 import com.icl.saxon.om.EmptyEnumeration; 26 import com.icl.saxon.om.NodeInfo; 27 import com.icl.saxon.om.SingletonEnumeration; 28 import com.icl.saxon.output.Outputter; 29 import com.icl.saxon.pattern.NodeTest; 30 import com.teamkonzept.dom4jb.schema.TextDescriptor; 31 32 public class Text 33 extends com.teamkonzept.dom4jb.dom.Text 34 implements NodeInfo, AxisNode { 35 36 private static final int LOW_20_MASK = 0xfffff; 37 private DescendantAxis axis; 38 private int position; 39 40 public Text(final Document document, 41 final TextDescriptor descriptor, 42 final Object bean) { 43 super(document, descriptor, bean); 44 this.axis = null; 45 this.position = -1; 46 } 47 48 public synchronized void attachAxis(final int position, 49 final DescendantAxis axis) { 50 this.axis = axis; 51 this.position = position; 52 } 53 54 public DescendantAxis getAxis() { 55 return axis; 56 } 57 58 public int getPosition() { 59 return position; 60 } 61 62 /*** 63 * Get a character string that uniquely identifies this node.<br /> 64 * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b) 65 * @return a string that uniquely identifies this node, within this 66 * document. The calling code prepends information to make the result 67 * unique across all documents. 68 */ 69 public String generateId() { 70 final StringBuffer sb = new StringBuffer(getParent().generateId()); 71 sb.append("text"); 72 sb.append(this.getChildIndex()); 73 return sb.toString(); 74 } 75 76 /*** 77 * Copy this node to a given outputter (deep copy) 78 */ 79 public void copy(final Outputter out) throws TransformerException { 80 out.writeContent(getStringValue()); 81 } 82 83 /*** 84 * Output all namespace nodes associated with this element. Does nothing if 85 * the node is not an element. 86 * @param out The relevant outputter 87 * @param includeAncestors True if namespaces declared on ancestor elements 88 * must be output; false if it is known that these are already on the 89 * result tree 90 */ 91 public void outputNamespaceNodes(final Outputter out, 92 final boolean includeAncestors) 93 throws TransformerException { 94 } 95 96 /*** 97 * Get the display name of this node. For elements and attributes this 98 * is [prefix:]localname. For unnamed nodes, it is an empty string. 99 * @return The display name of this node. 100 * For a node with no name, return an empty string. 101 */ 102 public String getDisplayName() { 103 return getNodeName(); 104 } 105 106 /*** 107 * Return the string value of the node. The interpretation of this depends 108 * on the type of node. For an element it is the accumulated character 109 * content of the element, including descendant elements. 110 * @return the string value of the node 111 */ 112 public String getStringValue() { 113 return getNodeValue(); 114 } 115 116 /*** 117 * Find the value of a given attribute of this node. <BR> 118 * This method is defined on all nodes to meet XSL requirements, but for 119 * nodes other than elements it will always return null. 120 * @param uri the namespace uri of an attribute ("" if no namespace) 121 * @param localName the local name of the attribute 122 * @return the value of the attribute, if it exists, otherwise null 123 */ 124 public String getAttributeValue(final String uri, final String localName) { 125 return ""; 126 } 127 128 /*** 129 * Get the value of a given attribute of this node 130 * @param fingerprint The fingerprint of the attribute name 131 * @return the attribute value if it exists or null if not 132 */ 133 public String getAttributeValue(final int fingerprint) { 134 return null; 135 } 136 137 public void expandStringValue(final StringBuffer sb) { 138 sb.append(getNodeValue()); 139 } 140 141 public Namespace[] getNamespaces() { 142 return null; 143 } 144 // ------- GENERAL stuff ------- 145 146 /*** 147 * Get the System ID for the node. 148 * @return the System Identifier of the entity in the source document 149 * containing the node, or null if not known. Note this is not the same as 150 * the base URI: the base URI can be modified by xml:base, but the 151 * system ID cannot. 152 */ 153 public String getSystemId() { 154 return ((Document) document).getSystemId(); 155 } 156 157 public void setSystemId(final String uri) { 158 ((Document) document).setSystemId(uri); 159 } 160 161 /*** 162 * Get the Base URI for the node, that is, the URI used for resolving a 163 * relative URI contained in the node. This will be the same as the 164 * System ID unless xml:base has been used. 165 */ 166 public String getBaseURI() { 167 return getSystemId(); 168 } 169 170 /*** 171 * Get line number 172 * @return the line number of the node in its original source document; 173 * or -1 if not available 174 */ 175 public int getLineNumber() { 176 return -1; 177 } 178 179 /*** 180 * Get name code. The name code is a coded form of the node name: two nodes 181 * with the same name code have the same namespace URI, the same local name, 182 * and the same prefix. By masking the name code with &0xfffff, you get a 183 * fingerprint: two nodes with the same fingerprint have the same local name 184 * and namespace URI. 185 * @see com.icl.saxon.om.NamePool#allocate allocate 186 */ 187 public int getNameCode() { 188 return -1; 189 } 190 191 /*** 192 * Get fingerprint. The fingerprint is a coded form of the expanded name 193 * of the node: two nodes 194 * with the same name code have the same namespace URI and the same 195 * local name. A fingerprint of -1 should be returned for a node with 196 * no name. 197 */ 198 public int getFingerprint() { 199 return getNameCode() & LOW_20_MASK; 200 } 201 202 /*** 203 * Get the URI part of the name of this node. This is the URI corresponding 204 * to the prefix, or the URI of the default namespace if appropriate. 205 * @return The URI of the namespace of this node. For an unnamed node, 206 * return null. For a node with an empty prefix, return an empty string. 207 */ 208 public String getURI() { 209 return null; 210 } 211 212 /*** 213 * Get the NodeInfo object representing the parent of this node 214 */ 215 public NodeInfo getParent() { 216 return (NodeInfo) getParentNode(); 217 } 218 219 /*** 220 * Get the prefix part of the name of this node. This is the name before 221 * the ":" if any. 222 * @return the prefix part of the name. For an unnamed node, return an 223 * empty string. 224 */ 225 public String getPrefix() { 226 return ""; 227 } 228 229 /*** 230 * Get the prefix part of the name of this node. This is the name before 231 * the ":" if any. 232 * @return the prefix part of the name. For an unnamed node, return an 233 * empty string. 234 */ 235 public String getLocalName() { 236 return ""; 237 } 238 239 /*** 240 * Get the root (document) node 241 * @return the DocumentInfo representing the containing document 242 */ 243 public DocumentInfo getDocumentRoot() { 244 return (DocumentInfo) document; 245 } 246 247 /*** 248 * Copy the string-value of this node to a given outputter 249 */ 250 public void copyStringValue(final Outputter out) 251 throws TransformerException { 252 out.writeContent(getStringValue()); 253 } 254 255 /*** 256 * Return an enumeration over the nodes reached by the given axis from 257 * this node 258 * @param nodeType the type(s) of node to be included, 259 * e.g. NodeInfo.ELEMENT, NodeInfo.TEXT. 260 * The value NodeInfo.NODE means include any type of node. 261 * @param nodeTest A pattern to be matched by the returned nodes 262 * @return a NodeEnumeration that scans the nodes reached by the axis 263 * in turn. 264 */ 265 public AxisEnumeration getEnumeration( 266 final byte axisNumber, 267 final NodeTest nodeTest) { 268 switch (axisNumber) { 269 case Axis.ANCESTOR : 270 return new FilterEnumeration( 271 new AncestorEnumeration(this, false), 272 nodeTest); 273 274 case Axis.ANCESTOR_OR_SELF : 275 return new FilterEnumeration( 276 new AncestorEnumeration(this, true), 277 nodeTest); 278 279 case Axis.ATTRIBUTE : 280 case Axis.CHILD : 281 case Axis.DESCENDANT : 282 return EmptyEnumeration.getInstance(); 283 284 case Axis.DESCENDANT_OR_SELF : 285 if (nodeTest.matches(this)) 286 return new SingletonEnumeration(this); 287 return EmptyEnumeration.getInstance(); 288 289 case Axis.FOLLOWING : 290 return new FilterEnumeration( 291 new FollowingEnumeration(this), 292 nodeTest); 293 294 case Axis.FOLLOWING_SIBLING : 295 return new FilterEnumeration( 296 new SiblingEnumeration(this, true), 297 nodeTest); 298 299 case Axis.NAMESPACE : 300 return EmptyEnumeration.getInstance(); 301 302 case Axis.PARENT : 303 if (nodeTest.matches((NodeInfo) parent)) 304 return new SingletonEnumeration((NodeInfo) parent); 305 return EmptyEnumeration.getInstance(); 306 307 case Axis.PRECEDING : 308 return new FilterEnumeration( 309 new PrecedingEnumeration(this, false), 310 nodeTest); 311 312 case Axis.PRECEDING_SIBLING : 313 return new FilterEnumeration( 314 new SiblingEnumeration(this, false), 315 nodeTest); 316 317 case Axis.SELF : 318 if (nodeTest.matches(this)) 319 return new SingletonEnumeration(this); 320 return EmptyEnumeration.getInstance(); 321 322 case Axis.PRECEDING_OR_ANCESTOR : 323 return new FilterEnumeration( 324 new PrecedingEnumeration(this, true), 325 nodeTest); 326 327 default : 328 throw new IllegalArgumentException( 329 "Unknown axis number " + axisNumber); 330 } 331 } 332 333 /*** 334 * Determine the relative position of this node and another node, 335 * in document order. The other node will always be in the same document. 336 * @param other The other node, whose position is to be compared with 337 * this node 338 * @return -1 if this node precedes the other node, +1 if it follows 339 * the other node, or 0 if they are the same node. (In this case, 340 * isSameNode() will always return true, and the two nodes will produce 341 * the same result for generateId()) 342 */ 343 public int compareOrder(final NodeInfo other) { 344 // are they the same node? 345 if (this == other || this.isSameNode(other)) { 346 return 0; 347 } 348 349 // are they siblings (common case) 350 if (this.getParent().isSameNode(other.getParent())) { 351 return this.getChildIndex() 352 - ((com.teamkonzept.dom4jb.dom.Node) other).getChildIndex(); 353 } 354 355 // are they evaluated on the same descendant axis 356 DescendantAxis axis; 357 int axisIdx = 0; 358 synchronized (this) { 359 axis = this.getAxis(); 360 if (axis != null) { 361 axisIdx = this.getPosition(); 362 } 363 } 364 AxisNode node = (AxisNode) other; 365 if (axis != null) { 366 synchronized (node) { 367 final DescendantAxis otherAxis = node.getAxis(); 368 if (otherAxis == axis) { 369 return axisIdx - node.getPosition(); 370 } 371 } 372 } 373 374 // find the depths of both nodes in the tree 375 int depth1 = 0; 376 int depth2 = 0; 377 NodeInfo p1 = this; 378 NodeInfo p2 = other; 379 while (p1 != null) { 380 depth1++; 381 p1 = p1.getParent(); 382 } 383 while (p2 != null) { 384 depth2++; 385 p2 = p2.getParent(); 386 } 387 388 // move up one branch of the tree so we have two nodes on the same level 389 p1 = this; 390 while (depth1 > depth2) { 391 p1 = p1.getParent(); 392 depth1--; 393 } 394 395 p2 = other; 396 while (depth2 > depth1) { 397 p2 = p2.getParent(); 398 depth2--; 399 } 400 401 // now move up both branches in sync until we find a common parent 402 while (true) { 403 NodeInfo par1 = p1.getParent(); 404 NodeInfo par2 = p2.getParent(); 405 if (par1 == null || par2 == null) { 406 throw new NullPointerException( 407 "DOM tree compare" + " - internal error"); 408 } 409 if (par1.isSameNode(par2)) { 410 return ((com.teamkonzept.dom4jb.dom.Node) p1).getChildIndex() 411 - ((com.teamkonzept.dom4jb.dom.Node) p2).getChildIndex(); 412 } 413 p1 = par1; 414 p2 = par2; 415 } 416 } 417 418 /*** 419 * Determine whether this is the same node as another node. <br /> 420 * Note: a.isSameNode(b) if and only if generateId(a)==generateId(b) 421 * @return true if this Node object and the supplied Node object 422 * represent the same node in the tree. 423 */ 424 public boolean isSameNode(final NodeInfo other) { 425 if (this == other) { 426 return true; 427 } 428 if (other == null 429 || this.getNodeType() != other.getNodeType() 430 || !(other instanceof com.teamkonzept.dom4jb.dom.Node) 431 || getChildIndex() 432 != ((com.teamkonzept.dom4jb.dom.Node) other).getChildIndex()) { 433 return false; 434 } 435 return this.equals(other); 436 } 437 }

This page was automatically generated by Maven