lmartin 2003/01/23 15:24:03
Modified: java/src/org/apache/xerces/dom NodeImpl.java
Log:
added initial impl for compareDocPosition
Revision Changes Path
1.63 +271 -1 xml-xerces/java/src/org/apache/xerces/dom/NodeImpl.java
Index: NodeImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/NodeImpl.java,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -r1.62 -r1.63
--- NodeImpl.java 17 Jan 2003 14:29:10 -0000 1.62
+++ NodeImpl.java 23 Jan 2003 23:23:59 -0000 1.63
@@ -69,6 +69,7 @@
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import org.w3c.dom.DocumentType;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
@@ -161,6 +162,14 @@
public static final short TREE_POSITION_DISCONNECTED = 0x00;
+ // DocumentPosition
+ public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
+ public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
+ public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
+ public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
+ public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
+ public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
+
/** Serialization version. */
static final long serialVersionUID = -6316591992167219696L;
@@ -781,6 +790,7 @@
* @return Returns how the given node is positioned relatively to this
* node.
* @since DOM Level 3
+ * @deprecated
*/
public short compareTreePosition(Node other) {
// Questions of clarification for this method - to be answered by the
@@ -979,6 +989,258 @@
return 0;
}
+ /**
+ * Compares a node with this node with regard to their position in the
+ * document.
+ * @param other The node to compare against this node.
+ * @return Returns how the given node is positioned relatively to this
+ * node.
+ * @since DOM Level 3
+ */
+ public short compareDocumentPosition(Node other) {
+
+ // If the nodes are the same, no flags should be set
+ if (this==other)
+ return 0;
+
+ Document thisOwnerDoc, otherOwnerDoc;
+ // get the respective Document owners.
+ if (this.getNodeType() == Node.DOCUMENT_NODE)
+ thisOwnerDoc = (Document)this;
+ else
+ thisOwnerDoc = this.getOwnerDocument();
+ if (other.getNodeType() == Node.DOCUMENT_NODE)
+ otherOwnerDoc = (Document)other;
+ else
+ otherOwnerDoc = other.getOwnerDocument();
+
+ // If from different documents, we know they are disconnected.
+ // Set DISCONNECTED for now.
+ // TODO: set order of Document nodes by assigning doc numbers to them
+ if (thisOwnerDoc != otherOwnerDoc)
+ return DOCUMENT_POSITION_DISCONNECTED;
+
+ // Find the ancestor of each node, and the distance each node is from
+ // its ancestor.
+ // During this traversal, look for ancestor/descendent relationships
+ // between the 2 nodes in question.
+ // We do this now, so that we get this info correct for attribute nodes
+ // and their children.
+
+ Node node;
+ Node thisAncestor = this;
+ Node otherAncestor = other;
+
+ int thisDepth=0;
+ int otherDepth=0;
+ for (node=this; node != null; node = node.getParentNode()) {
+ thisDepth +=1;
+ if (node == other)
+ // The other node is an ancestor of this one.
+ return (DOCUMENT_POSITION_CONTAINS |
+ DOCUMENT_POSITION_PRECEDING);
+ thisAncestor = node;
+ }
+
+ for (node=other; node!=null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == this)
+ // The other node is a descendent of the reference node.
+ return (DOCUMENT_POSITION_IS_CONTAINED |
+ DOCUMENT_POSITION_FOLLOWING);
+ otherAncestor = node;
+ }
+
+
+
+ int thisAncestorType = thisAncestor.getNodeType();
+ int otherAncestorType = otherAncestor.getNodeType();
+ Node thisNode = this;
+ Node otherNode = other;
+
+ // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
+ // LM: should rewrite this.
+ switch (thisAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ DocumentType container = thisOwnerDoc.getDoctype();
+ if (container == otherAncestor) return
+ (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
+ switch (otherAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ if (thisAncestorType != otherAncestorType)
+ // the nodes are of different types
+ return ((thisAncestorType>otherAncestorType) ?
+ DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
+ else {
+ // the nodes are of the same type. Find order.
+ if (thisAncestorType == Node.NOTATION_NODE)
+
+ if
(((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ if
(((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ }
+ }
+ }
+ thisNode = thisAncestor = thisOwnerDoc;
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE: {
+ if (otherNode == thisOwnerDoc)
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_CONTAINS);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING);
+ }
+ case Node.ATTRIBUTE_NODE: {
+ thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
+ if (otherAncestorType==Node.ATTRIBUTE_NODE) {
+ otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
+ if (otherNode == thisNode) {
+ if
(((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
+ return (DOCUMENT_POSITION_PRECEDING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ else
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
+ }
+ }
+
+ // Now, find the ancestor of the element
+ thisDepth=0;
+ for (node=thisNode; node != null; node=node.getParentNode()) {
+ thisDepth +=1;
+ if (node == otherNode)
+ // The other node is an ancestor of the owning element
+ {
+ return DOCUMENT_POSITION_PRECEDING;
+ }
+ thisAncestor = node;
+ }
+ }
+ }
+ switch (otherAncestorType) {
+ case Node.NOTATION_NODE:
+ case Node.ENTITY_NODE: {
+ DocumentType container = thisOwnerDoc.getDoctype();
+ if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
+ DOCUMENT_POSITION_FOLLOWING);
+ otherNode = otherAncestor = thisOwnerDoc;
+ break;
+ }
+ case Node.DOCUMENT_TYPE_NODE: {
+ if (thisNode == otherOwnerDoc)
+ return (DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IS_CONTAINED);
+ else
+ return (DOCUMENT_POSITION_PRECEDING);
+ }
+ case Node.ATTRIBUTE_NODE: {
+ otherDepth=0;
+ otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
+ for (node=otherNode; node != null; node=node.getParentNode()) {
+ otherDepth +=1;
+ if (node == thisNode)
+ // The other node is a descendent of the reference
+ // node's element
+ return DOCUMENT_POSITION_FOLLOWING |
+ DOCUMENT_POSITION_IS_CONTAINED;
+ otherAncestor = node;
+ }
+
+ }
+ }
+
+ // thisAncestor and otherAncestor must be the same at this point,
+ // otherwise, we are not in the same document fragment
+ // TODO: need to look at ordering document fragments as well?
+ if (thisAncestor != otherAncestor)
+ return DOCUMENT_POSITION_DISCONNECTED;
+
+
+ // Go up the parent chain of the deeper node, until we find a node
+ // with the same depth as the shallower node
+
+ if (thisDepth > otherDepth) {
+ for (int i=0; i<thisDepth - otherDepth; i++)
+ thisNode = thisNode.getParentNode();
+ // Check if the node we have reached is in fact "otherNode". This can
+ // happen in the case of attributes. In this case, otherNode
+ // "precedes" this.
+ if (thisNode == otherNode)
+ return DOCUMENT_POSITION_PRECEDING;
+ }
+
+ else {
+ for (int i=0; i<otherDepth - thisDepth; i++)
+ otherNode = otherNode.getParentNode();
+ // Check if the node we have reached is in fact "thisNode". This can
+ // happen in the case of attributes. In this case, otherNode
+ // "follows" this.
+ if (otherNode == thisNode)
+ return DOCUMENT_POSITION_FOLLOWING;
+ }
+
+ // We now have nodes at the same depth in the tree. Find a common
+ // ancestor.
+ Node thisNodeP, otherNodeP;
+ for (thisNodeP=thisNode.getParentNode(),
+ otherNodeP=otherNode.getParentNode();
+ thisNodeP!=otherNodeP;) {
+ thisNode = thisNodeP;
+ otherNode = otherNodeP;
+ thisNodeP = thisNodeP.getParentNode();
+ otherNodeP = otherNodeP.getParentNode();
+ }
+
+ // At this point, thisNode and otherNode are direct children of
+ // the common ancestor.
+ // See whether thisNode or otherNode is the leftmost
+
+ for (Node current=thisNodeP.getFirstChild();
+ current!=null;
+ current=current.getNextSibling()) {
+ if (current==otherNode) {
+ return DOCUMENT_POSITION_PRECEDING;
+ }
+ else if (current==thisNode) {
+ return DOCUMENT_POSITION_FOLLOWING;
+ }
+ }
+ // REVISIT: shouldn't get here. Should probably throw an
+ // exception
+ return 0;
+
+ }
+
+ /**
+ * This attribute returns the text content of this node and its
+ * descendants. When it is defined to be null, setting it has no effect.
+ * When set, any possible children this node may have are removed and
+ * replaced by a single <code>Text</code> node containing the string
+ * this attribute is set to. On getting, no serialization is performed,
+ * the returned string does not contain any markup. No whitespace
+ * normalization is performed, the returned string does not contain the
+ * element content whitespaces . Similarly, on setting, no parsing is
+ * performed either, the input string is taken as pure textual content.
+ * <br>The string returned is made of the text content of this node
+ * depending on its type, as defined below:
+ * <table border='1'>
+ * <tr>
+ * <th>Node type</th>
+ * <th>Content</th>
+ * </tr>
/**
* This attribute returns the text content of this node and its
@@ -1640,6 +1902,14 @@
protected void synchronizeData() {
// By default just change the flag to avoid calling this method again
needsSyncData(false);
+ }
+
+ /**
+ * For non-child nodes, the node which "points" to this node.
+ * For example, the owning element for an attribute
+ */
+ protected Node getContainer() {
+ return null;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]