package com.ausregistry.jtoolkit2.xml;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.NamespaceContext;
import com.ausregistry.jtoolkit2.se.ExtendedObjectType;
import com.ausregistry.jtoolkit2.se.ExtensionImpl;
import com.ausregistry.jtoolkit2.se.StandardObjectType;
/**
* <p>
* EPP specific implementation of a NamespaceContext, which maps prefixes to name space URIs and vice versa. Initially,
* instances of this class support all of the standard EPP object name spaces, as defined in RFC5730-RFC5733, as well as
* the name spaces of the e164epp, auext and aeext command/response extensions and the arext protocol extension. Support
* for other extensions can be added at runtime by invoking the {@link #put(String, String) put} class method.
* </p>
*
* <p>
* Uses the debug level loggers.
* </p>
*/
public final class NamespaceContextImpl implements NamespaceContext {
private static final int DEFAULT_SIZE = 8;
private static Map<List<String>, String> prefixUriMap;
private static Map<String, List<String>> uriPrefixMap;
static {
prefixUriMap = new HashMap<List<String>, String>(DEFAULT_SIZE);
uriPrefixMap = new HashMap<String, List<String>>(DEFAULT_SIZE);
/*
* No definite answer on why EPP has 2 prefixes, but it has been suggested that this may have to do with
* compatibility with the old toolkits.
*/
NamespaceContextImpl.put("e", "urn:ietf:params:xml:ns:epp-1.0");
NamespaceContextImpl.put("epp", "urn:ietf:params:xml:ns:epp-1.0");
for (StandardObjectType standardObjectType : StandardObjectType.values()) {
NamespaceContextImpl.put(standardObjectType.getName(), standardObjectType.getURI());
}
for (ExtensionImpl extension : ExtensionImpl.values()) {
NamespaceContextImpl.put(extension.getPrefix(), extension.getURI());
}
for (ExtendedObjectType extendedObjectType : ExtendedObjectType.values()) {
NamespaceContextImpl.put(extendedObjectType.getName(), extendedObjectType.getURI());
}
}
private final Logger debugLogger;
/**
* Create a NamespaceContextImpl with state as possibly adjusted by any previous calls to NamespaceContextImpl.put.
*/
public NamespaceContextImpl() {
final String pname = getClass().getPackage().getName();
debugLogger = Logger.getLogger(pname + ".debug");
}
/**
* Add a prefix to URI mapping and a URI to prefix mapping between the given prefix and URI.
*/
public static synchronized void put(String prefix, String uri) {
boolean isPut = false;
for (Map.Entry<List<String>, String> mapping : prefixUriMap.entrySet()) {
if (mapping.getValue().equals(uri)) {
mapping.getKey().add(prefix);
isPut = true;
break;
}
}
if (!isPut) {
final Vector<String> newList = new Vector<String>(3);
newList.add(prefix);
prefixUriMap.put(newList, uri);
}
if (uriPrefixMap.keySet().contains(uri)) {
final List<String> prefixList = uriPrefixMap.get(uri);
prefixList.add(prefix);
} else {
final List<String> newList = new Vector<String>(3);
newList.add(prefix);
uriPrefixMap.put(uri, newList);
}
}
/**
* Implemented using a map lookup of the given prefix.
*/
@Override
public String getNamespaceURI(String prefix) {
for (Map.Entry<List<String>, String> mapping : prefixUriMap.entrySet()) {
if (mapping.getKey().contains(prefix)) {
if (debugLogger.isLoggable(Level.FINE)) {
debugLogger.fine("resolved prefix " + prefix + " to URI " + mapping.getValue());
}
return mapping.getValue();
}
}
return null;
}
/**
* Implemented using a map lookup of the given name space URI.
*/
@Override
public String getPrefix(String namespaceURI) {
if (uriPrefixMap.keySet().contains(namespaceURI)) {
return uriPrefixMap.get(namespaceURI).get(0);
}
return null;
}
/**
* Lookup the List of prefixes for the given namespaceURI from the URI to prefix map, then return the iterator for
* that List if the URI is in the map. Return null if there is no mapping for the given URI.
*/
@Override
public Iterator<String> getPrefixes(String namespaceURI) {
if (!uriPrefixMap.keySet().contains(namespaceURI)) {
return null;
}
return uriPrefixMap.get(namespaceURI).iterator();
}
}