com.google.gwt.dom.client.NodeRemote.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.dom.client.NodeRemote.java

Source

package com.google.gwt.dom.client;

import com.google.gwt.core.client.JavaScriptObject;

public abstract class NodeRemote extends JavaScriptObject implements DomNode {
    /**
     * Assert that the given {@link JavaScriptObject} is a DOM node and
     * automatically typecast it.
     */
    public static Node as(JavaScriptObject o) {
        assert is(o);
        return nodeFor(o);
    }

    /**
     * Determines whether the given {@link JavaScriptObject} is a DOM node. A
     * <code>null</code> object will cause this method to return
     * <code>false</code>. The try catch is needed for the firefox permission
     * error: "Permission denied to access property 'nodeType'"
     */
    public static native boolean is(JavaScriptObject o) /*-{
                                                        try {
                                                        return (!!o) && (!!o.nodeType);
                                                        } catch (e) {
                                                        return false;
                                                        }
                                                        }-*/;

    static <N extends Node> N nodeFor(JavaScriptObject o) {
        return LocalDom.nodeFor(o);
    }

    protected NodeRemote() {
    }

    @Override
    public final <T extends Node> T appendChild(T newChild) {
        if (LocalDom.isPending(this)) {
            return null;
        }
        NodeRemote toAppend = resolvedOrPending(newChild);
        return (T) nodeFor(appendChild0(toAppend));
    }

    @Override
    public final native void callMethod(String methodName) /*-{
                                                           this[methodName]();
                                                           }-*/;

    @Override
    public final Node cloneNode(boolean deep) {
        return nodeFor(cloneNode0(deep));
    }

    @Override
    public final Node getChild(int index) {
        return DomNodeStatic.getChild(this, index);
    }

    @Override
    public final int getChildCount() {
        return DomNodeStatic.getChildCount(this);
    }

    /**
     * A NodeList that contains all children of this node. If there are no
     * children, this is a NodeList containing no nodes.
     */
    @Override
    public final NodeList<Node> getChildNodes() {
        return new NodeList<>(getChildNodes0());
    }

    @Override
    public final Node getFirstChild() {
        return nodeFor(getFirstChild0());
    }

    /**
     * The first child of this node. If there is no such node, this returns
     * null.
     */
    public final native NodeRemote getFirstChild0() /*-{
                                                    return this.firstChild;
                                                    }-*/;

    @Override
    public final Node getLastChild() {
        return nodeFor(getLastChild0());
    }

    @Override
    public final Node getNextSibling() {
        return nodeFor(getNextSibling0());
    }

    /**
     * The name of this node, depending on its type; see the table above.
     */
    @Override
    public final native String getNodeName() /*-{
                                             return this.nodeName;
                                             }-*/;

    /**
     * A code representing the type of the underlying object, as defined above.
     */
    @Override
    public final native short getNodeType() /*-{
                                            return this.nodeType;
                                            }-*/;

    /**
     * The value of this node, depending on its type; see the table above. When
     * it is defined to be null, setting it has no effect.
     */
    @Override
    public final native String getNodeValue() /*-{
                                              return this.nodeValue;
                                              }-*/;

    @Override
    public final Document getOwnerDocument() {
        return nodeFor(getOwnerDocument0());
    }

    @Override
    public final Element getParentElement() {
        return nodeFor(getParentElementRemote());
    }

    @Override
    public final Node getParentNode() {
        return nodeFor(getParentNodeRemote());
    }

    /**
     * The parent of this node. All nodes except Document may have a parent.
     * However, 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.
     */
    public final native NodeRemote getParentNodeRemote() /*-{
                                                         return this.parentNode;
                                                         }-*/;

    @Override
    public final Node getPreviousSibling() {
        return nodeFor(getPreviousSibling0());
    }

    /**
     * Returns whether this node has any children.
     */
    @Override
    public final native boolean hasChildNodes() /*-{
                                                return this.hasChildNodes();
                                                }-*/;

    @Override
    public final boolean hasParentElement() {
        return DomNodeStatic.hasParentElement(this);
    }

    @Override
    public final native int indexInParentChildren() /*-{
                                                    var idx = 0;
                                                    var size = this.parentNode.childNodes.length;
                                                    for (; idx < size; idx++) {
                                                    var node = this.parentNode.childNodes.item(idx);
                                                    if (node == this) {
                                                    return idx;
                                                    }
                                                    }
                                                    return -1;
                                                    }-*/;

    @Override
    public final Node insertAfter(Node newChild, Node refChild) {
        throw new UnsupportedOperationException();
    }

    @Override
    public final Node insertBefore(Node newChild, Node refChild) {
        if (LocalDom.isPending(this)) {
            return null;
        }
        NodeRemote newChildDom = resolvedOrPending(newChild);
        NodeRemote refChildDom = resolvedOrPending(refChild);
        return nodeFor(insertBefore0(newChildDom, refChildDom));
    }

    @Override
    public final Node insertFirst(Node child) {
        throw new UnsupportedOperationException();
    }

    /**
     * Determine whether a node is equal to, or the child of, this node.
     * 
     * @param child
     *            the potential child element
     * @return <code>true</code> if the relationship holds
     */
    @Override
    public final boolean isOrHasChild(Node child) {
        assert (child != null) : "Child cannot be null";
        return DOMImpl.impl.isOrHasChild(nodeFor(), child);
    }

    @Override
    public final Node nodeFor() {
        return LocalDom.nodeFor(this);
    }

    @Override
    public final Node removeAllChildren() {
        return DomNodeStatic.removeAllChildren(this);
    }

    @Override
    public final Node removeChild(Node oldChild) {
        // removed node should never be used - so can optimise as follows
        if (oldChild.linkedToRemote()) {
            removeChild0(oldChild.remote());
        }
        return null;
        // NodeRemote resolvedOrPending = resolvedOrPending(oldChild);
        // if (resolvedOrPending.getParentNode() == null) {
        // return nodeFor(resolvedOrPending);
        // } else {
        // return nodeFor(removeChild0(resolvedOrPending));
        // }
    }

    @Override
    public final void removeFromParent() {
        DomNodeStatic.removeFromParent(this);
    }

    @Override
    public final Node replaceChild(Node newChild, Node oldChild) {
        NodeRemote newChildDom = resolvedOrPending(newChild);
        NodeRemote oldChildDom = resolvedOrPending(oldChild);
        return nodeFor(replaceChild0(newChildDom, oldChildDom));
    }

    /**
     * The value of this node, depending on its type; see the table above. When
     * it is defined to be null, setting it has no effect.
     */
    @Override
    public final native void setNodeValue(String nodeValue) /*-{
                                                            this.nodeValue = nodeValue;
                                                            }-*/;

    /**
     * Adds the node newChild to the end of the list of children of this node.
     * If the newChild is already in the tree, it is first removed.
     * 
     * @param newChild
     *            The node to add
     * @return The node added
     */
    private final native NodeRemote appendChild0(NodeRemote newChild) /*-{
                                                                      return this.appendChild(newChild);
                                                                      }-*/;

    /**
     * The last child of this node. If there is no such node, this returns null.
     */
    private final native NodeRemote getLastChild0() /*-{
                                                    return this.lastChild;
                                                    }-*/;

    /**
     * The node immediately following this node. If there is no such node, this
     * returns null.
     */
    private final native NodeRemote getNextSibling0() /*-{
                                                      return this.nextSibling;
                                                      }-*/;

    /**
     * The Document object associated with this node. This is also the
     * {@link Document} object used to create new nodes.
     */
    private final native DocumentRemote getOwnerDocument0() /*-{
                                                            return this.ownerDocument;
                                                            }-*/;

    /**
     * The node immediately preceding this node. If there is no such node, this
     * returns null.
     */
    private final native NodeRemote getPreviousSibling0() /*-{
                                                          return this.previousSibling;
                                                          }-*/;

    /**
     * Removes the child node indicated by oldChild from the list of children,
     * and returns it.
     * 
     * @param oldChild
     *            The node being removed
     * @return The node removed
     */
    private final native NodeRemote removeChild0(NodeRemote oldChild) /*-{
                                                                      if (oldChild.parentNode == null && oldChild.nodeType == 3) {
                                                                      //handle strange IE11 case (text node equality/substitution?)
                                                                      var children = this.childNodes;
                                                                      for (var i = 0; i < children.length; i++) {
                                                                      var node = children[i];
                                                                      if (node.nodeType == 3 && node.data == oldChild.data) {
                                                                      this.removeChild(node);
                                                                      return oldChild;
                                                                      }
                                                                      }
                                                                      //not matched, fall through (which will throw a DOMException)
                                                                      }
                                                                      return this.removeChild(oldChild);
                                                                      }-*/;

    /**
     * Replaces the child node oldChild with newChild in the list of children,
     * and returns the oldChild node.
     * 
     * @param newChild
     *            The new node to put in the child list
     * @param oldChild
     *            The node being replaced in the list
     * @return The node replaced
     */
    private final native NodeRemote replaceChild0(NodeRemote newChild, NodeRemote oldChild) /*-{
                                                                                            return this.replaceChild(newChild, oldChild);
                                                                                            }-*/;

    /**
     * Link remote to [remote or local]
     */
    private NodeRemote resolvedOrPending(Node node) {
        if (node == null) {
            return null;
        }
        if (node.linkedToRemote()) {
            return node.remote();
        } else {
            if (node.wasResolved()) {
                LocalDom.ensureRemote(node);
                return node.remote();
            } else {
                return LocalDom.ensureRemoteNodeMaybePendingResolution(node);
            }
        }
    }

    /**
     * Returns a duplicate of this node, i.e., serves as a generic copy
     * constructor for nodes. The duplicate node has no parent; (parentNode is
     * null.).
     * 
     * Cloning an Element copies all attributes and their values, including
     * those generated by the XML processor to represent defaulted attributes,
     * but this method does not copy any text it contains unless it is a deep
     * clone, since the text is contained in a child Text node. Cloning an
     * Attribute directly, as opposed to be cloned as part of an Element cloning
     * operation, returns a specified attribute (specified is true). Cloning any
     * other type of node simply returns a copy of this node.
     * 
     * @param deep
     *            If true, recursively clone the subtree under the specified
     *            node; if false, clone only the node itself (and its
     *            attributes, if it is an {@link Element})
     * @return The duplicate node
     */
    final native NodeRemote cloneNode0(boolean deep) /*-{
                                                     return this.cloneNode(deep);
                                                     }-*/;

    final native NodeListRemote<Node> getChildNodes0() /*-{
                                                       return this.childNodes;
                                                       }-*/;

    final native ElementRemote getParentElementRemote() /*-{
                                                        var parentElement = this.parentElement;
                                                        if (parentElement) {
                                                        return parentElement;
                                                        }
                                                        var parentNode = this.parentNode;
                                                        if (parentNode && parentNode.nodeType == 1) {
                                                        return parentNode;
                                                        } else {
                                                        return null;
                                                        }
                                                        }-*/;

    /**
     * Inserts the node newChild before the existing child node refChild. If
     * refChild is <code>null</code>, insert newChild at the end of the list of
     * children.
     * 
     * @param newChild
     *            The node to insert
     * @param refChild
     *            The reference node (that is, the node before which the new
     *            node must be inserted), or <code>null</code>
     * @return The node being inserted
     */
    final native NodeRemote insertBefore0(NodeRemote newChild, NodeRemote refChild) /*-{
                                                                                    return this.insertBefore(newChild, refChild);
                                                                                    }-*/;

    final boolean provideIsElement() {
        return getNodeType() == Node.ELEMENT_NODE;
    }

    final boolean provideIsText() {
        return getNodeType() == Node.TEXT_NODE;
    }
}