You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by le...@locus.apache.org on 2000/01/13 01:28:21 UTC
cvs commit: xml-xerces/java/src/org/apache/xerces/dom NodeContainer.java AttrImpl.java DocumentFragmentImpl.java DocumentImpl.java DocumentTypeImpl.java ElementDefinitionImpl.java ElementImpl.java EntityImpl.java EntityReferenceImpl.java Makefile NodeImpl.java
lehors 00/01/12 16:28:21
Modified: java/src/org/apache/xerces/dom AttrImpl.java
DocumentFragmentImpl.java DocumentImpl.java
DocumentTypeImpl.java ElementDefinitionImpl.java
ElementImpl.java EntityImpl.java
EntityReferenceImpl.java Makefile NodeImpl.java
Added: java/src/org/apache/xerces/dom NodeContainer.java
Log:
Changed NodeImpl to not accept any children,
added a new class, NodeContainer, which inherits from NodeImpl to add the
capability of having children.
This makes leaf nodes, such as Text nodes, smaller, leading to a smaller
foot print.
Changed AttrImpl, DocumentFragmentImpl, DocumentImpl, DocumentTypeImpl,
ElementImpl, ElementDefinitionImpl, EntityImpl, EntityReferenceImple,
to inherit from NodeContainer.
Revision Changes Path
1.5 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/AttrImpl.java
Index: AttrImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/AttrImpl.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- AttrImpl.java 2000/01/06 21:56:34 1.4
+++ AttrImpl.java 2000/01/13 00:28:19 1.5
@@ -97,7 +97,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class AttrImpl
- extends NodeImpl
+ extends NodeContainer
implements Attr {
//
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/DocumentFragmentImpl.java
Index: DocumentFragmentImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DocumentFragmentImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- DocumentFragmentImpl.java 1999/11/09 01:13:22 1.1
+++ DocumentFragmentImpl.java 2000/01/13 00:28:20 1.2
@@ -100,7 +100,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class DocumentFragmentImpl
- extends NodeImpl
+ extends NodeContainer
implements DocumentFragment {
//
1.6 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/DocumentImpl.java
Index: DocumentImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DocumentImpl.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- DocumentImpl.java 2000/01/06 23:59:47 1.5
+++ DocumentImpl.java 2000/01/13 00:28:20 1.6
@@ -95,7 +95,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class DocumentImpl
- extends NodeImpl
+ extends NodeContainer
implements Document, DocumentTraversal, DocumentEvent {
//
1.4 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/DocumentTypeImpl.java
Index: DocumentTypeImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DocumentTypeImpl.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- DocumentTypeImpl.java 2000/01/06 21:56:35 1.3
+++ DocumentTypeImpl.java 2000/01/13 00:28:20 1.4
@@ -80,7 +80,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class DocumentTypeImpl
- extends NodeImpl
+ extends NodeContainer
implements DocumentType {
//
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/ElementDefinitionImpl.java
Index: ElementDefinitionImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/ElementDefinitionImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ElementDefinitionImpl.java 1999/11/09 01:13:24 1.1
+++ ElementDefinitionImpl.java 2000/01/13 00:28:20 1.2
@@ -69,7 +69,7 @@
* @version
*/
public class ElementDefinitionImpl
- extends NodeImpl {
+ extends NodeContainer {
//
// Constants
1.5 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/ElementImpl.java
Index: ElementImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/ElementImpl.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- ElementImpl.java 2000/01/05 01:34:48 1.4
+++ ElementImpl.java 2000/01/13 00:28:20 1.5
@@ -80,7 +80,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class ElementImpl
- extends NodeImpl
+ extends NodeContainer
implements Element {
//
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/EntityImpl.java
Index: EntityImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/EntityImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- EntityImpl.java 1999/11/09 01:13:25 1.1
+++ EntityImpl.java 2000/01/13 00:28:20 1.2
@@ -94,7 +94,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class EntityImpl
- extends NodeImpl
+ extends NodeContainer
implements Entity {
//
1.2 +1 -1 xml-xerces/java/src/org/apache/xerces/dom/EntityReferenceImpl.java
Index: EntityReferenceImpl.java
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/EntityReferenceImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- EntityReferenceImpl.java 1999/11/09 01:13:25 1.1
+++ EntityReferenceImpl.java 2000/01/13 00:28:20 1.2
@@ -111,7 +111,7 @@
* @since PR-DOM-Level-1-19980818.
*/
public class EntityReferenceImpl
- extends NodeImpl
+ extends NodeContainer
implements EntityReference {
//
1.2 +2 -1 xml-xerces/java/src/org/apache/xerces/dom/Makefile
Index: Makefile
===================================================================
RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/Makefile,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- Makefile 1999/11/09 01:13:26 1.1
+++ Makefile 2000/01/13 00:28:20 1.2
@@ -43,7 +43,8 @@
NodeImpl.class\
NotationImpl.class\
ProcessingInstructionImpl.class\
- TextImpl.class
+ TextImpl.class \
+ NodeContainer.class
all: dirs compile
1.6 +73 -568 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.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- NodeImpl.java 2000/01/12 21:41:14 1.5
+++ NodeImpl.java 2000/01/13 00:28:20 1.6
@@ -77,11 +77,13 @@
* with the exception of Document itself, only through a specific
* Document's factory methods.
* <P>
- * Node itself implements shared behaviors such as siblings and
+ * The Node interface provides shared behaviors such as siblings and
* children, both for consistancy and so that the most common tree
* operations may be performed without constantly having to downcast
* to specific node types. When there is no obvious mapping for one of
* these queries, it will respond with null.
+ * Note that the default behavior is that children are forbidden. To
+ * permit them, the subclass NodeContainer overrides several methods.
* <P>
* NodeImpl also implements NodeList, so it can return itself in
* response to the getChildNodes() query. This eliminiates the need
@@ -89,9 +91,6 @@
* IMPLEMENTATION DETAIL; applications should _never_ assume that
* this identity exists.
* <P>
- * Note that the default behavior is that children are forbidden. To
- * permit them, the subclass's constructor sets isLeafNode false.
- * <P>
* All nodes in a single document must originate
* in that document. (Note that this is much tighter than "must be
* same implementation") Nodes are all aware of their ownerDocument,
@@ -147,36 +146,11 @@
/** NON-DOM FEATURE; see setUserData/getUserData. **/
protected Object userData;
- // children
-
- /** First child. */
- protected NodeImpl firstChild;
-
- /** Last child. */
- protected NodeImpl lastChild;
-
// lazy-evaluation nifo
- /** Synchronization of child nodes needed. */
- protected transient boolean syncChildren;
-
/** Synchronization of data needed. */
protected transient boolean syncData;
- // other transients
-
- /** Last change number for index caching. */
- protected transient int nodeListChanges = -1;
-
- /** Cached node list length. */
- protected transient int nodeListLength;
-
- /** Last requested node. */
- protected transient NodeImpl nodeListNode;
-
- /** Last requested node index. */
- protected transient int nodeListIndex;
-
// internal data
/**
@@ -204,43 +178,7 @@
*/
int changes = 0;
- /** Table for quick check of child insertion. */
- protected static int[] kidOK;
-
- //
- // Static initialization
- //
-
- static {
-
- kidOK = new int[13];
-
- kidOK[DOCUMENT_NODE] =
- 1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
- 1 << COMMENT_NODE | 1 << DOCUMENT_TYPE_NODE;
-
- kidOK[DOCUMENT_FRAGMENT_NODE] =
- kidOK[ENTITY_NODE] =
- kidOK[ENTITY_REFERENCE_NODE] =
- kidOK[ELEMENT_NODE] =
- 1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
- 1 << COMMENT_NODE | 1 << TEXT_NODE |
- 1 << CDATA_SECTION_NODE | 1 << ENTITY_REFERENCE_NODE |
- 1 << ATTRIBUTE_NODE;
-
- kidOK[ATTRIBUTE_NODE] =
- 1 << TEXT_NODE | 1 << ENTITY_REFERENCE_NODE;
-
- kidOK[DOCUMENT_TYPE_NODE] =
- kidOK[PROCESSING_INSTRUCTION_NODE] =
- kidOK[COMMENT_NODE] =
- kidOK[TEXT_NODE] =
- kidOK[CDATA_SECTION_NODE] =
- kidOK[NOTATION_NODE] =
- 0;
- } // static
-
//
// Constructors
//
@@ -266,22 +204,6 @@
public NodeImpl() {}
//
- // Serialization methods
- //
-
- /** Deserialize object. */
- private void readObject(ObjectInputStream ois)
- throws ClassNotFoundException, IOException {
-
- // perform default deseralization
- ois.defaultReadObject();
-
- // initialize transients
- nodeListChanges = -1;
-
- } // readObject(ObjectInputStream)
-
- //
// Node methods
//
@@ -400,6 +322,9 @@
* Adds a child node to the end of the list of children for this node.
* Convenience shorthand for insertBefore(newChild,null).
* @see #insertBefore(Node, Node)
+ * <P>
+ * By default we do not accept any children, NodeContainer overrides this.
+ * @see NodeContainer
*
* @returns newChild, in its new state (relocated, or emptied in the
* case of DocumentNode.)
@@ -414,7 +339,8 @@
* read-only.
*/
public Node appendChild(Node newChild) throws DOMException {
- return insertBefore(newChild, null);
+ throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
+ "HIERARCHY_REQUEST_ERR");
}
/**
@@ -422,6 +348,11 @@
* generic "copy constructor" for nodes. The newly returned object should
* be completely independent of the source object's subtree, so changes
* in one after the clone has been made will not affect the other.
+ * <P>
+ * Note: since we never have any children deep is meaningless here,
+ * NodeContainer overrides this behavior.
+ * @see NodeContainer
+ *
* <p>
* Example: Cloning a Text node will copy both the node and the text it
* contains.
@@ -437,13 +368,9 @@
*/
public Node cloneNode(boolean deep) {
-
if (syncData) {
synchronizeData();
- }
- if (syncChildren) {
- synchronizeChildren();
- }
+ }
NodeImpl newnode;
try {
@@ -461,18 +388,7 @@
newnode.parentNode = null;
newnode.previousSibling = null;
newnode.nextSibling = null;
- newnode.firstChild = null;
- newnode.lastChild = null;
- // Then, if deep, clone the kids too.
- if (deep) {
- for (NodeImpl child = (NodeImpl)getFirstChild();
- child != null;
- child = (NodeImpl)child.getNextSibling()) {
- newnode.appendChild(child.cloneNode(true));
- }
- }
-
// REVISIT: Should the user data be cloned?
return newnode;
@@ -522,12 +438,12 @@
/**
* Test whether this node has any children. Convenience shorthand
* for (Node.getFirstChild()!=null)
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
*/
public boolean hasChildNodes() {
- if (syncChildren) {
- synchronizeChildren();
- }
- return firstChild != null;
+ return false;
}
/**
@@ -544,38 +460,33 @@
* differently.
*/
public NodeList getChildNodes() {
- // JKESS: KNOWN ISSUE HERE
-
- if (syncChildren) {
- synchronizeChildren();
- }
return this;
-
- } // getChildNodes():NodeList
+ }
- /** The first child of this Node, or null if none. */
+ /** The first child of this Node, or null if none.
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
+ */
public Node getFirstChild() {
-
- if (syncChildren) {
- synchronizeChildren();
- }
- return firstChild;
-
- } // getFirstChild():Node
+ return null;
+ }
- /** The first child of this Node, or null if none. */
+ /** The first child of this Node, or null if none.
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
+ */
public Node getLastChild() {
-
- if (syncChildren) {
- synchronizeChildren();
- }
- return lastChild;
-
- } // getLastChild():Node
+ return null;
+ }
/**
* Move one or more node(s) to our list of children. Note that this
* implicitly removes them from their previous parent.
+ * <P>
+ * By default we do not accept any children, NodeContainer overrides this.
+ * @see NodeContainer
*
* @param newChild The Node to be moved to our subtree. As a
* convenience feature, inserting a DocumentNode will instead insert
@@ -601,218 +512,18 @@
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
- public Node insertBefore(Node newChild, Node refChild)
- throws DOMException {
- // Tail-call; optimizer should be able to do good things with.
- return internalInsertBefore(newChild,refChild,MUTATION_ALL);
- } // insertBefore(Node,Node):Node
-
- /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
- * to control which mutation events are spawned. This version of the
- * insertBefore operation allows us to do so. It is not intended
- * for use by application programs.
- */
- Node internalInsertBefore(Node newChild, Node refChild,int mutationMask)
- throws DOMException {
-
- if (readOnly)
- throw new DOMExceptionImpl(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- "NO_MODIFICATION_ALLOWED_ERR");
-
- boolean errorChecking = ownerDocument.errorChecking;
- if(errorChecking && !(newChild instanceof NodeImpl)
- ||
- !(
- newChild.getOwnerDocument() == ownerDocument
- ||
- // SPECIAL-CASE: Document has no owner, but may be the owner.
- ( getNodeType() == Node.DOCUMENT_NODE &&
- newChild.getOwnerDocument() == (Document)this )
- ) ) {
- throw new DOMExceptionImpl(DOMException.WRONG_DOCUMENT_ERR,
- "WRONG_DOCUMENT_ERR");
- }
-
- if (syncChildren) {
- synchronizeChildren();
- }
-
- // Convert to internal type, to avoid repeated casting
- NodeImpl newInternal = (NodeImpl)newChild;
-
- if (errorChecking) {
- // Prevent cycles in the tree
- boolean treeSafe = true;
- for (NodeImpl a = parentNode; treeSafe && a != null; a = a.parentNode) {
- treeSafe = newInternal != a;
- }
- if(!treeSafe) {
- throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
- "HIERARCHY_REQUEST_ERR");
- }
-
- // refChild must in fact be a child of this node (or null)
- if(refChild != null && refChild.getParentNode() != this) {
- throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
- "NOT_FOUND_ERR");
- }
- }
-
- if (newInternal.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
- // SLOW BUT SAFE: We could insert the whole subtree without
- // juggling so many next/previous pointers. (Wipe out the
- // parent's child-list, patch the parent pointers, set the
- // ends of the list.) But we know some subclasses have special-
- // case behavior they add to insertBefore(), so we don't risk it.
- // This approch also takes fewer bytecodes.
-
- // NOTE: If one of the children is not a legal child of this
- // node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
- // have been transferred. (Alternative behaviors would be to
- // reparent up to the first failure point or reparent all those
- // which are acceptable to the target node, neither of which is
- // as robust. PR-DOM-0818 isn't entirely clear on which it
- // recommends?????
-
- // No need to check kids for right-document; if they weren't,
- // they wouldn't be kids of that DocFrag.
- for (Node kid = newInternal.getFirstChild(); // Prescan
- kid != null;
- kid = kid.getNextSibling()) {
-
- if (errorChecking && !ownerDocument.isKidOK(this, kid)) {
- throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
- "HIERARCHY_REQUEST_ERR");
- }
- }
-
- while (newInternal.hasChildNodes()) {
- insertBefore(newInternal.getFirstChild(), refChild);
- }
- }
-
- else if (errorChecking && !ownerDocument.isKidOK(this, newInternal)) {
- throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
- "HIERARCHY_REQUEST_ERR");
- }
- else {
- EnclosingAttr enclosingAttr=null;
- if(MUTATIONEVENTS && (mutationMask&MUTATION_AGGREGATE)!=0)
- {
- // MUTATION PREPROCESSING
- // No direct pre-events, but if we're within the scope
- // of an Attr and DOMAttrModified was requested,
- // we need to preserve its previous value.
- LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- enclosingAttr=getEnclosingAttr();
- }
- }
-
- Node oldparent = newInternal.getParentNode();
- if (oldparent != null) {
- oldparent.removeChild(newInternal);
- }
-
- NodeImpl prev;
- // Find the node we're inserting after, if any (null if
- // inserting to head of list)
- prev = (refChild == null)
- ? lastChild : ((NodeImpl)refChild).previousSibling;
-
- // Attach up
- newInternal.parentNode = this;
-
- // Attach after
- newInternal.previousSibling = prev;
- if (prev == null) {
- firstChild = newInternal;
- }
- else {
- prev.nextSibling = newInternal;
- }
-
- // Attach before
- newInternal.nextSibling = (NodeImpl)refChild;
- if (refChild == null) {
- lastChild=newInternal;
- }
- else {
- ((NodeImpl)refChild).previousSibling = newInternal;
- }
-
- changed();
-
- if(MUTATIONEVENTS)
- {
- // MUTATION POST-EVENTS:
- // "Local" events (non-aggregated)
- if( (mutationMask&MUTATION_LOCAL) != 0)
- {
- // New child is told it was inserted, and where
- LCount lc=LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- MutationEvent me=
- new MutationEventImpl();
- //?????ownerDocument.createEvent("MutationEvents");
- me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED,true,false,
- this,null,null,null);
- newInternal.dispatchEvent(me);
- }
-
- // If within the Document, tell the subtree it's been added
- // to the Doc.
- lc=LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- NodeImpl eventAncestor=this;
- if(enclosingAttr!=null)
- eventAncestor=(NodeImpl)(enclosingAttr.node.getOwnerElement());
- if(eventAncestor!=null) // Might have been orphan Attr
- {
- NodeImpl p=eventAncestor;
- while(p!=null)
- {
- eventAncestor=p; // Last non-null ancestor
- // In this context, ancestry includes
- // walking back from Attr to Element
- if(p.getNodeType()==ATTRIBUTE_NODE)
- p=(ElementImpl)( ((AttrImpl)p).getOwnerElement() );
- else
- p=p.parentNode;
- }
- if(eventAncestor.getNodeType()==Node.DOCUMENT_NODE)
- {
- MutationEvent me=
- new MutationEventImpl();
- //?????ownerDocument.createEvent("MutationEvents");
- me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT,
- false,false,
- null,null,null,null);
- dispatchEventToSubtree(newInternal,me);
- }
- }
- }
- }
-
- // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified
- // (Common to most kinds of mutation)
- if( (mutationMask&MUTATION_AGGREGATE) != 0)
- dispatchAggregateEvents(enclosingAttr);
- }
-
- }
-
- return newInternal;
-
- } // internalInsertBefore(Node,Node,int):Node
+ public Node insertBefore(Node newChild, Node refChild)
+ throws DOMException {
+ throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
+ "HIERARCHY_REQUEST_ERR");
+ }
/**
* Remove a child from this Node. The removed child's subtree
* remains intact so it may be re-inserted elsewhere.
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
*
* @return oldChild, in its new state (removed).
*
@@ -822,143 +533,20 @@
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
- public Node removeChild(Node oldChild)
+ public Node removeChild(Node oldChild)
throws DOMException {
- // Tail-call, should be optimizable
- return internalRemoveChild(oldChild,MUTATION_ALL);
- } // removeChild(Node) :Node
-
- /** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
- * to control which mutation events are spawned. This version of the
- * removeChild operation allows us to do so. It is not intended
- * for use by application programs.
- */
- Node internalRemoveChild(Node oldChild,int mutationMask)
- throws DOMException {
-
- if (readOnly) {
- throw new DOMExceptionImpl(
- DOMException.NO_MODIFICATION_ALLOWED_ERR,
- "NO_MODIFICATION_ALLOWED_ERR");
- }
-
- if (ownerDocument.errorChecking &&
- oldChild != null && oldChild.getParentNode() != this) {
- throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
- "NOT_FOUND_ERR");
- }
-
- // call out to any NodeIterators to remove the Node and fix-up the iterator.
- Enumeration iterators = ownerDocument.getNodeIterators();
- if (iterators != null) {
- while ( iterators.hasMoreElements()) {
- ((NodeIteratorImpl)iterators.nextElement()).removeNode(oldChild);
- }
- }
-
- NodeImpl oldInternal = (NodeImpl) oldChild;
-
- EnclosingAttr enclosingAttr=null;
- if(MUTATIONEVENTS)
- {
- // MUTATION PREPROCESSING AND PRE-EVENTS:
- // If we're within the scope of an Attr and DOMAttrModified
- // was requested, we need to preserve its previous value for
- // that event.
- LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- enclosingAttr=getEnclosingAttr();
- }
-
- if( (mutationMask&MUTATION_LOCAL) != 0)
- {
- // Child is told that it is about to be removed
- lc=LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- MutationEvent me=
- new MutationEventImpl();
- //?????ownerDocument.createEvent("MutationEvents");
- me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED,true,false,
- this,null,null,null);
- oldInternal.dispatchEvent(me);
- }
-
- // If within Document, child's subtree is informed that it's
- // losing that status
- lc=LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- NodeImpl eventAncestor=this;
- if(enclosingAttr!=null)
- eventAncestor=(NodeImpl)(enclosingAttr.node.getOwnerElement());
- if(eventAncestor!=null) // Might have been orphan Attr
- {
- for(NodeImpl p=eventAncestor.parentNode;
- p!=null;
- p=p.parentNode)
- {
- eventAncestor=p; // Last non-null ancestor
- }
- if(eventAncestor.getNodeType()==Node.DOCUMENT_NODE)
- {
- MutationEvent me=
- new MutationEventImpl();
- //?????ownerDocument.createEvent("MutationEvents");
- me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT,
- false,false,
- null,null,null,null);
- dispatchEventToSubtree(oldInternal,me);
- }
- }
- }
- }
- } // End mutation preprocessing
-
- // Patch tree past oldChild
- NodeImpl prev = oldInternal.previousSibling;
- NodeImpl next = oldInternal.nextSibling;
-
- if (prev != null) {
- prev.nextSibling = next;
- }
- else {
- firstChild = next;
- }
-
- if (next != null) {
- next.previousSibling = prev;
- }
- else {
- lastChild = prev;
- }
-
- // Remove oldInternal's references to tree
- oldInternal.parentNode = null;
- oldInternal.nextSibling = null;
- oldInternal.previousSibling = null;
-
- changed();
-
- if(MUTATIONEVENTS)
- {
- // MUTATION POST-EVENTS:
- // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
- // if required. (Common to most kinds of mutation)
- if( (mutationMask&MUTATION_AGGREGATE) != 0)
- dispatchAggregateEvents(enclosingAttr);
- } // End mutation postprocessing
-
- return oldInternal;
-
- } // internalRemoveChild(Node,int):Node
+ throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
+ "NOT_FOUND_ERR");
+ }
/**
* Make newChild occupy the location that oldChild used to
* have. Note that newChild will first be removed from its previous
* parent, if any. Equivalent to inserting newChild before oldChild,
* then removing oldChild.
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
*
* @returns oldChild, in its new state (removed).
*
@@ -977,35 +565,8 @@
*/
public Node replaceChild(Node newChild, Node oldChild)
throws DOMException {
- // If Mutation Events are being generated, this operation might
- // throw aggregate events twice when modifying an Attr -- once
- // on insertion and once on removal. DOM Level 2 does not specify
- // this as either desirable or undesirable, but hints that
- // aggregations should be issued only once per user request.
-
- EnclosingAttr enclosingAttr=null;
- if(MUTATIONEVENTS)
- {
- // MUTATION PREPROCESSING AND PRE-EVENTS:
- // If we're within the scope of an Attr and DOMAttrModified
- // was requested, we need to preserve its previous value for
- // that event.
- LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
- if(lc.captures+lc.bubbles+lc.defaults>0)
- {
- enclosingAttr=getEnclosingAttr();
- }
- } // End mutation preprocessing
-
- internalInsertBefore(newChild, oldChild,MUTATION_LOCAL);
- internalRemoveChild(oldChild,MUTATION_LOCAL);
-
- if(MUTATIONEVENTS)
- {
- dispatchAggregateEvents(enclosingAttr);
- }
-
- return oldChild;
+ throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
+ "HIERARCHY_REQUEST_ERR");
}
//
@@ -1014,60 +575,29 @@
/**
* NodeList method: Count the immediate children of this node
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
+ *
* @return int
*/
public int getLength() {
-
- if (nodeListChanges != changes) {
- nodeListChanges = changes;
- nodeListLength = 0;
- nodeListIndex = 0;
- nodeListNode = firstChild;
- for (NodeImpl node = firstChild; node != null; node = node.nextSibling) {
- nodeListLength++;
- }
- }
-
- return nodeListLength;
-
- } // getLength():int
+ return 0;
+ }
/**
* NodeList method: Return the Nth immediate child of this node, or
* null if the index is out of bounds.
+ * <P>
+ * By default we do not have any children, NodeContainer overrides this.
+ * @see NodeContainer
+ *
* @return org.w3c.dom.Node
* @param Index int
*/
public Node item(int index) {
-
- // short way
- if (nodeListChanges == changes) {
- if (nodeListIndex < index) {
- while (nodeListIndex < index && nodeListNode != null) {
- nodeListIndex++;
- nodeListNode = nodeListNode.nextSibling;
- }
- }
- else if (nodeListIndex > index) {
- while (nodeListIndex > index && nodeListNode != null) {
- nodeListIndex--;
- nodeListNode = nodeListNode.previousSibling;
- }
- }
- return nodeListNode;
- }
-
- // long way
- nodeListChanges = changes;
- nodeListNode = firstChild;
- for (nodeListIndex = 0;
- nodeListIndex < index && nodeListNode != null;
- nodeListIndex++) {
- nodeListNode = nodeListNode.nextSibling;
- }
- return nodeListNode;
-
- } // item(int):Node
+ return null;
+ }
//
// DOM2: methods, getters, setters
@@ -1092,11 +622,8 @@
* to take action.
*/
public void normalize() {
-
- Node kid;
- for (kid = getFirstChild(); kid != null; kid = kid.getNextSibling()) {
- kid.normalize();
- }
+ /* by default we do not have any children,
+ NodeContainer overrides this behavior */
}
/**
@@ -1587,7 +1114,7 @@
for(int i=a.getLength()-1;i>=0;--i)
dispatchEventToSubtree(((NodeImpl)a.item(i)),e);
}
- dispatchEventToSubtree(n.firstChild,e);
+ dispatchEventToSubtree((NodeImpl)n.getFirstChild(),e);
dispatchEventToSubtree(n.nextSibling,e);
}
} // dispatchEventToSubtree(NodeImpl,Event) :void
@@ -1740,6 +1267,10 @@
* is during construction of EntityRefernces, where it will be used to
* lock the contents replicated from Entity so they can't be casually
* altered. It _could_ be published as a DOM extension, if desired.
+ * <P>
+ * Note: since we never have any children deep is meaningless here,
+ * NodeContainer overrides this behavior.
+ * @see NodeContainer
*
* @param readOnly True or false as desired.
* @param deep If true, children are also toggled. Note that this will
@@ -1754,22 +1285,6 @@
this.readOnly = readOnly;
- if (deep) {
-
- if (syncChildren) {
- synchronizeChildren();
- }
-
- // Recursively set kids
- for (NodeImpl mykid = firstChild;
- mykid != null;
- mykid = mykid.nextSibling) {
- if(!(mykid instanceof EntityReference)) {
- mykid.setReadOnly(readOnly,true);
- }
- }
- }
-
} // setReadOnly(boolean,boolean)
/**
@@ -1811,12 +1326,6 @@
* Override this method in subclass to hook in efficient
* internal data structure.
*/
- protected void synchronizeChildren() {}
-
- /**
- * Override this method in subclass to hook in efficient
- * internal data structure.
- */
protected void synchronizeData() {}
/** Denotes that this node has changed. */
@@ -1843,14 +1352,10 @@
/** Serialize object. */
private void writeObject(ObjectOutputStream out) throws IOException {
- // synchronize data and chilren
+ // synchronize data
if (syncData) {
synchronizeData();
}
- if (syncChildren) {
- synchronizeChildren();
- }
-
// write object
out.defaultWriteObject();
1.1 xml-xerces/java/src/org/apache/xerces/dom/NodeContainer.java
Index: NodeContainer.java
===================================================================
/* $Id: NodeContainer.java,v 1.1 2000/01/13 00:28:20 lehors Exp $ */
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.xerces.dom;
import java.io.*;
import java.util.Enumeration;
import org.w3c.dom.*;
import org.w3c.dom.events.*;
import org.apache.xerces.dom.*;
import org.apache.xerces.dom.events.*;
import org.apache.xerces.dom.traversal.*;
/**
* NodeContainer inherits from NodeImpl and adds the capability of having child
* nodes. Not every node in the DOM can have children, so only nodes that can
* should inherit from this class and pay the price for it.
* <P>
* NodeContainer, just like NodeImpl, also implements NodeList, so it can
* return itself in response to the getChildNodes() query. This eliminiates
* the need for a separate ChildNodeList object. Note that this is an
* IMPLEMENTATION DETAIL; applications should _never_ assume that
* this identity exists.
* <P>
*/
public abstract class NodeContainer
extends NodeImpl
implements NodeList {
/** Serialization version. */
static final long serialVersionUID = 2815829867152120872L;
/** First child. */
protected NodeImpl firstChild;
/** Last child. */
protected NodeImpl lastChild;
// transients
/** Last change number for index caching. */
protected transient int nodeListChanges = -1;
/** Cached node list length. */
protected transient int nodeListLength;
/** Last requested node. */
protected transient NodeImpl nodeListNode;
/** Last requested node index. */
protected transient int nodeListIndex;
// lazy-evaluation info
/** Synchronization of child nodes needed. */
protected transient boolean syncChildren;
/** Table for quick check of child insertion. */
protected static int[] kidOK;
//
// Static initialization
//
static {
kidOK = new int[13];
kidOK[DOCUMENT_NODE] =
1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
1 << COMMENT_NODE | 1 << DOCUMENT_TYPE_NODE;
kidOK[DOCUMENT_FRAGMENT_NODE] =
kidOK[ENTITY_NODE] =
kidOK[ENTITY_REFERENCE_NODE] =
kidOK[ELEMENT_NODE] =
1 << ELEMENT_NODE | 1 << PROCESSING_INSTRUCTION_NODE |
1 << COMMENT_NODE | 1 << TEXT_NODE |
1 << CDATA_SECTION_NODE | 1 << ENTITY_REFERENCE_NODE |
1 << ATTRIBUTE_NODE;
kidOK[ATTRIBUTE_NODE] =
1 << TEXT_NODE | 1 << ENTITY_REFERENCE_NODE;
kidOK[DOCUMENT_TYPE_NODE] =
kidOK[PROCESSING_INSTRUCTION_NODE] =
kidOK[COMMENT_NODE] =
kidOK[TEXT_NODE] =
kidOK[CDATA_SECTION_NODE] =
kidOK[NOTATION_NODE] =
0;
} // static
//
// Constructors
//
/**
* No public constructor; only subclasses of NodeContainer should be
* instantiated, and those normally via a Document's factory methods
*/
protected NodeContainer(DocumentImpl ownerDocument,
String name, String value) {
super(ownerDocument, name, value);
}
/** Constructor for serialization. */
public NodeContainer() {}
//
// NodeList methods
//
/**
* Adds a child node to the end of the list of children for this node.
* Convenience shorthand for insertBefore(newChild,null).
* @see #insertBefore(Node, Node)
*
* @returns newChild, in its new state (relocated, or emptied in the
* case of DocumentNode.)
*
* @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
* type that shouldn't be a child of this node.
*
* @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
* different owner document than we do.
*
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
public Node appendChild(Node newChild) throws DOMException {
return insertBefore(newChild, null);
}
/**
* Returns a duplicate of a given node. You can consider this a
* generic "copy constructor" for nodes. The newly returned object should
* be completely independent of the source object's subtree, so changes
* in one after the clone has been made will not affect the other.
* <p>
* Example: Cloning a Text node will copy both the node and the text it
* contains.
* <p>
* Example: Cloning something that has children -- Element or Attr, for
* example -- will _not_ clone those children unless a "deep clone"
* has been requested. A shallow clone of an Attr node will yield an
* empty Attr of the same name.
* <p>
* NOTE: Clones will always be read/write, even if the node being cloned
* is read-only, to permit applications using only the DOM API to obtain
* editable copies of locked portions of the tree.
*/
public Node cloneNode(boolean deep) {
NodeContainer newnode = (NodeContainer) super.cloneNode(deep);
if (syncChildren) {
synchronizeChildren();
}
// Need to break the association w/ original kids
newnode.firstChild = null;
newnode.lastChild = null;
// Then, if deep, clone the kids too.
if (deep) {
for (NodeImpl child = (NodeImpl)getFirstChild();
child != null;
child = (NodeImpl)child.getNextSibling()) {
newnode.appendChild(child.cloneNode(true));
}
}
return newnode;
} // cloneNode(boolean):Node
/**
* Test whether this node has any children. Convenience shorthand
* for (Node.getFirstChild()!=null)
*/
public boolean hasChildNodes() {
if (syncChildren) {
synchronizeChildren();
}
return firstChild != null;
}
/**
* Obtain a NodeList enumerating all children of this node. If there
* are none, an (initially) empty NodeList is returned.
* <p>
* NodeLists are "live"; as children are added/removed the NodeList
* will immediately reflect those changes. Also, the NodeList refers
* to the actual nodes, so changes to those nodes made via the DOM tree
* will be reflected in the NodeList and vice versa.
* <p>
* In this implementation, Nodes implement the NodeList interface and
* provide their own getChildNodes() support. Other DOMs may solve this
* differently.
*/
public NodeList getChildNodes() {
// JKESS: KNOWN ISSUE HERE
if (syncChildren) {
synchronizeChildren();
}
return this;
} // getChildNodes():NodeList
/** The first child of this Node, or null if none. */
public Node getFirstChild() {
if (syncChildren) {
synchronizeChildren();
}
return firstChild;
} // getFirstChild():Node
/** The first child of this Node, or null if none. */
public Node getLastChild() {
if (syncChildren) {
synchronizeChildren();
}
return lastChild;
} // getLastChild():Node
/**
* Move one or more node(s) to our list of children. Note that this
* implicitly removes them from their previous parent.
*
* @param newChild The Node to be moved to our subtree. As a
* convenience feature, inserting a DocumentNode will instead insert
* all its children.
*
* @param refChild Current child which newChild should be placed
* immediately before. If refChild is null, the insertion occurs
* after all existing Nodes, like appendChild().
*
* @returns newChild, in its new state (relocated, or emptied in the
* case of DocumentNode.)
*
* @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
* type that shouldn't be a child of this node, or if newChild is an
* ancestor of this node.
*
* @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
* different owner document than we do.
*
* @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
* this node.
*
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
public Node insertBefore(Node newChild, Node refChild)
throws DOMException {
// Tail-call; optimizer should be able to do good things with.
return internalInsertBefore(newChild,refChild,MUTATION_ALL);
} // insertBefore(Node,Node):Node
/** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
* to control which mutation events are spawned. This version of the
* insertBefore operation allows us to do so. It is not intended
* for use by application programs.
*/
Node internalInsertBefore(Node newChild, Node refChild,int mutationMask)
throws DOMException {
if (readOnly)
throw new DOMExceptionImpl(
DOMException.NO_MODIFICATION_ALLOWED_ERR,
"NO_MODIFICATION_ALLOWED_ERR");
boolean errorChecking = ownerDocument.errorChecking;
if(errorChecking && !(newChild instanceof NodeImpl)
||
!(
newChild.getOwnerDocument() == ownerDocument
||
// SPECIAL-CASE: Document has no owner, but may be the owner.
( getNodeType() == Node.DOCUMENT_NODE &&
newChild.getOwnerDocument() == (Document)this )
) ) {
throw new DOMExceptionImpl(DOMException.WRONG_DOCUMENT_ERR,
"WRONG_DOCUMENT_ERR");
}
if (syncChildren) {
synchronizeChildren();
}
// Convert to internal type, to avoid repeated casting
NodeImpl newInternal = (NodeImpl)newChild;
if (errorChecking) {
// Prevent cycles in the tree
boolean treeSafe = true;
for (NodeImpl a = parentNode; treeSafe && a != null; a = a.parentNode) {
treeSafe = newInternal != a;
}
if(!treeSafe) {
throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
"HIERARCHY_REQUEST_ERR");
}
// refChild must in fact be a child of this node (or null)
if(refChild != null && refChild.getParentNode() != this) {
throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
"NOT_FOUND_ERR");
}
}
if (newInternal.getNodeType() == Node.DOCUMENT_FRAGMENT_NODE) {
// SLOW BUT SAFE: We could insert the whole subtree without
// juggling so many next/previous pointers. (Wipe out the
// parent's child-list, patch the parent pointers, set the
// ends of the list.) But we know some subclasses have special-
// case behavior they add to insertBefore(), so we don't risk it.
// This approch also takes fewer bytecodes.
// NOTE: If one of the children is not a legal child of this
// node, throw HIERARCHY_REQUEST_ERR before _any_ of the children
// have been transferred. (Alternative behaviors would be to
// reparent up to the first failure point or reparent all those
// which are acceptable to the target node, neither of which is
// as robust. PR-DOM-0818 isn't entirely clear on which it
// recommends?????
// No need to check kids for right-document; if they weren't,
// they wouldn't be kids of that DocFrag.
for (Node kid = newInternal.getFirstChild(); // Prescan
kid != null;
kid = kid.getNextSibling()) {
if (errorChecking && !ownerDocument.isKidOK(this, kid)) {
throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
"HIERARCHY_REQUEST_ERR");
}
}
while (newInternal.hasChildNodes()) {
insertBefore(newInternal.getFirstChild(), refChild);
}
}
else if (errorChecking && !ownerDocument.isKidOK(this, newInternal)) {
throw new DOMExceptionImpl(DOMException.HIERARCHY_REQUEST_ERR,
"HIERARCHY_REQUEST_ERR");
}
else {
EnclosingAttr enclosingAttr=null;
if(MUTATIONEVENTS && (mutationMask&MUTATION_AGGREGATE)!=0)
{
// MUTATION PREPROCESSING
// No direct pre-events, but if we're within the scope
// of an Attr and DOMAttrModified was requested,
// we need to preserve its previous value.
LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
enclosingAttr=getEnclosingAttr();
}
}
Node oldparent = newInternal.getParentNode();
if (oldparent != null) {
oldparent.removeChild(newInternal);
}
NodeImpl prev;
// Find the node we're inserting after, if any (null if
// inserting to head of list)
prev = (refChild == null)
? lastChild : ((NodeImpl)refChild).previousSibling;
// Attach up
newInternal.parentNode = this;
// Attach after
newInternal.previousSibling = prev;
if (prev == null) {
firstChild = newInternal;
}
else {
prev.nextSibling = newInternal;
}
// Attach before
newInternal.nextSibling = (NodeImpl)refChild;
if (refChild == null) {
lastChild=newInternal;
}
else {
((NodeImpl)refChild).previousSibling = newInternal;
}
changed();
if(MUTATIONEVENTS)
{
// MUTATION POST-EVENTS:
// "Local" events (non-aggregated)
if( (mutationMask&MUTATION_LOCAL) != 0)
{
// New child is told it was inserted, and where
LCount lc=LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
MutationEvent me=
new MutationEventImpl();
//?????ownerDocument.createEvent("MutationEvents");
me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED,true,false,
this,null,null,null);
newInternal.dispatchEvent(me);
}
// If within the Document, tell the subtree it's been added
// to the Doc.
lc=LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
NodeImpl eventAncestor=this;
if(enclosingAttr!=null)
eventAncestor=(NodeImpl)(enclosingAttr.node.getOwnerElement());
if(eventAncestor!=null) // Might have been orphan Attr
{
NodeImpl p=eventAncestor;
while(p!=null)
{
eventAncestor=p; // Last non-null ancestor
// In this context, ancestry includes
// walking back from Attr to Element
if(p.getNodeType()==ATTRIBUTE_NODE)
p=(ElementImpl)( ((AttrImpl)p).getOwnerElement() );
else
p=p.parentNode;
}
if(eventAncestor.getNodeType()==Node.DOCUMENT_NODE)
{
MutationEvent me=
new MutationEventImpl();
//?????ownerDocument.createEvent("MutationEvents");
me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT,
false,false,
null,null,null,null);
dispatchEventToSubtree(newInternal,me);
}
}
}
}
// Subroutine: Transmit DOMAttrModified and DOMSubtreeModified
// (Common to most kinds of mutation)
if( (mutationMask&MUTATION_AGGREGATE) != 0)
dispatchAggregateEvents(enclosingAttr);
}
}
return newInternal;
} // internalInsertBefore(Node,Node,int):Node
/**
* Remove a child from this Node. The removed child's subtree
* remains intact so it may be re-inserted elsewhere.
*
* @return oldChild, in its new state (removed).
*
* @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
* this node.
*
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
public Node removeChild(Node oldChild)
throws DOMException {
// Tail-call, should be optimizable
return internalRemoveChild(oldChild,MUTATION_ALL);
} // removeChild(Node) :Node
/** NON-DOM INTERNAL: Within DOM actions,we sometimes need to be able
* to control which mutation events are spawned. This version of the
* removeChild operation allows us to do so. It is not intended
* for use by application programs.
*/
Node internalRemoveChild(Node oldChild,int mutationMask)
throws DOMException {
if (readOnly) {
throw new DOMExceptionImpl(
DOMException.NO_MODIFICATION_ALLOWED_ERR,
"NO_MODIFICATION_ALLOWED_ERR");
}
if (ownerDocument.errorChecking &&
oldChild != null && oldChild.getParentNode() != this) {
throw new DOMExceptionImpl(DOMException.NOT_FOUND_ERR,
"NOT_FOUND_ERR");
}
// call out to any NodeIterators to remove the Node and fix-up the iterator.
Enumeration iterators = ownerDocument.getNodeIterators();
if (iterators != null) {
while ( iterators.hasMoreElements()) {
((NodeIteratorImpl)iterators.nextElement()).removeNode(oldChild);
}
}
NodeImpl oldInternal = (NodeImpl) oldChild;
EnclosingAttr enclosingAttr=null;
if(MUTATIONEVENTS)
{
// MUTATION PREPROCESSING AND PRE-EVENTS:
// If we're within the scope of an Attr and DOMAttrModified
// was requested, we need to preserve its previous value for
// that event.
LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
enclosingAttr=getEnclosingAttr();
}
if( (mutationMask&MUTATION_LOCAL) != 0)
{
// Child is told that it is about to be removed
lc=LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
MutationEvent me=
new MutationEventImpl();
//?????ownerDocument.createEvent("MutationEvents");
me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED,true,false,
this,null,null,null);
oldInternal.dispatchEvent(me);
}
// If within Document, child's subtree is informed that it's
// losing that status
lc=LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
NodeImpl eventAncestor=this;
if(enclosingAttr!=null)
eventAncestor=(NodeImpl)(enclosingAttr.node.getOwnerElement());
if(eventAncestor!=null) // Might have been orphan Attr
{
for(NodeImpl p=eventAncestor.parentNode;
p!=null;
p=p.parentNode)
{
eventAncestor=p; // Last non-null ancestor
}
if(eventAncestor.getNodeType()==Node.DOCUMENT_NODE)
{
MutationEvent me=
new MutationEventImpl();
//?????ownerDocument.createEvent("MutationEvents");
me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT,
false,false,
null,null,null,null);
dispatchEventToSubtree(oldInternal,me);
}
}
}
}
} // End mutation preprocessing
// Patch tree past oldChild
NodeImpl prev = oldInternal.previousSibling;
NodeImpl next = oldInternal.nextSibling;
if (prev != null) {
prev.nextSibling = next;
}
else {
firstChild = next;
}
if (next != null) {
next.previousSibling = prev;
}
else {
lastChild = prev;
}
// Remove oldInternal's references to tree
oldInternal.parentNode = null;
oldInternal.nextSibling = null;
oldInternal.previousSibling = null;
changed();
if(MUTATIONEVENTS)
{
// MUTATION POST-EVENTS:
// Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
// if required. (Common to most kinds of mutation)
if( (mutationMask&MUTATION_AGGREGATE) != 0)
dispatchAggregateEvents(enclosingAttr);
} // End mutation postprocessing
return oldInternal;
} // internalRemoveChild(Node,int):Node
/**
* Make newChild occupy the location that oldChild used to
* have. Note that newChild will first be removed from its previous
* parent, if any. Equivalent to inserting newChild before oldChild,
* then removing oldChild.
*
* @returns oldChild, in its new state (removed).
*
* @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
* type that shouldn't be a child of this node, or if newChild is
* one of our ancestors.
*
* @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
* different owner document than we do.
*
* @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
* this node.
*
* @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
* read-only.
*/
public Node replaceChild(Node newChild, Node oldChild)
throws DOMException {
// If Mutation Events are being generated, this operation might
// throw aggregate events twice when modifying an Attr -- once
// on insertion and once on removal. DOM Level 2 does not specify
// this as either desirable or undesirable, but hints that
// aggregations should be issued only once per user request.
EnclosingAttr enclosingAttr=null;
if(MUTATIONEVENTS)
{
// MUTATION PREPROCESSING AND PRE-EVENTS:
// If we're within the scope of an Attr and DOMAttrModified
// was requested, we need to preserve its previous value for
// that event.
LCount lc=LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
if(lc.captures+lc.bubbles+lc.defaults>0)
{
enclosingAttr=getEnclosingAttr();
}
} // End mutation preprocessing
internalInsertBefore(newChild, oldChild,MUTATION_LOCAL);
internalRemoveChild(oldChild,MUTATION_LOCAL);
if(MUTATIONEVENTS)
{
dispatchAggregateEvents(enclosingAttr);
}
return oldChild;
}
//
// NodeList methods
//
/**
* NodeList method: Count the immediate children of this node
* @return int
*/
public int getLength() {
if (nodeListChanges != changes) {
nodeListChanges = changes;
nodeListLength = 0;
nodeListIndex = 0;
nodeListNode = firstChild;
for (NodeImpl node = firstChild; node != null; node = node.nextSibling) {
nodeListLength++;
}
}
return nodeListLength;
} // getLength():int
/**
* NodeList method: Return the Nth immediate child of this node, or
* null if the index is out of bounds.
* @return org.w3c.dom.Node
* @param Index int
*/
public Node item(int index) {
// short way
if (nodeListChanges == changes) {
if (nodeListIndex < index) {
while (nodeListIndex < index && nodeListNode != null) {
nodeListIndex++;
nodeListNode = nodeListNode.nextSibling;
}
}
else if (nodeListIndex > index) {
while (nodeListIndex > index && nodeListNode != null) {
nodeListIndex--;
nodeListNode = nodeListNode.previousSibling;
}
}
return nodeListNode;
}
// long way
nodeListChanges = changes;
nodeListNode = firstChild;
for (nodeListIndex = 0;
nodeListIndex < index && nodeListNode != null;
nodeListIndex++) {
nodeListNode = nodeListNode.nextSibling;
}
return nodeListNode;
} // item(int):Node
//
// DOM2: methods, getters, setters
//
/**
* Override default behavior to call normalize() on this Node's
* children. It is up to implementors or Node to override normalize()
* to take action.
*/
public void normalize() {
Node kid;
for (kid = getFirstChild(); kid != null; kid = kid.getNextSibling()) {
kid.normalize();
}
}
//
// Public methods
//
/**
* Override default behavior so that if deep is true, children are also
* toggled.
* @see Node
* <P>
* Note: this will not change the state of an EntityReference or its
* children, which are always read-only.
*/
public void setReadOnly(boolean readOnly, boolean deep) {
super.setReadOnly(readOnly, deep);
if (deep) {
if (syncChildren) {
synchronizeChildren();
}
// Recursively set kids
for (NodeImpl mykid = firstChild;
mykid != null;
mykid = mykid.nextSibling) {
if(!(mykid instanceof EntityReference)) {
mykid.setReadOnly(readOnly,true);
}
}
}
} // setReadOnly(boolean,boolean)
//
// Protected methods
//
/**
* Override this method in subclass to hook in efficient
* internal data structure.
*/
protected void synchronizeChildren() {}
//
// Serialization methods
//
/** Serialize object. */
private void writeObject(ObjectOutputStream out) throws IOException {
// synchronize chilren
if (syncChildren) {
synchronizeChildren();
}
// write object
out.defaultWriteObject();
} // writeObject(ObjectOutputStream)
/** Deserialize object. */
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
// perform default deseralization
ois.defaultReadObject();
// initialize transients
nodeListChanges = -1;
} // readObject(ObjectInputStream)
} // class NodeContainer