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

org.mozilla.javascript.xmlimpl.XmlNode Maven / Gradle / Ivy

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Rhino DOM-only E4X implementation.
 *
 * The Initial Developer of the Original Code is
 * David P. Caldwell.
 * Portions created by David P. Caldwell are Copyright (C) 
 * 2007 David P. Caldwell. All Rights Reserved.
 *
 *
 * Contributor(s):
 *   David P. Caldwell 
 *
 * Alternatively, the contents of this file may be used under the terms of
 * the GNU General Public License Version 2 or later (the "GPL"), in which
 * case the provisions of the GPL are applicable instead of those above. If
 * you wish to allow use of your version of this file only under the terms of
 * the GPL and not to allow others to use your version of this file under the
 * MPL, indicate your decision by deleting the provisions above and replacing
 * them with the notice and other provisions required by the GPL. If you do
 * not delete the provisions above, a recipient may use your version of this
 * file under either the MPL or the GPL.
 *
 * ***** END LICENSE BLOCK ***** */

package org.mozilla.javascript.xmlimpl;

import java.util.*;

import org.w3c.dom.*;

import org.mozilla.javascript.*;

//	Disambiguate with org.mozilla.javascript
import org.w3c.dom.Node;

class XmlNode {
	private static final String XML_NAMESPACES_NAMESPACE_URI = "http://www.w3.org/2000/xmlns/";
	
	private static final String USER_DATA_XMLNODE_KEY = XmlNode.class.getName();
	
	private static final boolean DOM_LEVEL_3 = true;
	
	private static XmlNode getUserData(Node node) {
		if (DOM_LEVEL_3) {
			return (XmlNode)node.getUserData(USER_DATA_XMLNODE_KEY);
		}
		return null;
	}
	
	private static void setUserData(Node node, XmlNode wrap) {
		if (DOM_LEVEL_3) {
			node.setUserData(USER_DATA_XMLNODE_KEY, wrap, wrap.events);
		}
	}
	
	private static XmlNode createImpl(Node node) {
		if (node instanceof Document) throw new IllegalArgumentException();
		XmlNode rv = null;
		if (getUserData(node) == null) {
			rv = new XmlNode();
			rv.dom = node;
			setUserData(node, rv);
		} else {
			rv = getUserData(node);
		}
		return rv;		
	}
	
	static XmlNode newElementWithText(XmlProcessor processor, XmlNode reference, XmlNode.QName qname, String value) {
		if (reference instanceof org.w3c.dom.Document) throw new IllegalArgumentException("Cannot use Document node as reference");
		Document document = null;
		if (reference != null) {
			document = reference.dom.getOwnerDocument();
		} else {
			document = processor.newDocument();
		}
		Node referenceDom = (reference != null) ? reference.dom : null;
		Element e = document.createElementNS(qname.getUri(), qname.qualify(referenceDom));
		if (value != null) {
			e.appendChild(document.createTextNode(value));
		}
		return XmlNode.createImpl(e);
	}
	
	static XmlNode createText(XmlProcessor processor, String value) {
		return createImpl( processor.newDocument().createTextNode(value) );
	}
	
	static XmlNode createElement(XmlProcessor processor, String namespaceUri, String xml) throws org.xml.sax.SAXException {
		return createImpl( processor.toXml(namespaceUri, xml) );
	}
	
	static XmlNode createEmpty(XmlProcessor processor) {
		return createText(processor, "");
	}
	
	private static XmlNode copy(XmlNode other) {
		return createImpl( other.dom.cloneNode(true) );
	}
	
	private static final long serialVersionUID = 1L;
	
	private UserDataHandler events = new UserDataHandler() {
		public void handle(short operation, String key, Object data, Node src, Node dest) {
		}
	};
	
	private Node dom;
	
	private XML xml;
	
	private XmlNode() {
	}
	
	String debug() {
		XmlProcessor raw = new XmlProcessor();
		raw.setIgnoreComments(false);
		raw.setIgnoreProcessingInstructions(false);
		raw.setIgnoreWhitespace(false);
		raw.setPrettyPrinting(false);
		return raw.ecmaToXmlString(this.dom);
	}
	
	public String toString() {
		return "XmlNode: type=" + dom.getNodeType() + " dom=" + dom.toString();
	}
	
	XML getXml() {
		return xml;
	}
	
	void setXml(XML xml) {
		this.xml = xml;
	}
	
	int getChildCount() {
		return this.dom.getChildNodes().getLength();
	}
	
	XmlNode parent() {
		Node domParent = dom.getParentNode();
		if (domParent instanceof Document) return null;
		if (domParent == null) return null;
		return createImpl(domParent);
	}
	
	int getChildIndex() {
		if (this.isAttributeType()) return -1;
		if (parent() == null) return -1;
		org.w3c.dom.NodeList siblings = this.dom.getParentNode().getChildNodes();
		for (int i=0; i 0) {
			e.setAttributeNS(XML_NAMESPACES_NAMESPACE_URI, "xmlns:" + prefix, uri);
		} else {
			e.setAttribute("xmlns", uri);
		}
	}
	
	void declareNamespace(String prefix, String uri) {
		if (!(dom instanceof Element)) throw new IllegalStateException();
		if (dom.lookupNamespaceURI(uri) != null && dom.lookupNamespaceURI(uri).equals(prefix)) {
			//	do nothing
		} else {
			Element e = (Element)dom;
			declareNamespace(e, prefix, uri);
		}
	}
	
	private Namespace getDefaultNamespace() {
		String prefix = "";
		String uri = (dom.lookupNamespaceURI(null) == null) ? "" : dom.lookupNamespaceURI(null);
		return Namespace.create(prefix, uri);
	}
	
	private String getExistingPrefixFor(Namespace namespace) {
		if (getDefaultNamespace().getUri().equals(namespace.getUri())) {
			return "";
		}
		return dom.lookupPrefix(namespace.getUri());
	}
	
	private Namespace getNodeNamespace() {
		String uri = dom.getNamespaceURI();
		String prefix = dom.getPrefix();
		if (uri == null) uri = "";
		if (prefix == null) prefix = "";
		return Namespace.create(prefix, uri);
	}
	
	Namespace getNamespace() {
		return getNodeNamespace();
	}
	
	void removeNamespace(Namespace namespace) {
		Namespace current = getNodeNamespace();
		
		//	Do not remove in-use namespace
		if (namespace.is(current)) return;
		NamedNodeMap attrs = this.dom.getAttributes();
		for (int i=0; i 0) return prefix + ":" + localName;
			return localName;
		}
		
		private Namespace namespace;
		private String localName;
		
		private QName() {
		}
		
		public String toString() {
			return "XmlNode.QName [" + localName + "," + namespace + "]";
		}
		
		private boolean equals(String one, String two) {
			if (one == null && two == null) return true;
			if (one == null || two == null) return false;
			return one.equals(two);
		}
		
		private boolean namespacesEqual(Namespace one, Namespace two) {
			if (one == null && two == null) return true;
			if (one == null || two == null) return false;
			return equals(one.getUri(), two.getUri());
		}
		
		final boolean isEqualTo(QName other) {
			if (!namespacesEqual(this.namespace, other.namespace)) return false;
			if (!equals(this.localName, other.localName)) return false;
			return true;
		}

		void lookupPrefix(org.w3c.dom.Node node) {
			if (node == null) throw new IllegalArgumentException("node must not be null");
			String prefix = node.lookupPrefix(namespace.getUri());
			if (prefix == null) {
				//	check to see if we match the default namespace
				String defaultNamespace = node.lookupNamespaceURI(null);
				if (defaultNamespace == null) defaultNamespace = "";
				String nodeNamespace = namespace.getUri();
				if (nodeNamespace.equals(defaultNamespace)) {
					prefix = "";
				}
			}
			int i = 0;
			while(prefix == null) {
				String generatedPrefix = "e4x_" + i++;
				String generatedUri = node.lookupNamespaceURI(generatedPrefix);
				if (generatedUri == null) {
					prefix = generatedPrefix;
					org.w3c.dom.Node top = node;
					while(top.getParentNode() != null && top.getParentNode() instanceof org.w3c.dom.Element) {
						top = top.getParentNode();
					}
					((org.w3c.dom.Element)top).setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + prefix, namespace.getUri());
				}
			}
			namespace.setPrefix(prefix);
		}
	
		String qualify(org.w3c.dom.Node node) {
			if (namespace.getPrefix() == null) {
				if (node != null) {
					lookupPrefix(node);
				} else {
					if (namespace.getUri().equals("")) {
						namespace.setPrefix("");
					} else {
						//	TODO	I am not sure this is right, but if we are creating a standalone node, I think we can set the
						//			default namespace on the node itself and not worry about setting a prefix for that namespace.
						namespace.setPrefix("");
					}
				}
			}
			return qualify(namespace.getPrefix(), localName);
		}

		void setAttribute(org.w3c.dom.Element element, String value) {
			if (namespace.getPrefix() == null) lookupPrefix(element);
			element.setAttributeNS(namespace.getUri(), qualify(namespace.getPrefix(), localName), value);		
		}
	
		/** @deprecated Use getNamespace() */
		String getUri() {
			return namespace.getUri();
		}
		
		/** @deprecated Use getNamespace() */
		String getPrefix() {
			return namespace.getPrefix();
		}
		
		Namespace getNamespace() {
			return namespace;
		}
		
		String getLocalName() {
			return localName;
		}
	}
			
	static class List {
		private java.util.Vector v;
		
		List() {
			v = new java.util.Vector();
		}
		
		private void _add(XmlNode n) {
			v.add(n);
		}
		
		XmlNode item(int index) {
			return (XmlNode)(v.get(index));
		}
		
		void remove(int index) {
			v.remove(index);
		}
		
		void add(List other) {
			for (int i=0; i




© 2015 - 2025 Weber Informatics LLC | Privacy Policy