/* * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. */ /* * 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 com.sun.org.apache.xerces.internal.dom; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Vector; import org.w3c.dom.DOMException; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; /** * NamedNodeMaps represent collections of Nodes that can be accessed * by name. Entity and Notation nodes are stored in NamedNodeMaps * attached to the DocumentType. Attributes are placed in a NamedNodeMap * attached to the elem they're related too. However, because attributes * require more work, such as firing mutation events, they are stored in * a subclass of NamedNodeMapImpl. *
* Only one Node may be stored per name; attempting to * store another will replace the previous value. *
* NOTE: The "primary" storage key is taken from the NodeName attribute of the * node. The "secondary" storage key is the namespaceURI and localName, when * accessed by DOM level 2 nodes. All nodes, even DOM Level 2 nodes are stored * in a single Vector sorted by the primary "nodename" key. *
* NOTE: item()'s integer index does _not_ imply that the named nodes * must be stored in an array; that's only an access method. Note too * that these indices are "live"; if someone changes the map's * contents, the indices associated with nodes may change. *
*
* @xerces.internal
*
* @since PR-DOM-Level-1-19980818.
* @LastModified: Oct 2017
*/
public class NamedNodeMapImpl
implements NamedNodeMap, Serializable {
//
// Constants
//
/** Serialization version. */
static final long serialVersionUID = -7039242451046758020L;
//
// Data
//
protected short flags;
protected final static short READONLY = 0x1<<0;
protected final static short CHANGED = 0x1<<1;
protected final static short HASDEFAULTS = 0x1<<2;
/** Nodes. */
protected List
* Retrieves a node specified by local name and namespace URI.
*
* @param namespaceURI The namespace URI of the node to retrieve.
* When it is null or an empty string, this
* method behaves like getNamedItem.
* @param localName The local name of the node to retrieve.
* @return Node A Node (of any type) with the specified name, or null if the specified
* name did not identify any node in the map.
*/
public Node getNamedItemNS(String namespaceURI, String localName) {
int i = findNamePoint(namespaceURI, localName);
return (i < 0) ? null : (nodes.get(i));
} // getNamedItemNS(String,String):Node
/**
* Adds a node using its nodeName attribute.
* As the nodeName attribute is used to derive the name which the node must be
* stored under, multiple nodes of certain types (those that have a "special" string
* value) cannot be stored as the names would clash. This is seen as preferable to
* allowing nodes to be aliased.
* @see org.w3c.dom.NamedNodeMap#setNamedItem
* @return If the new Node replaces an existing node the replaced Node is returned,
* otherwise null is returned.
* @param arg
* A node to store in a named node map. The node will later be
* accessible using the value of the namespaceURI and localName
* attribute of the node. If a node with those namespace URI and
* local name is already present in the map, it is replaced by the new
* one.
* @exception org.w3c.dom.DOMException The exception description.
*/
public Node setNamedItem(Node arg)
throws DOMException {
CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
if (ownerDocument.errorChecking) {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
}
if (arg.getOwnerDocument() != ownerDocument) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
}
}
int i = findNamePoint(arg.getNodeName(),0);
NodeImpl previous = null;
if (i >= 0) {
previous = (NodeImpl) nodes.get(i);
nodes.set(i, arg);
} else {
i = -1 - i; // Insert point (may be end of list)
if (null == nodes) {
nodes = new ArrayList<>(5);
}
nodes.add(i, arg);
}
return previous;
} // setNamedItem(Node):Node
/**
* Adds a node using its namespaceURI and localName.
* @see org.w3c.dom.NamedNodeMap#setNamedItem
* @return If the new Node replaces an existing node the replaced Node is returned,
* otherwise null is returned.
* @param arg A node to store in a named node map. The node will later be
* accessible using the value of the namespaceURI and localName
* attribute of the node. If a node with those namespace URI and
* local name is already present in the map, it is replaced by the new
* one.
*/
public Node setNamedItemNS(Node arg)
throws DOMException {
CoreDocumentImpl ownerDocument = ownerNode.ownerDocument();
if (ownerDocument.errorChecking) {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
}
if(arg.getOwnerDocument() != ownerDocument) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
throw new DOMException(DOMException.WRONG_DOCUMENT_ERR, msg);
}
}
int i = findNamePoint(arg.getNamespaceURI(), arg.getLocalName());
NodeImpl previous = null;
if (i >= 0) {
previous = (NodeImpl) nodes.get(i);
nodes.set(i, arg);
} else {
// If we can't find by namespaceURI, localName, then we find by
// nodeName so we know where to insert.
i = findNamePoint(arg.getNodeName(),0);
if (i >= 0) {
previous = (NodeImpl) nodes.get(i);
nodes.add(i, arg);
} else {
i = -1 - i; // Insert point (may be end of list)
if (null == nodes) {
nodes = new ArrayList<>(5);
}
nodes.add(i, arg);
}
}
return previous;
} // setNamedItemNS(Node):Node
/**
* Removes a node specified by name.
* @param name The name of a node to remove.
* @return The node removed from the map if a node with such a name exists.
*/
/***/
public Node removeNamedItem(String name)
throws DOMException {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw
new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
msg);
}
int i = findNamePoint(name,0);
if (i < 0) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
}
NodeImpl n = (NodeImpl)nodes.get(i);
nodes.remove(i);
return n;
} // removeNamedItem(String):Node
/**
* Introduced in DOM Level 2.
* Removes a node specified by local name and namespace URI.
* @param namespaceURI
* The namespace URI of the node to remove.
* When it is null or an empty string, this
* method behaves like removeNamedItem.
* @param name The local name of the node to remove.
* @return Node The node removed from the map if a node with such
* a local name and namespace URI exists.
* @throws NOT_FOUND_ERR: Raised if there is no node named
* name in the map.
*/
public Node removeNamedItemNS(String namespaceURI, String name)
throws DOMException {
if (isReadOnly()) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
throw
new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
msg);
}
int i = findNamePoint(namespaceURI, name);
if (i < 0) {
String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
}
NodeImpl n = (NodeImpl)nodes.get(i);
nodes.remove(i);
return n;
} // removeNamedItem(String):Node
//
// Public methods
//
/**
* Cloning a NamedNodeMap is a DEEP OPERATION; it always clones
* all the nodes contained in the map.
*/
public NamedNodeMapImpl cloneMap(NodeImpl ownerNode) {
NamedNodeMapImpl newmap = new NamedNodeMapImpl(ownerNode);
newmap.cloneContent(this);
return newmap;
}
protected void cloneContent(NamedNodeMapImpl srcmap) {
List