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

com.sun.xml.stream.buffer.stax.NamespaceContexHelper Maven / Gradle / Ivy

There is a newer version: 4.0.4
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2005-2012 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * http://glassfish.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.xml.stream.buffer.stax;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.jvnet.staxex.NamespaceContextEx;

/**
 * A helper class for managing the declaration of namespaces.
 * 

* A namespace is declared on a namespace context. * Namespace contexts are pushed on and popped off the namespace context stack. *

* A declared namespace will be in scope iff the context that it was declared on * has not been popped off the stack. *

* When instantiated the namespace stack consists of the root namespace context, * which contains, by default, the "xml" and "xmlns" declarations. * Namespaces may be declarations may be declared on the root context. * The root context cannot be popped but can be reset to contain just the * "xml" and "xmlns" declarations. *

* Implementation note: determining the prefix from a namespace URI * (or vice versa) is efficient when there are few namespace * declarations i.e. what is considered to be the case for namespace * declarations in 'average' XML documents. The look up of a namespace URI * given a prefix is performed in O(n) time. The look up of a prefix given * a namespace URI is performed in O(2n) time. *

* The implementation does not scale when there are many namespace * declarations. TODO: Use a hash map when there are many namespace * declarations. * * @author [email protected] */ final public class NamespaceContexHelper implements NamespaceContextEx { private static int DEFAULT_SIZE = 8; // The prefixes of the namespace declarations private String[] prefixes = new String[DEFAULT_SIZE]; // The URIs of the namespace declarations private String[] namespaceURIs = new String[DEFAULT_SIZE]; // Current position to store the next namespace declaration private int namespacePosition; // The namespace contexts private int[] contexts = new int[DEFAULT_SIZE]; // Current position to store the next namespace context private int contextPosition; /** * Create a new NamespaceContexHelper. * */ public NamespaceContexHelper() { // The default namespace declarations that are always in scope prefixes[0] = "xml"; namespaceURIs[0] = "http://www.w3.org/XML/1998/namespace"; prefixes[1] = "xmlns"; namespaceURIs[1] = "http://www.w3.org/2000/xmlns/"; namespacePosition = 2; } // NamespaceContext interface public String getNamespaceURI(String prefix) { if (prefix == null) throw new IllegalArgumentException(); prefix = prefix.intern(); for (int i = namespacePosition - 1; i >= 0; i--) { final String declaredPrefix = prefixes[i]; if (declaredPrefix == prefix) { return namespaceURIs[i]; } } return ""; } public String getPrefix(String namespaceURI) { if (namespaceURI == null) throw new IllegalArgumentException(); for (int i = namespacePosition - 1; i >= 0; i--) { final String declaredNamespaceURI = namespaceURIs[i]; if (declaredNamespaceURI == namespaceURI || declaredNamespaceURI.equals(namespaceURI)) { final String declaredPrefix = prefixes[i]; // Check if prefix is out of scope for (++i; i < namespacePosition; i++) if (declaredPrefix == prefixes[i]) return null; return declaredPrefix; } } return null; } public Iterator getPrefixes(String namespaceURI) { if (namespaceURI == null) throw new IllegalArgumentException(); List l = new ArrayList(); NAMESPACE_LOOP: for (int i = namespacePosition - 1; i >= 0; i--) { final String declaredNamespaceURI = namespaceURIs[i]; if (declaredNamespaceURI == namespaceURI || declaredNamespaceURI.equals(namespaceURI)) { final String declaredPrefix = prefixes[i]; // Check if prefix is out of scope for (int j = i + 1; j < namespacePosition; j++) if (declaredPrefix == prefixes[j]) continue NAMESPACE_LOOP; l.add(declaredPrefix); } } return l.iterator(); } // NamespaceContextEx interface public Iterator iterator() { if (namespacePosition == 2) return Collections.EMPTY_LIST.iterator(); final List namespaces = new ArrayList(namespacePosition); NAMESPACE_LOOP: for (int i = namespacePosition - 1; i >= 2; i--) { final String declaredPrefix = prefixes[i]; // Check if prefix is out of scope for (int j = i + 1; j < namespacePosition; j++) { if (declaredPrefix == prefixes[j]) continue NAMESPACE_LOOP; namespaces.add(new NamespaceBindingImpl(i)); } } return namespaces.iterator(); } final private class NamespaceBindingImpl implements NamespaceContextEx.Binding { int index; NamespaceBindingImpl(int index) { this.index = index; } public String getPrefix() { return prefixes[index]; } public String getNamespaceURI() { return namespaceURIs[index]; } } /** * Declare a default namespace. *

* @param namespaceURI the namespace URI to declare, may be null. */ public void declareDefaultNamespace(String namespaceURI) { declareNamespace("", namespaceURI); } /** * Declare a namespace. *

* The namespace will be declared on the current namespace context. *

* The namespace can be removed by popping the current namespace * context, or, if the declaration occured in the root context, by * reseting the namespace context. *

* A default namespace can be declared by passing "" as * the value of the prefix parameter. * A namespace may be undeclared by passing null as the * value of the namespaceURI parameter. *

* @param prefix the namespace prefix to declare, may not be null. * @param namespaceURI the namespace URI to declare, may be null. * @throws IllegalArgumentException, if the prefix is null. */ public void declareNamespace(String prefix, String namespaceURI) { if (prefix == null) throw new IllegalArgumentException(); prefix = prefix.intern(); // Ignore the "xml" or "xmlns" declarations if (prefix == "xml" || prefix == "xmlns") return; // Check for undeclaration if (namespaceURI != null) namespaceURI = namespaceURI.intern(); if (namespacePosition == namespaceURIs.length) resizeNamespaces(); // Add new declaration prefixes[namespacePosition] = prefix; namespaceURIs[namespacePosition++] = namespaceURI; } private void resizeNamespaces() { final int newLength = namespaceURIs.length * 3 / 2 + 1; String[] newPrefixes = new String[newLength]; System.arraycopy(prefixes, 0, newPrefixes, 0, prefixes.length); prefixes = newPrefixes; String[] newNamespaceURIs = new String[newLength]; System.arraycopy(namespaceURIs, 0, newNamespaceURIs, 0, namespaceURIs.length); namespaceURIs = newNamespaceURIs; } /** * Push a namespace context on the stack. */ public void pushContext() { if (contextPosition == contexts.length) resizeContexts(); contexts[contextPosition++] = namespacePosition; } private void resizeContexts() { int[] newContexts = new int[contexts.length * 3 / 2 + 1]; System.arraycopy(contexts, 0, newContexts, 0, contexts.length); contexts = newContexts; } /** * Pop the namespace context off the stack. *

* Namespaces declared within the context (to be popped) * will be removed and no longer be in scope. */ public void popContext() { if (contextPosition > 0) { namespacePosition = contexts[--contextPosition]; } } /** * Reset namespace contexts. *

* Pop all namespace contexts and reset the root context. */ public void resetContexts() { namespacePosition = 2; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy