Added XPath utilities and updated the javadocs.
[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     public static SimpleNamespaceContext namespaces() { 
53         return new SimpleNamespaceContext();
54     }
55
56     /**
57      * Constructs a context with a single prefix. 
58      * @param aPrefix Prefix. 
59      * @param aNamespace Namespace. 
60      */
61     public SimpleNamespaceContext(String aPrefix, String aNamespace) {
62         this();
63         addPrefix(aPrefix, aNamespace);
64     }
65
66     /**
67      * Constructs empty context (for use with static imports).
68      * @return Namespace context. 
69      */
70     public static SimpleNamespaceContext namespaceContext() {
71         return new SimpleNamespaceContext();
72     }
73
74     /**
75      * Constructs a context with a single prefix (for use with static imports).  
76      * @param aPrefix Prefix
77      * @param aNamespace Namespace. 
78      * @return
79      */
80     public static SimpleNamespaceContext namespaceContext(String aPrefix,
81         String aNamespace) {
82         return new SimpleNamespaceContext(aPrefix, aNamespace);
83     }
84
85     /**
86      * Sets the default namespace. 
87      * @param aDefaultNs Default namespace. 
88      * @return Current object for method chaining. 
89      */
90     public SimpleNamespaceContext defaultNamespace(String aDefaultNs) {
91         defaultNs = aDefaultNs;
92         return this;
93     }
94
95     /**
96      * Adds a prefix. 
97      * @param aPrefix Prefix to add. 
98      * @param aNamespace Namespace to bind prefix to. 
99      * @return Current object for method chaining. 
100      */
101     public SimpleNamespaceContext addPrefix(String aPrefix, String aNamespace) {
102         if (aPrefix == null) {
103             throw new IllegalArgumentException("prefix is null");
104         }
105         if (aNamespace == null) {
106             throw new IllegalArgumentException("namespace is null");
107         }
108         prefixMap.put(aPrefix, aNamespace);
109         return this;
110     }
111
112     @Override
113     public String getNamespaceURI(String aPrefix) {
114         if (XMLConstants.DEFAULT_NS_PREFIX.equals(aPrefix)) {
115             if (defaultNs == null) {
116                 return XMLConstants.NULL_NS_URI;
117             }
118             return defaultNs;
119         }
120         if (XMLConstants.XML_NS_PREFIX.equals(aPrefix)) {
121             return XMLConstants.XML_NS_URI;
122         }
123         if (XMLConstants.XMLNS_ATTRIBUTE.equals(aPrefix)) {
124             return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
125         }
126         String ns = prefixMap.get(aPrefix);
127         if (ns == null) {
128             return XMLConstants.NULL_NS_URI;
129         }
130         return ns;
131     }
132
133     @Override
134     public String getPrefix(String aNamespaceURI) {
135          List<String> prefixes = getPrefixList(aNamespaceURI);
136          if (prefixes.isEmpty()) { 
137              return null; 
138          }
139          return prefixes.get(0);
140     }
141
142     @Override
143     public Iterator getPrefixes(String aNamespaceURI) {
144         return Collections.unmodifiableList(getPrefixList(aNamespaceURI)).iterator();
145     }
146     
147     public List<String> getPrefixList(String aNamespaceURI) {
148         List<String> result = new ArrayList<String>(); 
149         
150         if ((aNamespaceURI == null && defaultNs == null) ||
151             (defaultNs != null && defaultNs.equals(aNamespaceURI))) {
152             result.add(XMLConstants.DEFAULT_NS_PREFIX);
153             return result; // make sure not more prefixes added.
154         }
155         if (XMLConstants.XML_NS_URI.equals(aNamespaceURI)) {
156             result.add(XMLConstants.XML_NS_PREFIX);
157             return result; // make sure no more prefixes added. 
158         }
159         if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(aNamespaceURI)) {
160             result.add(XMLConstants.XMLNS_ATTRIBUTE);
161             return result; 
162         }
163         for (Map.Entry<String,String> entry: prefixMap.entrySet()) {
164             if (entry.getValue().equals(aNamespaceURI)) { 
165                 result.add(entry.getKey());
166             }
167         }
168         return result; 
169     }
170
171 }