📄 nodeimpl.java
字号:
nextChild = (NodeProxy)newChildX.getNextSibling(); appendChild( newChildX ); newChildX = nextChild; } return newChild; } // Node becomes child of this parent and part of this document. // Note that this code comes after the test for a DocumentFragment. // A fragment does not become part of this node, only its children. // The fragment becomes parent-less and child-less. // newChildX._parent = this; newChildX.setParentNode( this ); if (_ownerDocument != null) { newChildX.setOwnerDocument( _ownerDocument ); } // If the list has no end (it is empty) then newChild is added as the // only child in it. if (_lastChild == null) { _lastChild = newChildX; _firstChild = newChildX; newChildX.setPreviousSibling( null ); newChildX.setNextSibling( null ); } else { // newChild becomes the new end of the list, adjusting the previous // last child. _lastChild.setNextSibling( newChildX ); newChildX.setPreviousSibling( _lastChild ); newChildX.setNextSibling( null ); _lastChild = newChildX; } // Keep this count accurate at all times. ++_childsCount; } return newChild; } /** * Remove <TT>oldChild</TT> from this parent. If <TT>oldChild</TT> is not * a direct child of this parent, or childern are not supported by this node * type, an exception is thrown. * * @param oldChild The child to remove * @return The removed child * @throws org.w3c.dom.DOMException <TT>NO_MODIFICATION_ALLOWED_ERR</TT> * Node is read-only and cannot be modified * @throws org.w3c.dom.DOMException <TT>HIERARCHY_REQUEST_ERR</TT> * Children are not supported by this node type * @throws org.w3c.dom.DOMException <TT>NOT_FOUND_ERR</TT> * <TT>oldChild</TT> is not a direct child of this node * @see #castOldChild */ public synchronized final Node removeChild( Node oldChild ) throws DOMException { NodeProxy oldChildX; int i; // Make sure the node is not read-only. // Throw exception if children not supported by derived class. if (isReadOnly()) { throw new DOMExceptionImpl( DOMException.NO_MODIFICATION_ALLOWED_ERR ); } if (!supportsChildern()) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "No childern supported by this node type." ); } // Cast refChild to NodeImpl, making sure it is a child of this node. oldChildX = (NodeProxy)castOldChild( oldChild ); // We're going to mess with this child node, so make sure no other thread // is touching it synchronized (oldChild) { // Need to tell all the iterators that might be observing the // child node that the child node is removed from the current // tree. The iterators will reflect the changed by selecting // a different child to point to. Interesting iterators are // those the observer the tree underneath this node and all its // parents. notifyIterators( oldChild ); // Child becomes orphan. It is no longer first or last child of this // node. Removed from linked list. oldChildX.setParentNode( null ); if (_firstChild != null && _firstChild.equals( oldChildX )) { _firstChild = (NodeProxy)oldChildX.getNextSibling(); } if (_lastChild != null && _lastChild.equals( oldChildX )) { _lastChild = (NodeProxy)oldChildX.getPreviousSibling(); } if (oldChildX.getPreviousSibling() != null) { ((NodeProxy)oldChildX.getPreviousSibling()).setNextSibling( oldChildX.getNextSibling() ); } if (oldChildX.getNextSibling() != null) { ((NodeProxy)oldChildX.getNextSibling()).setPreviousSibling( oldChildX.getPreviousSibling() ); } oldChildX.setPreviousSibling( null ); oldChildX.setNextSibling( null ); // Keep this count accurate at all times. --_childsCount; } return oldChild; } /** * Replace <TT>oldChild</TT> with <TT>newChild</TT>, adding the new child and * removing the old one. * <P> * If <TT>newChild</TT> does not belong to this DOM, <TT>oldChild</TT> is not * a direct child of this parent, or childern are not supported by this node * type, an exception is thrown. * <P> * <TT>newChild</TT> is removed from its original parent before adding to this * parent. If <TT>newChild</TT> is a {@link org.w3c.dom.DocumentFragment}, all * its children are inserted one by one into this parent. * * @param newChild The new child to add * @param oldChild The old child to take away * @return The old child * @throws org.w3c.dom.DOMException <TT>NO_MODIFICATION_ALLOWED_ERR</TT> * Node is read-only and cannot be modified * @throws org.w3c.dom.DOMException <TT>HIERARCHY_REQUEST_ERR</TT> * Children are not supported by this node type, or <TT>newChild</TT> is not * a compatible type for this node * @throws org.w3c.dom.DOMException <TT>NOT_FOUND_ERR</TT> * <TT>oldChild</TT> is not a direct child of this node * @see #castNewChild * @see #castOldChild */ public synchronized final Node replaceChild( Node newChild, Node oldChild ) throws DOMException { // Node arguments must be casted to NodeEx in order to operate on them. NodeProxy newChildX; NodeProxy oldChildX; // Make sure the node is not read-only. // Throw exception if children not supported by derived class. if (isReadOnly()) { throw new DOMExceptionImpl( DOMException.NO_MODIFICATION_ALLOWED_ERR ); } if (!supportsChildern()) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "No childern supported by this node type." ); } // Cast newChild to NodeImpl and make sure it can be inserted to this node. // Cast oldChild to NodeImpl, making sure it is a child of this node. if (newChild != null) { newChildX = (NodeProxy)castNewChild( newChild ); } oldChildX = (NodeProxy)castOldChild( oldChild ); // We're going to mess with this child node, so make sure no other thread // is touching it synchronized (oldChild) { if (newChild != null) { // .. or this synchronized (newChild) { // Lazy implementation adds newChild before oldChild and then takes // oldChild away. Might be a touch slowed, but is way more reliable. insertBefore( newChild, oldChild ); removeChild( oldChild ); } } else { // The case of just removing the old child, when the new one // is null. removeChild( oldChild ); } } return oldChild; } /** * Insert <TT>newChild</TT> in this parent, before the existing child * <TT>refChild</TT>. If <TT>refChild</TT> is null, insert <TT>newChild</TT> * as the last child of this parent, akin to calling {@link #appendChild}. * <P> * If <TT>newChild</TT> is null, <TT>newChild</TT> does not belong to this DOM, * <TT>refChild</TT> is not a direct child of this node, or childern are not * supported by this node type, an exception is thrown. * <P> * <TT>newChild</TT> is removed from its original parent before adding to this * parent. If <TT>newChild</TT> is a {@link org.w3c.dom.DocumentFragment}, all * its children are inserted one by one into this parent. * * @param newChild The new child to add * @param refChild Insert new child before this child, or insert at the end * if this child is null * @return The newly inserted child * @throws org.w3c.dom.DOMException <TT>NO_MODIFICATION_ALLOWED_ERR</TT> * Node is read-only and cannot be modified * @throws org.w3c.dom.DOMException <TT>HIERARCHY_REQUEST_ERR</TT> * Children are not supported by this node type, or <TT>newChild</TT> is not * a compatible type for this node * @throws org.w3c.dom.DOMException <TT>NOT_FOUND_ERR</TT> * <TT>oldChild</TT> is not null and not a direct child of this node * @see #castNewChild * @see #castOldChild */ public synchronized final Node insertBefore( Node newChild, Node refChild ) throws DOMException { // Node arguments must be casted to NodeEx in order to operate on them. NodeProxy newChildX; NodeProxy refChildX; // Make sure the node is not read-only. // Throw exception if children not supported by derived class. if (isReadOnly()) { throw new DOMExceptionImpl( DOMException.NO_MODIFICATION_ALLOWED_ERR ); } if (!supportsChildern()) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "No childern supported by this node type." ); } // If refChild is null, act as if appendChild was called. if (refChild == null) { return appendChild( newChild ); } // Cast newChild to NodeImpl and make sure it can be inserted to this node. // Cast refChild to NodeImpl, making sure it is a child of this node. newChildX = (NodeProxy)castNewChild( newChild ); refChildX = (NodeProxy)castOldChild( refChild ); // We're going to mess with this child node, so make sure no other thread // is touching it synchronized (newChild) { // .. or this synchronized (refChild) { // If the newChild is already a child or some node, remove it first // before becoming child of this node. Make sure that parent is not // read-only. if (newChildX.getParentNode() != null) { if (((NodeProxy)newChildX.getParentNode()).isReadOnly()) { throw new DOMExceptionImpl( DOMException.NO_MODIFICATION_ALLOWED_ERR ); } newChildX.getParentNode().removeChild( newChildX ); } // Special case: newChild is a DocumentFragment and instead of // inserting itself, all of its childs are inserted one by one. if (newChildX instanceof DocumentFragment) { NodeProxy nextChild; newChildX = (NodeProxy)newChildX.getFirstChild(); while (newChildX != null) { nextChild = (NodeProxy)newChildX.getNextSibling(); insertBefore( newChildX, refChild ); newChildX = nextChild; } return newChild; } // Node becomes child of this parent and part of this document. // Note that this code comes after the test for a DocumentFragment. // A fragment does not become part of this node, only its children. // The fragment becomes parent-less and child-less. newChildX.setParentNode( this ); newChildX.setOwnerDocument( _ownerDocument ); // If refChild is the first child, newChild becomes the first // child on the list. if (_firstChild.equals( refChildX )) { _firstChild = newChildX; } // refChild is not the first child, so adjust the previous child // to point at newChild instead. if (refChildX.getPreviousSibling() != null) { newChildX.setPreviousSibling( refChildX.getPreviousSibling() ); ((NodeProxy)refChildX.getPreviousSibling()).setNextSibling( newChildX ); } // Adjust the refChild to point at this child and vice versa. refChildX.setPreviousSibling( newChildX ); newChildX.setNextSibling( refChildX ); // Keep this count accurate at all times. ++_childsCount; } } return newChild; } /** * Checks whether <TT>newChild</TT> can be added to this node as a child, and * if so, performs a necessary cast. <TT>newChild</TT> cannot be null and must * belong to this DOM. It is impossible to transfer nodes between different * DOM implementations. * <P> * The following rules govern the allowed <TT>newChild</TT> types: * <UL> * <LI>Parent is an {@link org.w3c.dom.Attr}, <TT>newChild</TT> must be either * a {@link org.w3c.dom.Text} or an {@link org.w3c.dom.EntityReference} * <LI>Parent is a {@link org.w3c.dom.DocumentType}, <TT>newChild</TT> must be * either an {@link org.w3c.dom.Entity} or a {@link org.w3c.dom.Notation}. * <LI>Parnet is any other node type, <TT>newChild</TT> must be an {@link * org.w3c.dom.Element}, a {@link org.w3c.dom.CharacterData} derived type, * a {@link org.w3c.dom.DocumentFragment}, an {@link * org.w3c.dom.EntityReference} or a {@link org.w3c.dom.ProcessingInstruction}. * </UL> * Any deviation will throw an exception. * * @param newChild New child node * @return <TT>newChild</TT> cast to type {@link NodeImpl} * @throws org.w3c.dom.DOMException <TT>HIERARCHY_REQUEST_ERR</TT> * <TT>newChild</TT> is null, does not belong to this DOM, or its node type * is not supported for this parent */ protected Node castNewChild( Node newChild ) throws DOMException { if (newChild == null) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "Child reference is null." ); } // newChild must be Element, CDATASection, Text, Comment (all three // derived from CharacterData), DocumentFragment, EntityReference, // or ProcessingInstruction. if (!(newChild instanceof Node)) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "Child is not a compatible type for this node." ); } if (!(newChild instanceof Element || newChild instanceof CharacterData || newChild instanceof DocumentFragment || newChild instanceof EntityReference || newChild instanceof ProcessingInstruction)) { throw new DOMExceptionImpl( DOMException.HIERARCHY_REQUEST_ERR, "Child is not a compatible type for this node." ); } return (Node)newChild; } /** * Checks whether <TT>oldChild</TT> is a direct child of this node, and if so, * performs a necessary cast. <TT>oldChild</TT> cannot be null. * * @param oldChild Old child node * @return <T>oldChild</TT> cast to type {@link NodeImpl} * @throws org.w3c.dom.DOMException <TT>NOT_FOUND_ERR</TT> * <TT>oldChild</TT> is null, or not a direct child of this node */ protected final Node castOldChild( Node oldChild ) throws DOMException { if (oldChild == null || !(oldChild instanceof NodeProxy) || !((OzoneProxy)oldChild.getParentNode()).remoteID().equals( container().id() )) { throw new DOMExceptionImpl( DOMException.NOT_FOUND_ERR, "Not a direct child of this node." ); } return (Node)oldChild; } /** * This clone method is called after a new node has been constructed to copy * the contents of this node into the new one. It clones in contents but not * in context, and guarantees that the cloned node will pass the equality * test (see {@link #equals}). * <P> * <TT>into</TT> must be a valid node of the exact same class as this one. * <TT>deep</TT> is true if deep cloning (includes all children nodes) is to * be performed. If <TT>deep</TT> is false, the clone might not pass the * equality test. * <P> * Derived classes override and call this method to add per-class variable
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -