/*
* 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.jackrabbit.core.xml;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
import javax.jcr.NamespaceException;
import java.util.HashMap;
import java.util.Map;
/**
* Hierarchically scoped namespace resolver. Each NamespaceContext instance
* contains an immutable set of namespace mappings and a reference (possibly
* <code>null</code>) to a parent NamespaceContext. Namespace resolution is
* performed by first looking at the local namespace mappings and then using
* the parent resolver if no local match is found.
* <p>
* The local namespace mappings are stored internally as two hash maps, one
* that maps the namespace prefixes to namespace URIs and another that contains
* the reverse mapping.
*/
class NamespaceContext implements NamespaceResolver {
/**
* The parent namespace context.
*/
private final NamespaceContext parent;
/**
* The namespace prefix to namespace URI mapping.
*/
private final Map<String, String> prefixToURI;
/**
* The namespace URI to namespace prefix mapping.
*/
private final Map<String, String> uriToPrefix;
/**
* Creates a NamespaceContext instance with the given parent context
* and local namespace mappings.
*
* @param parent parent context
* @param mappings local namespace mappings (prefix -> URI)
*/
public NamespaceContext(NamespaceContext parent, Map<String, String> mappings) {
this.parent = parent;
this.prefixToURI = new HashMap<String, String>();
this.uriToPrefix = new HashMap<String, String>();
for (Map.Entry<String, String> mapping : mappings.entrySet()) {
prefixToURI.put(mapping.getKey(), mapping.getValue());
uriToPrefix.put(mapping.getValue(), mapping.getKey());
}
}
/**
* Returns the parent namespace context.
*
* @return parent namespace context
*/
public NamespaceContext getParent() {
return parent;
}
//------------------------------------------------< NamespaceResolver >
/**
* Returns the namespace URI mapped to the given prefix.
*
* @param prefix namespace prefix
* @return namespace URI
* @throws NamespaceException if the prefix is not mapped
*/
public String getURI(String prefix) throws NamespaceException {
NamespaceContext current = this;
while (current != null) {
String uri = (String) current.prefixToURI.get(prefix);
if (uri != null) {
return uri;
}
current = current.parent;
}
throw new NamespaceException("Unknown prefix: " + prefix);
}
/**
* Returns the namespace prefix mapped to the given URI.
*
* @param uri namespace URI
* @return namespace prefix
* @throws NamespaceException if the URI is not mapped
*/
public String getPrefix(String uri) throws NamespaceException {
NamespaceContext current = this;
while (current != null) {
String prefix = (String) current.uriToPrefix.get(uri);
if (prefix != null) {
return prefix;
}
current = current.parent;
}
throw new NamespaceException("Unknown URI: " + uri);
}
}