/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** 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 code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Milen Nankov * * 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.xml.impl.xmlbeans; import java.util.*; import org.apache.xmlbeans.XmlCursor; import org.mozilla.javascript.*; class NamespaceHelper { private XMLLibImpl lib; private final Map prefixToURI = new HashMap(); private final Map uriToPrefix = new HashMap(); // A set of URIs that are used without explicit namespace declaration in scope. private final Set undeclared = new HashSet(); private NamespaceHelper(XMLLibImpl lib) { this.lib = lib; // Insert the default namespace prefixToURI.put("", ""); Set prefixes = new HashSet(); prefixes.add(""); uriToPrefix.put("", prefixes); } /** * Declared a new namespace * * @param prefix * @param uri * @param declarations */ private void declareNamespace(String prefix, String uri, ObjArray declarations) { Set prefixes = (Set)uriToPrefix.get(uri); if(prefixes == null) { prefixes = new HashSet(); uriToPrefix.put(uri, prefixes); } if(!prefixes.contains(prefix)) { String oldURI = (String)prefixToURI.get(prefix); // Add the new mapping prefixes.add(prefix); prefixToURI.put(prefix, uri); if(declarations != null) declarations.add(new Namespace(lib, prefix, uri)); if(oldURI != null) { // Update the existing mapping prefixes = (Set)uriToPrefix.get(oldURI); prefixes.remove(prefix); } } } /** * Updates the internal state of this NamespaceHelper to reflect the * existance of the XML token pointed to by the cursor. */ private void processName(XmlCursor cursor, ObjArray declarations) { javax.xml.namespace.QName qname = cursor.getName(); String uri = qname.getNamespaceURI(); Set prefixes = (Set)uriToPrefix.get(uri); if(prefixes == null || prefixes.size() == 0) { undeclared.add(uri); if(declarations != null) declarations.add(new Namespace(lib, uri)); } } /** * Updates the internal state of this NamespaceHelper with the * namespace information of the element pointed to by the cursor. */ private void update(XmlCursor cursor, ObjArray declarations) { // Process the Namespace declarations cursor.push(); while(cursor.toNextToken().isAnyAttr()) { if(cursor.isNamespace()) { javax.xml.namespace.QName name = cursor.getName(); String prefix = name.getLocalPart(); String uri = name.getNamespaceURI(); declareNamespace(prefix, uri, declarations); } } cursor.pop(); // Process the element processName(cursor, declarations); // Process the attributes cursor.push(); boolean hasNext = cursor.toFirstAttribute(); while(hasNext) { processName(cursor, declarations); hasNext = cursor.toNextAttribute(); } cursor.pop(); } /** * @return Object[] array of Namespace objects in scope at the cursor. */ public static Object[] inScopeNamespaces(XMLLibImpl lib, XmlCursor cursor) { ObjArray namespaces = new ObjArray(); NamespaceHelper helper = new NamespaceHelper(lib); cursor.push(); int depth = 0; while(cursor.hasPrevToken()) { if(cursor.isContainer()) { cursor.push(); depth++; } cursor.toParent(); } for(int i = 0; i < depth; i++) { cursor.pop(); helper.update(cursor, null); } Iterator i = helper.prefixToURI.entrySet().iterator(); while(i.hasNext()) { Map.Entry entry = (Map.Entry)i.next(); Namespace ns = new Namespace(lib, (String)entry.getKey(), (String)entry.getValue()); namespaces.add(ns); } i = helper.undeclared.iterator(); while(i.hasNext()) { Namespace ns = new Namespace(lib, (String)i.next()); namespaces.add(ns); } cursor.pop(); return namespaces.toArray(); } static Namespace getNamespace(XMLLibImpl lib, XmlCursor cursor, Object[] inScopeNamespaces) { String uri; String prefix; if (cursor.isProcinst()) { uri = ""; prefix = ""; } else { javax.xml.namespace.QName qname = cursor.getName(); uri = qname.getNamespaceURI(); prefix = qname.getPrefix(); } if (inScopeNamespaces == null) return new Namespace(lib, prefix, uri); Namespace result = null; for (int i = 0; i != inScopeNamespaces.length; ++i) { Namespace ns = (Namespace)inScopeNamespaces[i]; if(ns == null) continue; String nsURI = ns.uri(); if(nsURI.equals(uri)) { if(prefix.equals(ns.prefix())) { result = ns; break; } if(result == null || (result.prefix() == null && ns.prefix() != null)) result = ns; } } if(result == null) result = new Namespace(lib, prefix, uri); return result; } /** * @return List of Namespace objects that are declared in the container pointed to by the cursor. */ public static Object[] namespaceDeclarations(XMLLibImpl lib, XmlCursor cursor) { ObjArray declarations = new ObjArray(); NamespaceHelper helper = new NamespaceHelper(lib); cursor.push(); int depth = 0; while(cursor.hasPrevToken()) { if(cursor.isContainer()) { cursor.push(); depth++; } cursor.toParent(); } for(int i = 0; i < depth - 1; i++) { cursor.pop(); helper.update(cursor, null); } if(depth > 0) { cursor.pop(); helper.update(cursor, declarations); } cursor.pop(); return declarations.toArray(); } /** * @return Prefix to URI map of all namespaces in scope at the cursor. */ public static Map getAllNamespaces(XMLLibImpl lib, XmlCursor cursor) { NamespaceHelper helper = new NamespaceHelper(lib); cursor.push(); int depth = 0; while(cursor.hasPrevToken()) { if(cursor.isContainer()) { cursor.push(); depth++; } cursor.toParent(); } for(int i = 0; i < depth; i++) { cursor.pop(); helper.update(cursor, null); } cursor.pop(); return helper.prefixToURI; } public static void getNamespaces(XmlCursor cursor, Map prefixToURI) { cursor.push(); while(cursor.toNextToken().isAnyAttr()) { if(cursor.isNamespace()) { javax.xml.namespace.QName name = cursor.getName(); String prefix = name.getLocalPart(); String uri = name.getNamespaceURI(); prefixToURI.put(prefix, uri); } } cursor.pop(); } public static void removeNamespace(XmlCursor cursor, String prefix) { cursor.push(); while(cursor.toNextToken().isAnyAttr()) { if(cursor.isNamespace()) { javax.xml.namespace.QName name = cursor.getName(); if(name.getLocalPart().equals(prefix)) { cursor.removeXml(); break; } } } cursor.pop(); } }