All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.axiom.om.impl.dom.NodeImpl Maven / Gradle / Ivy

There is a newer version: 1.4.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axiom.om.impl.dom;

import static org.apache.axiom.dom.DOMExceptionUtil.newDOMException;

import org.apache.axiom.core.NodeFactory;
import org.apache.axiom.dom.DOMNode;
import org.apache.axiom.om.OMMetaFactory;
import org.apache.axiom.om.OMXMLParserWrapper;
import org.apache.axiom.om.impl.dom.factory.DOOMNodeFactory;
import org.apache.axiom.om.impl.dom.factory.OMDOMMetaFactory;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.UserDataHandler;

import java.util.Hashtable;

public abstract class NodeImpl implements DOMNode {

    /** Holds the user data objects */
    private Hashtable userData; // Will be initialized in setUserData()

    public final NodeFactory coreGetNodeFactory() {
        return DOOMNodeFactory.INSTANCE;
    }
    
    public final OMMetaFactory getMetaFactory() {
        return OMDOMMetaFactory.INSTANCE;
    }

    public void normalize() {
        //Parent node should override this 
    }

    /*
     * DOM-Level 3 methods
     */

    public String getBaseURI() {
        // TODO TODO
        throw new UnsupportedOperationException("TODO");
    }

    public short compareDocumentPosition(Node other) throws DOMException {
        // This is not yet implemented. In the meantime, we throw a DOMException
        // and not an UnsupportedOperationException, since this works better with
        // some other libraries (such as Saxon 8.9).
        throw newDOMException(DOMException.NOT_SUPPORTED_ERR);
    }

    public boolean isSameNode(Node node) {
        // TODO : check
        return this == node;
    }

    /**
     * Tests whether two nodes are equal. 
This method tests for equality of nodes, not sameness * (i.e., whether the two nodes are references to the same object) which can be tested with * Node.isSameNode(). All nodes that are the same will also be equal, though the * reverse may not be true.
Two nodes are equal if and only if the following conditions are * satisfied:
  • The two nodes are of the same type.
  • The following string * attributes are equal: nodeName, localName, * namespaceURI, prefix, nodeValue . This is: they are * both null, or they have the same length and are character for character * identical.
  • The attributes NamedNodeMaps are equal. This * is: they are both null, or they have the same length and for each node that * exists in one map there is a node that exists in the other map and is equal, although not * necessarily at the same index.
  • The childNodes NodeLists * are equal. This is: they are both null, or they have the same length and contain * equal nodes at the same index. Note that normalization can affect equality; to avoid this, * nodes should be normalized before being compared.

For two * DocumentType nodes to be equal, the following conditions must also be satisfied: *
  • The following string attributes are equal: publicId, * systemId, internalSubset.
  • The entities * NamedNodeMaps are equal.
  • The notations * NamedNodeMaps are equal.

On the other hand, the following do not * affect equality: the ownerDocument, baseURI, and * parentNode attributes, the specified attribute for * Attr nodes, the schemaTypeInfo attribute for Attr and * Element nodes, the Text.isElementContentWhitespace attribute for * Text nodes, as well as any user data or event listeners registered on the nodes. *

Note: As a general rule, anything not mentioned in the description above is not * significant in consideration of equality checking. Note that future versions of this * specification may take into account more attributes and implementations conform to this * specification are expected to be updated accordingly. * * @param node The node to compare equality with. * @return Returns true if the nodes are equal, false otherwise. * @since DOM Level 3 */ //TODO : sumedha, complete public boolean isEqualNode(Node node) { final boolean equal = true; final boolean notEqual = false; if (this.getNodeType() != node.getNodeType()) { return notEqual; } if (checkStringAttributeEquality(node)) { if (checkNamedNodeMapEquality(node)) { } else { return notEqual; } } else { return notEqual; } return equal; } private boolean checkStringAttributeEquality(Node node) { final boolean equal = true; final boolean notEqual = false; // null not-null -> true // not-null null -> true // null null -> false // not-null not-null -> false //NodeName if (node.getNodeName() == null ^ this.getNodeName() == null) { return notEqual; } else { if (node.getNodeName() == null) { //This means both are null.do nothing } else { if (!(node.getNodeName().equals(this.getNodeName()))) { return notEqual; } } } //localName if (node.getLocalName() == null ^ this.getLocalName() == null) { return notEqual; } else { if (node.getLocalName() == null) { //This means both are null.do nothing } else { if (!(node.getLocalName().equals(this.getLocalName()))) { return notEqual; } } } //namespaceURI if (node.getNamespaceURI() == null ^ this.getNamespaceURI() == null) { return notEqual; } else { if (node.getNamespaceURI() == null) { //This means both are null.do nothing } else { if (!(node.getNamespaceURI().equals(this.getNamespaceURI()))) { return notEqual; } } } //prefix if (node.getPrefix() == null ^ this.getPrefix() == null) { return notEqual; } else { if (node.getPrefix() == null) { //This means both are null.do nothing } else { if (!(node.getPrefix().equals(this.getPrefix()))) { return notEqual; } } } //nodeValue if (node.getNodeValue() == null ^ this.getNodeValue() == null) { return notEqual; } else { if (node.getNodeValue() == null) { //This means both are null.do nothing } else { if (!(node.getNodeValue().equals(this.getNodeValue()))) { return notEqual; } } } return equal; } private boolean checkNamedNodeMapEquality(Node node) { final boolean equal = true; final boolean notEqual = false; if (node.getAttributes() == null ^ this.getAttributes() == null) { return notEqual; } NamedNodeMap thisNamedNodeMap = this.getAttributes(); NamedNodeMap nodeNamedNodeMap = node.getAttributes(); // null not-null -> true // not-null null -> true // null null -> false // not-null not-null -> false if (thisNamedNodeMap == null ^ nodeNamedNodeMap == null) { return notEqual; } else { if (thisNamedNodeMap == null) { //This means both are null.do nothing } else { if (thisNamedNodeMap.getLength() != nodeNamedNodeMap.getLength()) { return notEqual; } else { //they have the same length and for each node that exists in one map //there is a node that exists in the other map and is equal, although //not necessarily at the same index. int itemCount = thisNamedNodeMap.getLength(); for (int a = 0; a < itemCount; a++) { NodeImpl thisNode = (NodeImpl) thisNamedNodeMap.item(a); NodeImpl tmpNode = (NodeImpl) nodeNamedNodeMap.getNamedItem(thisNode.getNodeName()); if (tmpNode == null) { //i.e. no corresponding node return notEqual; } else { if (!(thisNode.isEqualNode(tmpNode))) { return notEqual; } } } } } } return equal; } public Object getFeature(String feature, String version) { // TODO TODO throw new UnsupportedOperationException("TODO"); } /* * * userData storage/hashtable will be called only when the user needs to set user data. Previously, it was done as, * for every node a new Hashtable created making the excution very inefficient. According to profiles, no. of method * invocations to setUserData() method is very low, so this implementation is better. * Another option: * TODO do a profile and check the times for hashtable initialization. If it's still higher, we have to go to second option * Create a separate class(UserData) to store key and value pairs. Then put those objects to a array with a reasonable size. * then grow it accordingly. @ Kasun Gajasinghe * @param key userData key * @param value userData value * @param userDataHandler it seems all invocations sends null for this parameter. * Kept it for the moment just for being on the safe side. * @return previous Object if one is set before. */ public Object setUserData(String key, Object value, UserDataHandler userDataHandler) { if (userData == null) { userData = new Hashtable(); } return userData.put(key, value); } public Object getUserData(String key) { if (userData != null) { return userData.get(key); } return null; } /** * Get the owner document of this node. In contrast to {@link Node#getOwnerDocument()}, this * method returns a non null value when invoked on a {@link Document} instance. * * @return the owner document */ final DocumentImpl ownerDocument() { return (DocumentImpl)coreGetOwnerDocument(true); } void checkSameOwnerDocument(Node otherNode) { if (!(otherNode instanceof NodeImpl && coreHasSameOwnerDocument((NodeImpl)otherNode))) { throw newDOMException(DOMException.WRONG_DOCUMENT_ERR); } } // / // /OMNode methods // / public abstract OMXMLParserWrapper getBuilder(); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy