1 /*
2  * Copyright 2005-2014 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.xml.namespace;
18
19 import java.util.Collections;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.LinkedHashMap;
23 import java.util.LinkedHashSet;
24 import java.util.Map;
25 import java.util.Set;
26 import javax.xml.XMLConstants;
27 import javax.xml.namespace.NamespaceContext;
28
29 import org.springframework.util.Assert;
30
31 /**
32  * Simple {@code javax.xml.namespace.NamespaceContext} implementation. Follows the standard
33  * {@code NamespaceContext} contract, and is loadable via a {@code java.util.Map} or
34  * {@code java.util.Properties} object
35  *
36  * @author Arjen Poutsma
37  * @since 1.0.0
38  */

39 public class SimpleNamespaceContext implements NamespaceContext {
40
41     private Map<String, String> prefixToNamespaceUri = new LinkedHashMap<String, String>();
42
43     private Map<String, Set<String>> namespaceUriToPrefixes = new LinkedHashMap<String, Set<String>>();
44
45     @Override
46     public String getNamespaceURI(String prefix) {
47         Assert.notNull(prefix, "prefix is null");
48         if (XMLConstants.XML_NS_PREFIX.equals(prefix)) {
49             return XMLConstants.XML_NS_URI;
50         }
51         else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
52             return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
53         }
54         else if (prefixToNamespaceUri.containsKey(prefix)) {
55             return prefixToNamespaceUri.get(prefix);
56         }
57         return XMLConstants.NULL_NS_URI;
58     }
59
60     @Override
61     public String getPrefix(String namespaceUri) {
62         Iterator<String> iterator = getPrefixes(namespaceUri);
63         return iterator.hasNext() ? iterator.next() : null;
64     }
65
66     @Override
67     public Iterator<String> getPrefixes(String namespaceUri) {
68         Set<String> prefixes = getPrefixesInternal(namespaceUri);
69         prefixes = Collections.unmodifiableSet(prefixes);
70         return prefixes.iterator();
71     }
72
73     /**
74      * Sets the bindings for this namespace context. The supplied map must consist of string key value pairs.
75      *
76      * @param bindings the bindings
77      */

78     public void setBindings(Map<String, String> bindings) {
79         for (Map.Entry<String, String> entry : bindings.entrySet()) {
80             bindNamespaceUri(entry.getKey(), entry.getValue());
81         }
82     }
83
84     /**
85      * Binds the given namespace as default namespace.
86      *
87      * @param namespaceUri the namespace uri
88      */

89     public void bindDefaultNamespaceUri(String namespaceUri) {
90         bindNamespaceUri(XMLConstants.DEFAULT_NS_PREFIX, namespaceUri);
91     }
92
93     /**
94      * Binds the given prefix to the given namespace.
95      *
96      * @param prefix       the namespace prefix
97      * @param namespaceUri the namespace uri
98      */

99     public void bindNamespaceUri(String prefix, String namespaceUri) {
100         Assert.notNull(prefix, "No prefix given");
101         Assert.notNull(namespaceUri, "No namespaceUri given");
102         if (XMLConstants.XML_NS_PREFIX.equals(prefix)) {
103             Assert.isTrue(XMLConstants.XML_NS_URI.equals(namespaceUri), "Prefix \"" + prefix +
104                     "\" bound to namespace \"" + namespaceUri + "\" (should be \"" + XMLConstants.XML_NS_URI + "\")");
105         } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
106             Assert.isTrue(XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceUri), "Prefix \"" + prefix +
107                     "\" bound to namespace \"" + namespaceUri + "\" (should be \"" +
108                     XMLConstants.XMLNS_ATTRIBUTE_NS_URI + "\")");
109         }
110         else {
111             prefixToNamespaceUri.put(prefix, namespaceUri);
112             getPrefixesInternal(namespaceUri).add(prefix);
113         }
114     }
115
116     /** Removes all declared prefixes. */
117     public void clear() {
118         prefixToNamespaceUri.clear();
119         namespaceUriToPrefixes.clear();
120     }
121
122     /**
123      * Returns all declared prefixes.
124      *
125      * @return the declared prefixes
126      */

127     public Iterator<String> getBoundPrefixes() {
128         Set<String> prefixes = new HashSet<String>(prefixToNamespaceUri.keySet());
129         prefixes.remove(XMLConstants.DEFAULT_NS_PREFIX);
130         prefixes = Collections.unmodifiableSet(prefixes);
131         return prefixes.iterator();
132     }
133
134     private Set<String> getPrefixesInternal(String namespaceUri) {
135         if (XMLConstants.XML_NS_URI.equals(namespaceUri)) {
136             return Collections.singleton(XMLConstants.XML_NS_PREFIX);
137         }
138         else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceUri)) {
139             return Collections.singleton(XMLConstants.XMLNS_ATTRIBUTE);
140         }
141         else {
142             Set<String> set = namespaceUriToPrefixes.get(namespaceUri);
143             if (set == null) {
144                 set = new LinkedHashSet<String>();
145                 namespaceUriToPrefixes.put(namespaceUri, set);
146             }
147             return set;
148         }
149     }
150
151     /**
152      * Removes the given prefix from this context.
153      *
154      * @param prefix the prefix to be removed
155      */

156     public void removeBinding(String prefix) {
157         String namespaceUri = prefixToNamespaceUri.remove(prefix);
158         if (namespaceUri != null) {
159             Set<String> prefixes = getPrefixesInternal(namespaceUri);
160             prefixes.remove(prefix);
161         }
162     }
163
164     public boolean hasBinding(String prefix) {
165         return prefixToNamespaceUri.containsKey(prefix);
166     }
167 }
168