📄 nodeimpl.java
字号:
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;
// 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 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 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
* copying. This method is called by {@link #cloneNode} and the default
* {@link java.lang.Object#clone} method.
* <P>
* Contents cloning duplicates the node's name and value, and its children.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -