[kaffe] CVS kaffe (robilad): Resynced with GNU Classpath: DomNode fix
Kaffe CVS
cvs-commits at kaffe.org
Sun Apr 17 17:30:46 PDT 2005
PatchSet 5686
Date: 2005/04/18 00:06:24
Author: robilad
Branch: HEAD
Tag: (none)
Log:
Resynced with GNU Classpath: DomNode fix
2005-04-17 Dalibor Topic <robilad at kaffe.org>
Resynced with GNU Classpath.
2005-03-26 Chris Burdess <dog at gnu.org>
* gnu/xml/dom/DomNode.java (notifyNode): grow listener array as
required.
Members:
ChangeLog:1.3852->1.3853
libraries/javalib/gnu/xml/dom/DomNode.java:INITIAL->1.14
Index: kaffe/ChangeLog
diff -u kaffe/ChangeLog:1.3852 kaffe/ChangeLog:1.3853
--- kaffe/ChangeLog:1.3852 Mon Apr 18 00:02:16 2005
+++ kaffe/ChangeLog Mon Apr 18 00:06:24 2005
@@ -2,6 +2,15 @@
Resynced with GNU Classpath.
+ 2005-03-26 Chris Burdess <dog at gnu.org>
+
+ * gnu/xml/dom/DomNode.java (notifyNode): grow listener array as
+ required.
+
+2005-04-17 Dalibor Topic <robilad at kaffe.org>
+
+ Resynced with GNU Classpath.
+
2005-03-26 Jeroen Frijters <jeroen at frijters.net>
* java/awt/image/PixelGrabber.java (setPixels(int,int,int,int,
===================================================================
Checking out kaffe/libraries/javalib/gnu/xml/dom/DomNode.java
RCS: /home/cvs/kaffe/kaffe/libraries/javalib/gnu/xml/dom/DomNode.java,v
VERS: 1.14
***************
--- /dev/null Sun Aug 4 19:57:58 2002
+++ kaffe/libraries/javalib/gnu/xml/dom/DomNode.java Mon Apr 18 00:30:45 2005
@@ -0,0 +1,2189 @@
+/* DomNode.java --
+ Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package gnu.xml.dom;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.UserDataHandler;
+import org.w3c.dom.events.DocumentEvent;
+import org.w3c.dom.events.Event;
+import org.w3c.dom.events.EventException;
+import org.w3c.dom.events.EventListener;
+import org.w3c.dom.events.EventTarget;
+import org.w3c.dom.events.MutationEvent;
+import org.w3c.dom.traversal.NodeFilter;
+import org.w3c.dom.traversal.NodeIterator;
+
+/**
+ * <p> "Node", "EventTarget", and "DocumentEvent" implementation.
+ * This provides most of the core DOM functionality; only more
+ * specialized features are provided by subclasses. Those subclasses may
+ * have some particular constraints they must implement, by overriding
+ * methods defined here. Such constraints are noted here in the method
+ * documentation. </p>
+ *
+ * <p> Note that you can create events with type names prefixed with "USER-",
+ * and pass them through this DOM. This lets you use the DOM event scheme
+ * for application specific purposes, although you must use a predefined event
+ * structure (such as MutationEvent) to pass data along with those events.
+ * Test for existence of this feature with the "USER-Events" DOM feature
+ * name.</p>
+ *
+ * <p> Other kinds of events you can send include the "html" events,
+ * like "load", "unload", "abort", "error", and "blur"; and the mutation
+ * events. If this DOM has been compiled with mutation event support
+ * enabled, it will send mutation events when you change parts of the
+ * tree; otherwise you may create and send such events yourself, but
+ * they won't be generated by the DOM itself. </p>
+ *
+ * <p> Note that there is a namespace-aware name comparison method,
+ * <em>nameAndTypeEquals</em>, which compares the names (and types) of
+ * two nodes in conformance with the "Namespaces in XML" specification.
+ * While mostly intended for use with elements and attributes, this should
+ * also be helpful for ProcessingInstruction nodes and some others which
+ * do not have namespace URIs.
+ *
+ * @author David Brownell
+ * @author <a href='mailto:dog at gnu.org'>Chris Burdess</a>
+ */
+public abstract class DomNode
+ implements Node, NodeList, EventTarget, DocumentEvent, Cloneable, Comparable
+{
+
+ // package private
+ //final static String xmlNamespace = "http://www.w3.org/XML/1998/namespace";
+ //final static String xmlnsURI = "http://www.w3.org/2000/xmlns/";
+
+ // tunable
+ // NKIDS_* affects arrays of children (which grow)
+ // (currently) fixed size:
+ // ANCESTORS_* is for event capture/bubbling, # ancestors
+ // NOTIFICATIONS_* is for per-node event delivery, # events
+ private static final int NKIDS_DELTA = 8;
+ private static final int ANCESTORS_INIT = 20;
+ private static final int NOTIFICATIONS_INIT = 10;
+
+ // tunable: enable mutation events or not? Enabling it costs about
+ // 10-15% in DOM construction time, last time it was measured.
+
+ // package private !!!
+ static final boolean reportMutations = true;
+
+ // locking protocol changeable only within this class
+ private static final Object lockNode = new Object();
+
+ // NON-FINAL class data
+
+ // Optimize event dispatch by not allocating memory each time
+ private static boolean dispatchDataLock;
+ private static DomNode[] ancestors = new DomNode[ANCESTORS_INIT];
+ private static ListenerRecord[] notificationSet
+ = new ListenerRecord[NOTIFICATIONS_INIT];
+
+ // Ditto for the (most common) event object itself!
+ private static boolean eventDataLock;
+ private static DomEvent.DomMutationEvent mutationEvent
+ = new DomEvent.DomMutationEvent(null);
+
+ //
+ // PER-INSTANCE DATA
+ //
+
+ DomDocument owner;
+ DomNode parent; // parent node;
+ DomNode previous; // previous sibling node
+ DomNode next; // next sibling node
+ DomNode first; // first child node
+ DomNode last; // last child node
+ int index; // index of this node in its parent's children
+ int depth; // depth of the node in the document
+ int length; // number of children
+ final short nodeType;
+
+ // Bleech ... "package private" so a builder can populate entity refs.
+ // writable during construction. DOM spec is nasty.
+ boolean readonly;
+
+ // event registrations
+ private ListenerRecord[] listeners;
+ private int nListeners;
+
+ // DOM Level 3 userData dictionary.
+ private HashMap userData;
+ private HashMap userDataHandlers;
+
+ //
+ // Some of the methods here are declared 'final' because
+ // knowledge about their implementation is built into this
+ // class -- for both integrity and performance.
+ //
+
+ /**
+ * Reduces space utilization for this node.
+ */
+ public void compact()
+ {
+ if (listeners != null && listeners.length != nListeners)
+ {
+ if (nListeners == 0)
+ {
+ listeners = null;
+ }
+ else
+ {
+ ListenerRecord[] l = new ListenerRecord[nListeners];
+ System.arraycopy(listeners, 0, l, 0, nListeners);
+ listeners = l;
+ }
+ }
+ }
+
+ /**
+ * Constructs a node and associates it with its owner. Only
+ * Document and DocumentType nodes may be created with no owner,
+ * and DocumentType nodes get an owner as soon as they are
+ * associated with a document.
+ */
+ protected DomNode(short nodeType, DomDocument owner)
+ {
+ this.nodeType = nodeType;
+
+ if (owner == null)
+ {
+ // DOM calls never go down this path
+ if (nodeType != DOCUMENT_NODE && nodeType != DOCUMENT_TYPE_NODE)
+ {
+ throw new IllegalArgumentException ("no owner!");
+ }
+ }
+ this.owner = owner;
+ }
+
+
+ /**
+ * <b>DOM L1</b>
+ * Returns null; Element subclasses must override this method.
+ */
+ public NamedNodeMap getAttributes()
+ {
+ return null;
+ }
+
+ /**
+ * <b>DOM L2></b>
+ * Returns true iff this is an element node with attributes.
+ */
+ public boolean hasAttributes()
+ {
+ return false;
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns a list, possibly empty, of the children of this node.
+ * In this implementation, to conserve memory, nodes are the same
+ * as their list of children. This can have ramifications for
+ * subclasses, which may need to provide their own getLength method
+ * for reasons unrelated to the NodeList method of the same name.
+ */
+ public NodeList getChildNodes()
+ {
+ return this;
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns the first child of this node, or null if there are none.
+ */
+ public Node getFirstChild()
+ {
+ return first;
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns the last child of this node, or null if there are none.
+ */
+ public Node getLastChild()
+ {
+ return last;
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Returns true if this node has children.
+ */
+ public boolean hasChildNodes()
+ {
+ return length != 0;
+ }
+
+
+ /**
+ * Exposes the internal "readonly" flag. In DOM, children of
+ * entities and entity references are readonly, as are the
+ * objects associated with DocumentType objets.
+ */
+ public final boolean isReadonly()
+ {
+ return readonly;
+ }
+
+ /**
+ * Sets the internal "readonly" flag so this subtree can't be changed.
+ * Subclasses need to override this method for any associated content
+ * that's not a child node, such as an element's attributes or the
+ * (few) declarations associated with a DocumentType.
+ */
+ public void makeReadonly()
+ {
+ readonly = true;
+ for (DomNode child = first; child != null; child = child.next)
+ {
+ child.makeReadonly();
+ }
+ }
+
+ /**
+ * Used to adopt a node to a new document.
+ */
+ void setOwner(DomDocument doc)
+ {
+ this.owner = doc;
+ for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ {
+ ctx.setOwner(doc);
+ }
+ }
+
+ // just checks the node for inclusion -- may be called many
+ // times (docfrag) before anything is allowed to change
+ private void checkMisc(DomNode child)
+ {
+ if (readonly && !owner.building)
+ {
+ throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ null, this, 0);
+ }
+ for (DomNode ctx = this; ctx != null; ctx = ctx.parent)
+ {
+ if (child == ctx)
+ {
+ throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ "can't make ancestor into a child",
+ this, 0);
+ }
+ }
+
+ DomDocument owner = (nodeType == DOCUMENT_NODE) ? (DomDocument) this :
+ this.owner;
+ DomDocument childOwner = child.owner;
+ short childNodeType = child.nodeType;
+
+ if (childOwner != owner)
+ {
+ // new in DOM L2, this case -- patch it up later, in reparent()
+ if (!(childNodeType == DOCUMENT_TYPE_NODE && childOwner == null))
+ {
+ throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
+ null, child, 0);
+ }
+ }
+
+ // enforce various structural constraints
+ switch (nodeType)
+ {
+ case DOCUMENT_NODE:
+ switch (childNodeType)
+ {
+ case ELEMENT_NODE:
+ case PROCESSING_INSTRUCTION_NODE:
+ case COMMENT_NODE:
+ case DOCUMENT_TYPE_NODE:
+ return;
+ }
+ break;
+
+ case ATTRIBUTE_NODE:
+ switch (childNodeType)
+ {
+ case TEXT_NODE:
+ case ENTITY_REFERENCE_NODE:
+ return;
+ }
+ break;
+
+ case DOCUMENT_FRAGMENT_NODE:
+ case ENTITY_REFERENCE_NODE:
+ case ELEMENT_NODE:
+ case ENTITY_NODE:
+ switch (childNodeType)
+ {
+ case ELEMENT_NODE:
+ case TEXT_NODE:
+ case COMMENT_NODE:
+ case PROCESSING_INSTRUCTION_NODE:
+ case CDATA_SECTION_NODE:
+ case ENTITY_REFERENCE_NODE:
+ return;
+ }
+ break;
+ }
+ if (owner.checkingWellformedness)
+ {
+ throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ "can't append " +
+ nodeTypeToString(childNodeType) +
+ " to node of type " +
+ nodeTypeToString(nodeType),
+ this, 0);
+ }
+ }
+
+ // Here's hoping a good optimizer will detect the case when the
+ // next several methods are never called, and won't allocate
+ // object code space of any kind. (Case: not reporting any
+ // mutation events. We can also remove some static variables
+ // listed above.)
+
+ private void insertionEvent(DomEvent.DomMutationEvent event,
+ DomNode target)
+ {
+ if (owner == null || owner.building)
+ {
+ return;
+ }
+ boolean doFree = false;
+
+ if (event == null)
+ {
+ event = getMutationEvent();
+ }
+ if (event != null)
+ {
+ doFree = true;
+ }
+ else
+ {
+ event = new DomEvent.DomMutationEvent(null);
+ }
+ event.initMutationEvent("DOMNodeInserted",
+ true /* bubbles */, false /* nocancel */,
+ this /* related */, null, null, null, (short) 0);
+ target.dispatchEvent(event);
+
+ // XXX should really visit every descendant of 'target'
+ // and sent a DOMNodeInsertedIntoDocument event to it...
+ // bleech, there's no way to keep that acceptably fast.
+
+ if (doFree)
+ {
+ event.target = null;
+ event.relatedNode = null;
+ event.currentNode = null;
+ eventDataLock = false;
+ } // else we created work for the GC
+ }
+
+ private void removalEvent(DomEvent.DomMutationEvent event,
+ DomNode target)
+ {
+ if (owner == null || owner.building)
+ {
+ return;
+ }
+ boolean doFree = false;
+
+ if (event == null)
+ {
+ event = getMutationEvent();
+ }
+ if (event != null)
+ {
+ doFree = true;
+ }
+ else
+ {
+ event = new DomEvent.DomMutationEvent(null);
+ }
+ event.initMutationEvent("DOMNodeRemoved",
+ true /* bubbles */, false /* nocancel */,
+ this /* related */, null, null, null, (short) 0);
+ target.dispatchEvent(event);
+
+ // XXX should really visit every descendant of 'target'
+ // and sent a DOMNodeRemovedFromDocument event to it...
+ // bleech, there's no way to keep that acceptably fast.
+
+ event.target = null;
+ event.relatedNode = null;
+ event.currentNode = null;
+ if (doFree)
+ {
+ eventDataLock = false;
+ }
+ // else we created more work for the GC
+ }
+
+ //
+ // Avoid creating lots of memory management work, by using a simple
+ // allocation strategy for the mutation event objects that get used
+ // at least once per tree modification. We can't use stack allocation,
+ // so we do the next simplest thing -- more or less, static allocation.
+ // Concurrent notifications should be rare, anyway.
+ //
+ // Returns the preallocated object, which needs to be carefully freed,
+ // or null to indicate the caller needs to allocate their own.
+ //
+ static private DomEvent.DomMutationEvent getMutationEvent()
+ {
+ synchronized (lockNode)
+ {
+ if (eventDataLock)
+ {
+ return null;
+ }
+ eventDataLock = true;
+ return mutationEvent;
+ }
+ }
+
+ // NOTE: this is manually inlined in the insertion
+ // and removal event methods above; change in sync.
+ static private void freeMutationEvent()
+ {
+ // clear fields to enable GC
+ mutationEvent.clear();
+ eventDataLock = false;
+ }
+
+ void setDepth(int depth)
+ {
+ this.depth = depth;
+ for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ {
+ ctx.setDepth(depth + 1);
+ }
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Appends the specified node to this node's list of children.
+ * Document subclasses must override this to enforce the restrictions
+ * that there be only one element and document type child.
+ *
+ * <p> Causes a DOMNodeInserted mutation event to be reported.
+ * Will first cause a DOMNodeRemoved event to be reported if the
+ * parameter already has a parent. If the new child is a document
+ * fragment node, both events will be reported for each child of
+ * the fragment; the order in which children are removed and
+ * inserted is implementation-specific.
+ *
+ * <p> If this DOM has been compiled without mutation event support,
+ * these events will not be reported.
+ */
+ public Node appendChild(Node newChild)
+ {
+ try
+ {
+ DomNode child = (DomNode) newChild;
+
+ if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
+ {
+ // Append all nodes in the fragment to this node
+ for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
+ {
+ checkMisc(ctx);
+ }
+ for (DomNode ctx = child.first; ctx != null; )
+ {
+ DomNode ctxNext = ctx.next;
+ appendChild(ctx);
+ ctx = ctxNext;
+ }
+ }
+ else
+ {
+ checkMisc(child);
+ if (child.parent != null)
+ {
+ child.parent.removeChild(child);
+ }
+ child.parent = this;
+ child.index = length++;
+ child.setDepth(depth + 1);
+ child.next = null;
+ if (last == null)
+ {
+ first = child;
+ child.previous = null;
+ }
+ else
+ {
+ last.next = child;
+ child.previous = last;
+ }
+ last = child;
+
+ if (reportMutations)
+ {
+ insertionEvent(null, child);
+ }
+ }
+
+ return child;
+ }
+ catch (ClassCastException e)
+ {
+ throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
+ null, newChild, 0);
+ }
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Inserts the specified node in this node's list of children.
+ * Document subclasses must override this to enforce the restrictions
+ * that there be only one element and document type child.
+ *
+ * <p> Causes a DOMNodeInserted mutation event to be reported. Will
+ * first cause a DOMNodeRemoved event to be reported if the newChild
+ * parameter already has a parent. If the new child is a document
+ * fragment node, both events will be reported for each child of
+ * the fragment; the order in which children are removed and inserted
+ * is implementation-specific.
+ *
+ * <p> If this DOM has been compiled without mutation event support,
+ * these events will not be reported.
+ */
+ public Node insertBefore(Node newChild, Node refChild)
+ {
+ if (refChild == null)
+ {
+ return appendChild(newChild);
+ }
+
+ try
+ {
+ DomNode child = (DomNode) newChild;
+ DomNode ref = (DomNode) refChild;
+
+ if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
+ {
+ // Append all nodes in the fragment to this node
+ for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
+ {
+ checkMisc(ctx);
+ }
+ for (DomNode ctx = child.first; ctx != null; )
+ {
+ DomNode ctxNext = ctx.next;
+ insertBefore(ctx, ref);
+ ctx = ctxNext;
+ }
+ }
+ else
+ {
+ checkMisc(child);
+ if (ref == null || ref.parent != this)
+ {
+ throw new DomDOMException(DOMException.NOT_FOUND_ERR,
+ null, ref, 0);
+ }
+ if (ref == child)
+ {
+ throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
+ "can't insert node before itself",
+ ref, 0);
+ }
+
+ if (child.parent != null)
+ {
+ child.parent.removeChild(child);
+ }
+ child.parent = this;
+ int i = ref.index;
+ child.setDepth(depth + 1);
+ child.next = ref;
+ if (ref.previous != null)
+ {
+ ref.previous.next = child;
+ }
+ child.previous = ref.previous;
+ ref.previous = child;
+ if (first == ref)
+ {
+ first = child;
+ }
+ // index renumbering
+ for (DomNode ctx = child; ctx != null; ctx = ctx.next)
+ {
+ ctx.index = i++;
+ }
+
+ if (reportMutations)
+ {
+ insertionEvent(null, child);
+ }
+ }
+
+ return child;
+ }
+ catch (ClassCastException e)
+ {
+ throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
+ null, newChild, 0);
+ }
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Replaces the specified node in this node's list of children.
+ * Document subclasses must override this to test the restrictions
+ * that there be only one element and document type child.
+ *
+ * <p> Causes DOMNodeRemoved and DOMNodeInserted mutation event to be
+ * reported. Will cause another DOMNodeRemoved event to be reported if
+ * the newChild parameter already has a parent. These events may be
+ * delivered in any order, except that the event reporting removal
+ * from such an existing parent will always be delivered before the
+ * event reporting its re-insertion as a child of some other node.
+ * The order in which children are removed and inserted is implementation
+ * specific.
+ *
+ * <p> If your application needs to depend on the in which those removal
+ * and insertion events are delivered, don't use this API. Instead,
+ * invoke the removeChild and insertBefore methods directly, to guarantee
+ * a specific delivery order. Similarly, don't use document fragments,
+ * Otherwise your application code may not work on a DOM which implements
+ * this method differently.
+ *
+ * <p> If this DOM has been compiled without mutation event support,
+ * these events will not be reported.
+ */
+ public Node replaceChild(Node newChild, Node refChild)
+ {
+ try
+ {
+ DomNode child = (DomNode) newChild;
+ DomNode ref = (DomNode) refChild;
+
+ DomEvent.DomMutationEvent event = getMutationEvent();
+ boolean doFree = (event != null);
+
+ if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
+ {
+ // Append all nodes in the fragment to this node
+ for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
+ {
+ checkMisc(ctx);
+ }
+ if (ref == null || ref.parent != this)
+ {
+ throw new DomDOMException(DOMException.NOT_FOUND_ERR,
+ null, ref, 0);
+ }
+
+ if (reportMutations)
+ {
+ removalEvent(event, ref);
+ }
+ length--;
+ length += child.length;
+
+ if (child.length == 0)
+ {
+ // Removal
+ if (ref.previous != null)
+ {
+ ref.previous.next = ref.next;
+ }
+ if (ref.next != null)
+ {
+ ref.next.previous = ref.previous;
+ }
+ if (first == ref)
+ {
+ first = ref.next;
+ }
+ if (last == ref)
+ {
+ last = ref.previous;
+ }
+ }
+ else
+ {
+ int i = ref.index;
+ for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
+ {
+ // Insertion
+ ctx.parent = this;
+ ctx.index = i++;
+ ctx.setDepth(ref.depth);
+ if (ctx == child.first)
+ {
+ ctx.previous = ref.previous;
+ }
+ if (ctx == child.last)
+ {
+ ctx.next = ref.next;
+ }
+ }
+ if (first == ref)
+ {
+ first = child.first;
+ }
+ if (last == ref)
+ {
+ last = child.last;
+ }
+ }
+ }
+ else
+ {
+ checkMisc(child);
+ if (ref == null || ref.parent != this)
+ {
+ throw new DomDOMException(DOMException.NOT_FOUND_ERR,
+ null, ref, 0);
+ }
+
+ if (reportMutations)
+ {
+ removalEvent(event, ref);
+ }
+
+ if (child.parent != null)
+ {
+ child.parent.removeChild(child);
+ }
+ child.parent = this;
+ child.index = ref.index;
+ child.setDepth(ref.depth);
+ if (ref.previous != null)
+ {
+ ref.previous.next = child;
+ }
+ child.previous = ref.previous;
+ if (ref.next != null)
+ {
+ ref.next.previous = child;
+ }
+ child.next = ref.next;
+ if (first == ref)
+ {
+ first = child;
+ }
+ if (last == ref)
+ {
+ last = child;
+ }
+
+ if (reportMutations)
+ {
+ insertionEvent(event, child);
+ }
+ if (doFree)
+ {
+ freeMutationEvent();
+ }
+ }
+ ref.parent = null;
+ ref.index = 0;
+ ref.setDepth(0);
+ ref.previous = null;
+ ref.next = null;
+
+ return ref;
+ }
+ catch (ClassCastException e)
+ {
+ throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
+ null, newChild, 0);
+ }
+ }
+
+ /**
+ * <b>DOM L1</b>
+ * Removes the specified child from this node's list of children,
+ * or else reports an exception.
+ *
+ * <p> Causes a DOMNodeRemoved mutation event to be reported.
+ *
+ * <p> If this DOM has been compiled without mutation event support,
+ * these events will not be reported.
+ */
+ public Node removeChild(Node refChild)
+ {
+ try
+ {
+ DomNode ref = (DomNode) refChild;
+
+ if (ref == null || ref.parent != this)
+ {
+ throw new DomDOMException(DOMException.NOT_FOUND_ERR,
+ null, ref, 0);
+ }
+ if (readonly && !owner.building)
+ {
+ throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
+ null, this, 0);
+ }
+
+ for (DomNode child = first; child != null; child = child.next)
+ {
+ if (child == ref)
+ {
+ if (reportMutations)
+ {
+ removalEvent(null, child);
+ }
+
+ length--;
+ if (ref.previous != null)
+ {
+ ref.previous.next = ref.next;
+ }
+ if (ref.next != null)
+ {
+ ref.next.previous = ref.previous;
+ }
+ if (first == ref)
+ {
+ first = ref.next;
+ }
+ if (last == ref)
+ {
+ last = ref.previous;
+ }
+ // renumber indices
+ int i = 0;
+ for (DomNode ctx = first; ctx != null; ctx = ctx.next)
+ {
+ ctx.index = i++;
+ }
+ ref.parent = null;
+ ref.setDepth(0);
+ ref.index = 0;
+ ref.previous = null;
+ ref.next = null;
+
+ return ref;
+ }
+ }
+ throw new DomDOMException(DOMException.NOT_FOUND_ERR,
+ "that's no child of mine", refChild, 0);
+ }
+ catch (ClassCastException e)
+ {
+ throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
+ null, refChild, 0);
+ }
+ }
+
+ /**
+ * <b>DOM L1 (NodeList)</b>
+ * Returns the item with the specified index in this NodeList,
+ * else null.
+ */
+ public Node item(int index)
+ {
+ DomNode child = first;
+ int count = 0;
+ while (child != null && count < index)
+ {
+ child = child.next;
+ count++;
+ }
+ return child;
+ }
+
+ /**
+ * <b>DOM L1 (NodeList)</b>
+ * Returns the number of elements in this NodeList.
+ * (Note that many interfaces have a "Length" property, not just
+ * NodeList, and if a node subtype must implement one of those,
+ * it will also need to override getChildNodes.)
+ */
*** Patch too long, truncated ***
More information about the kaffe
mailing list