7e8092a980b7f2197564b4455b61dcc5bbb10d39
[utils] / support / general / src / main / java / org / wamblee / xml / SimpleNamespaceContext.java
1 /*
2  * Copyright 2005-2011 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 package org.wamblee.xml;
17
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24
25 import javax.xml.XMLConstants;
26 import javax.xml.namespace.NamespaceContext;
27
28 /**
29  * Implementation of {@link NamespaceContext} for binding namespace prefixes to 
30  * namespaces. This class implements the full contract as defined by that interface. 
31  * 
32  * It provides a fluent interface style. In its simplest use, it can be constructed
33  * empty or with a single prefix using a constructor. In addition, the methods
34  * {@link #addPrefix(String, String)} and {@link #defaultNamespace(String)} can be used
35  * to add prefixes and to define the default namespace respectively. 
36  * 
37  * @author Erik Brakkee
38  */
39 public class SimpleNamespaceContext implements NamespaceContext {
40
41     private String defaultNs;
42     private Map<String, String> prefixMap;
43
44     /**
45      * Constructs an empty context without prefixes. 
46      */
47     public SimpleNamespaceContext() {
48         defaultNs = null;
49         prefixMap = new HashMap<String, String>();
50     }
51
52     /**
53      * Constructs a context with a single prefix. 
54      * @param aPrefix Prefix. 
55      * @param aNamespace Namespace. 
56      */
57     public SimpleNamespaceContext(String aPrefix, String aNamespace) {
58         this();
59         addPrefix(aPrefix, aNamespace);
60     }
61
62     /**
63      * Constructs empty context (for use with static imports).
64      * @return Namespace context. 
65      */
66     public static SimpleNamespaceContext namespaceContext() {
67         return new SimpleNamespaceContext();
68     }
69
70     /**
71      * Constructs a context with a single prefix (for use with static imports).  
72      * @param aPrefix Prefix
73      * @param aNamespace Namespace. 
74      * @return
75      */
76     public static SimpleNamespaceContext namespaceContext(String aPrefix,
77         String aNamespace) {
78         return new SimpleNamespaceContext(aPrefix, aNamespace);
79     }
80
81     /**
82      * Sets the default namespace. 
83      * @param aDefaultNs Default namespace. 
84      * @return Current object for method chaining. 
85      */
86     public SimpleNamespaceContext defaultNamespace(String aDefaultNs) {
87         defaultNs = aDefaultNs;
88         return this;
89     }
90
91     /**
92      * Adds a prefix. 
93      * @param aPrefix Prefix to add. 
94      * @param aNamespace Namespace to bind prefix to. 
95      * @return Current object for method chaining. 
96      */
97     public SimpleNamespaceContext addPrefix(String aPrefix, String aNamespace) {
98         if (aPrefix == null) {
99             throw new IllegalArgumentException("prefix is null");
100         }
101         if (aNamespace == null) {
102             throw new IllegalArgumentException("namespace is null");
103         }
104         prefixMap.put(aPrefix, aNamespace);
105         return this;
106     }
107
108     @Override
109     public String getNamespaceURI(String aPrefix) {
110         if (XMLConstants.DEFAULT_NS_PREFIX.equals(aPrefix)) {
111             if (defaultNs == null) {
112                 return XMLConstants.NULL_NS_URI;
113             }
114             return defaultNs;
115         }
116         if (XMLConstants.XML_NS_PREFIX.equals(aPrefix)) {
117             return XMLConstants.XML_NS_URI;
118         }
119         if (XMLConstants.XMLNS_ATTRIBUTE.equals(aPrefix)) {
120             return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
121         }
122         String ns = prefixMap.get(aPrefix);
123         if (ns == null) {
124             return XMLConstants.NULL_NS_URI;
125         }
126         return ns;
127     }
128
129     @Override
130     public String getPrefix(String aNamespaceURI) {
131          List<String> prefixes = getPrefixList(aNamespaceURI);
132          if (prefixes.isEmpty()) { 
133              return null; 
134          }
135          return prefixes.get(0);
136     }
137
138     @Override
139     public Iterator getPrefixes(String aNamespaceURI) {
140         return Collections.unmodifiableList(getPrefixList(aNamespaceURI)).iterator();
141     }
142     
143     public List<String> getPrefixList(String aNamespaceURI) {
144         List<String> result = new ArrayList<String>(); 
145         
146         if ((aNamespaceURI == null && defaultNs == null) ||
147             (defaultNs != null && defaultNs.equals(aNamespaceURI))) {
148             result.add(XMLConstants.DEFAULT_NS_PREFIX);
149             return result; // make sure not more prefixes added.
150         }
151         if (XMLConstants.XML_NS_URI.equals(aNamespaceURI)) {
152             result.add(XMLConstants.XML_NS_PREFIX);
153             return result; // make sure no more prefixes added. 
154         }
155         if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(aNamespaceURI)) {
156             result.add(XMLConstants.XMLNS_ATTRIBUTE);
157             return result; 
158         }
159         for (Map.Entry<String,String> entry: prefixMap.entrySet()) {
160             if (entry.getValue().equals(aNamespaceURI)) { 
161                 result.add(entry.getKey());
162             }
163         }
164         return result; 
165     }
166
167 }