FileDocCategorySizeDatePackage
CompositeNode.javaAPI DocphoneME MR2 API (J2ME)15299Wed May 02 18:00:36 BST 2007com.sun.perseus.model

CompositeNode

public abstract class CompositeNode extends ModelNode
CompositeNode models ModelNodesA CompositeNode can have either ModelNode children and text content children (see the {@link #appendTextChild appendTextChild} method).
version
$Id: CompositeNode.java,v 1.9 2006/06/29 10:47:30 ln156897 Exp $

Fields Summary
protected ElementNode
firstChild
The first child
protected ElementNode
lastChild
The last child
Constructors Summary
Methods Summary
public voidadd(ElementNode element)
Appends an element at the end of the list

param
element the node to add to this CompositeNode
throws
NullPointerException if the input argument is null.

        if (element == null) {
            throw new NullPointerException();
        }

        element.preValidate();

        if (firstChild == null) {
            firstChild = element;
            lastChild = element;
            element.nextSibling = null;
            element.prevSibling = null;
        } else {
            lastChild.nextSibling = element;
            element.nextSibling = null;
            element.prevSibling = lastChild;
            lastChild = element;
            
        }

        // An insertion event is triggered from the setParent call.
        element.setParent(this);
    
public org.w3c.dom.NodeappendChild(org.w3c.dom.Node newChild)

        return insertBefore(newChild, null);
    
protected voidclearLayouts()
Clears the text layouts, if any exist. This is typically called when the font selection has changed and nodes such as Text should recompute their layouts. This should recursively call clearLayouts on children node or expanded content, if any.

        clearLayouts(firstChild);
    
public ModelNodegetFirstChildNode()

return
this node's first child.

        return firstChild;
    
public ModelNodegetLastChildNode()

return
this node's last child.

        return lastChild;
    
public abstract java.lang.StringgetLocalName()

return
unprefixed node name. For an SVGElement, this returns the tag name without a prefix. In case of the Document node, string #document is returned.
throws
SecurityException if the application does not have the necessary privilege rights to access this (SVG) content.

public abstract java.lang.StringgetNamespaceURI()

return
the namespace URI of the Node.
throws
SecurityException if the application does not have the necessary privilege rights to access this (SVG) content.

public abstract org.w3c.dom.NodegetParentNode()
Returns the parent Node of this Node.

return
the parent node or null if there is no parent (i.e. if a node has just been created and not yet added to the tree, or if it has been removed from the tree, this is null).
throws
SecurityException if the application does not have the necessary privilege rights to access this (SVG) content.

public org.w3c.dom.NodeinsertBefore(org.w3c.dom.Node newChild, org.w3c.dom.Node refChild)

        if (newChild == null) {
            throw new NullPointerException();
        }

        if (newChild == ownerDocument) {
            throw new DOMException
                (DOMException.HIERARCHY_REQUEST_ERR, 
                 Messages.formatMessage
                 (Messages.ERROR_CANNOT_INSERT_DOCUMENT_NODE,
                                        null));
        }

        // The DocumentNode class can only create ElementNode instances.  If we
        // are dealing with an object which is not an ElementNode instance, we
        // know we are dealing with something in the wrong document.
        if (!(newChild instanceof ElementNode)) {
            throw new DOMException
                (DOMException.WRONG_DOCUMENT_ERR, 
                 Messages.formatMessage
                 (Messages.ERROR_CANNOT_INSERT_FROM_OTHER_DOCUMENT,
                                        null));
        }

        ElementNode newNode = (ElementNode) newChild;
        
        // Check if newNode belongs to the same document.
        if (newNode.ownerDocument != ownerDocument) {
            throw new DOMException
                (DOMException.WRONG_DOCUMENT_ERR,
                 Messages.formatMessage
                 (Messages.ERROR_CANNOT_INSERT_FROM_OTHER_DOCUMENT,
                                        null));
        }

        // Check if the newNode is of a type allowed by this Node
        // implementation.
        if (!isAllowedChild(newNode)) {
            throw new DOMException
                (DOMException.HIERARCHY_REQUEST_ERR, 
                 Messages.formatMessage
                 (Messages.ERROR_CHILD_NOT_ALLOWED,
                  new String[] {newNode.getLocalName(),
                                newNode.getNamespaceURI(),
                                getLocalName(),
                                getNamespaceURI()}));
        }

        // Check if the newNode is one of this node's ancestor, or the 
        // node itself.
        if (isAncestor(newNode)) {
            throw new DOMException
                (DOMException.HIERARCHY_REQUEST_ERR, 
                 Messages.formatMessage
                 (Messages.ERROR_INSERTING_ANCESTOR,
                  null));
        }

        // Check if this node is of type document and already has a child.
        if (this == ownerDocument) {
            if (firstChild != null) {
                throw new DOMException
                    (DOMException.HIERARCHY_REQUEST_ERR,
                     Messages.formatMessage
                     (Messages.ERROR_INSERTING_UNDER_DOCUMENT, null));
            }
        }

        // Check refChild if refChild is not null
        if (refChild != null) {
            if (!isChild(refChild)) {
                throw new DOMException
                    (DOMException.NOT_FOUND_ERR,
                     Messages.formatMessage
                     (Messages.ERROR_REF_NODE_NOT_A_CHILD, null));
            }
        }

        // Check that newChild is _not_ a child of the DocumentNode
        if (newNode.parent == ownerDocument) {
            throw new DOMException
                (DOMException.NOT_SUPPORTED_ERR, 
                 Messages.formatMessage
                 (Messages.ERROR_INSERTING_DOCUMENT_ELEMENT,
                  null));
        }

        // If the inserted node already has a parent, remove the node
        // from its current parent.
        if (newNode.parent != null) {
            ((CompositeNode) newNode.parent).removeChild(newNode);
        }

        if (refChild == null) {
	    // Performs the Use xlink:href attribute validation
            add(newNode);
        } else {
            // Because refChild's parent is this node, we know it has to 
            // be an ElementNode. So the following cast is safe. See 
            // isChild call above.
            ElementNode refNode = (ElementNode) refChild;
            newNode.prevSibling = refNode.prevSibling;
            newNode.nextSibling = refNode;
            if (refNode.prevSibling != null) {
                // refNode is _not_ the first node
                refNode.prevSibling.nextSibling = newNode;
            } else {
                // refNode _is_ the first node
                firstChild = newNode;
            }
            refNode.prevSibling = newNode;
            newNode.nextSibling = refNode;

            // An insertion event is triggered from the setParent call
            newNode.setParent(this);
        }

        return newChild;
    
protected booleanisAllowedChild(ElementNode node)
Implementation helper. By default, we only disallow SVG nodes under all nodes except DocumentNode.

param
node the candidate child node.
return
true if the input node can be inserted under this CompositeNode

        if (node instanceof SVG) {
            return false;
        }
        return true;
    
final booleanisAncestor(ElementNode node)
Implementation helper.

param
node the node which may be an ancestor of this CompositeNode.
return
true if the input node is this node or if it is one of its ancestors.

        if (node == this) {
            return true;
        } else if (parent != null) {
            return ((CompositeNode) parent).isAncestor(node);
        } else {
            return false;
        }
    
final booleanisChild(org.w3c.dom.Node node)
Implementation helper.

param
node the node which may be a child of this composite node.
return
true if the input node is one of this composite's children.

        ElementNode c = firstChild;
        while (c != null) {
            if (c == node) {
                return true;
            } 
            c = (ElementNode) c.nextSibling;
        }
        return false;
    
protected static booleanisIdBranch(ElementNode node)

param
node the root of the branch to check for ids. Should not be null.
return
true if the input node, or any of its descendant, has an id.

        if (node.id != null) {
            return true;
        } 

        ElementNode c = node.firstChild;
        while (c != null) {
            if (isIdBranch(c)) {
                return true;
            } else {
                c = (ElementNode) c.nextSibling;
            }
        }
        
        return false;
    
protected booleanisRemoveChildSupported()

return
true if this node supports removing children. By default, this returns true.

        return true;
    
voidnodeHookedInDocumentTree()
To be overriddent by derived classes, such as TimedElementNode, if they need to do special operations when hooked into the document tree.

    
voidnodeUnhookedFromDocumentTree()
To be overriddent by derived classes, such as TimedElementNode, if they need to do special operations when unhooked from the document tree.

    
final voidonHookedInDocumentTree()
When a CompositeNode is hooked into the document tree, by default, it notifies its children and calls its own nodeHookedInDocumentTree method.

        super.onHookedInDocumentTree();

        nodeHookedInDocumentTree();

        ModelNode c = getFirstExpandedChild();
        while (c != null) {
            c.onHookedInDocumentTree();
            c = c.nextSibling;
        }

        c = getFirstChildNode();
        while (c != null) {
            c.onHookedInDocumentTree();
            c = c.nextSibling;
        }
    
final voidonUnhookedFromDocumentTree()
When a CompositeNode is hooked into the document tree, by default, it notifies its children and calls its own nodeUnhookedFromDocumentTree method.

        super.onUnhookedFromDocumentTree();

        nodeUnhookedFromDocumentTree();

        ModelNode c = getFirstExpandedChild();
        while (c != null) {
            c.onUnhookedFromDocumentTree();
            c = c.nextSibling;
        }

        c = getFirstChildNode();
        while (c != null) {
            c.onUnhookedFromDocumentTree();
            c = c.nextSibling;
        }
    
public org.w3c.dom.NoderemoveChild(org.w3c.dom.Node oldChild)

        // First, check if this is indeed a child of this node.
        if (!isChild(oldChild)) {
            if (oldChild == null) {
                throw new NullPointerException();
            }

            throw new DOMException(
                    DOMException.NOT_FOUND_ERR, 
                    Messages.formatMessage(Messages.ERROR_NOT_A_CHILD, null));
        }

        // Now, check if this is a supported operation
        if (!isRemoveChildSupported()) {
            throw new DOMException
                (DOMException.NOT_SUPPORTED_ERR,
                 Messages.formatMessage(
                        Messages.ERROR_REMOVE_CHILD_NOT_SUPPORTED,
                        new String[] {
                            getLocalName(),
                            getNamespaceURI()
                        }));
        }

        // Check if the removed child, or one of its descendants, has
        // an identifier.
        ElementNode oldNode = (ElementNode) oldChild;
        if (isIdBranch(oldNode)) {
            throw new DOMException(
                    DOMException.INVALID_ACCESS_ERR, 
                    Messages.formatMessage(
                        Messages.ERROR_CANNOT_REMOVE_NODE_WITH_ID,
                        null));
        }

        if (oldNode.nextSibling != null) {
            oldNode.nextSibling.prevSibling = oldNode.prevSibling;
        } else {
            lastChild = (ElementNode) oldNode.prevSibling;
        }

        if (oldNode.prevSibling != null) {
            oldNode.prevSibling.nextSibling = oldNode.nextSibling;
        } else {
            firstChild = (ElementNode) oldNode.nextSibling;
        }

        oldNode.nextSibling = null;
        oldNode.prevSibling = null;
        oldNode.setParent(null);
        
        return oldChild;
    
protected voidunhookChildrenQuiet()
Utility method. Unhooks the children.

        unhookQuiet(firstChild);
        firstChild = null;
        lastChild = null;