1
2
3
4
5
6
7
8 package de.nierbeck.timeTrack.model.impl.runtime;
9
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.Map;
15 import java.util.Set;
16
17 import javax.xml.XMLConstants;
18
19 import org.xml.sax.SAXException;
20
21 import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
22 import com.sun.xml.bind.marshaller.NamespaceSupport;
23
24 /***
25 * Implementation of the NamespaceContext2.
26 *
27 * This class also provides several utility methods for XMLSerializer-derived
28 * classes.
29 *
30 * The startElement method and the endElement method need to be called
31 * appropriately when used. See javadoc for those methods for details.
32 */
33 public class NamespaceContextImpl implements NamespaceContext2 {
34 /***
35 * Sequence generator. Used as the last resort to generate unique prefix.
36 */
37 private int iota = 1;
38
39 /***
40 * Used to maintain association between prefixes and URIs.
41 */
42 private final NamespaceSupport nss = new NamespaceSupport();
43
44 /***
45 * A flag that indicates the current mode of this object.
46 */
47 private boolean inCollectingMode;
48
49 /*** Assigns prefixes to URIs. Can be null. */
50 private final NamespacePrefixMapper prefixMapper;
51
52 /***
53 * Used during the collecting mode to sort out the namespace URIs we need
54 * for this element.
55 *
56 * A map from prefixes to namespace URIs.
57 */
58 private final Map decls = new HashMap();
59
60 private final Map reverseDecls = new HashMap();
61
62 public NamespaceContextImpl(NamespacePrefixMapper _prefixMapper) {
63 this.prefixMapper = _prefixMapper;
64
65
66 nss.declarePrefix("", "");
67 nss.declarePrefix("xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI);
68
69
70 }
71
72 public final NamespacePrefixMapper getNamespacePrefixMapper() {
73 return prefixMapper;
74 }
75
76
77
78
79
80
81 /***
82 * @param requirePrefix
83 * true if this is called for attribute name. false otherwise.
84 */
85 public String declareNamespace(String namespaceUri, String preferedPrefix,
86 boolean requirePrefix) {
87 if (!inCollectingMode) {
88 if (!requirePrefix && nss.getURI("").equals(namespaceUri))
89 return "";
90
91
92
93
94
95
96 if (requirePrefix)
97 return nss.getPrefix2(namespaceUri);
98 else
99 return nss.getPrefix(namespaceUri);
100 } else {
101 if (requirePrefix && namespaceUri.length() == 0)
102 return "";
103
104
105 String prefix = (String) reverseDecls.get(namespaceUri);
106 if (prefix != null) {
107 if (!requirePrefix || prefix.length() != 0) {
108
109
110 return prefix;
111 } else {
112
113
114
115
116 decls.remove(prefix);
117 reverseDecls.remove(namespaceUri);
118 }
119 }
120
121 if (namespaceUri.length() == 0) {
122
123
124 prefix = "";
125 } else {
126
127 prefix = nss.getPrefix(namespaceUri);
128 if (prefix == null)
129 prefix = (String) reverseDecls.get(namespaceUri);
130
131 if (prefix == null) {
132
133
134
135
136
137
138 if (prefixMapper != null)
139 prefix = prefixMapper.getPreferredPrefix(namespaceUri,
140 preferedPrefix, requirePrefix);
141 else
142 prefix = preferedPrefix;
143
144 if (prefix == null)
145
146 prefix = "ns" + (iota++);
147 }
148 }
149
150
151
152 if (requirePrefix && prefix.length() == 0)
153
154 prefix = "ns" + (iota++);
155
156 while (true) {
157 String existingUri = (String) decls.get(prefix);
158
159 if (existingUri == null) {
160
161 decls.put(prefix, namespaceUri);
162 reverseDecls.put(namespaceUri, prefix);
163 return prefix;
164 }
165
166 if (existingUri.length() == 0) {
167
168
169
170 ;
171 } else {
172
173
174
175
176
177 decls.put(prefix, namespaceUri);
178 reverseDecls.put(namespaceUri, prefix);
179
180 namespaceUri = existingUri;
181 }
182
183
184
185 prefix = "ns" + (iota++);
186
187
188 }
189 }
190 }
191
192 public String getPrefix(String namespaceUri) {
193
194
195
196
197
198
199
200 return declareNamespace(namespaceUri, null, false);
201 }
202
203 /***
204 * Obtains the namespace URI currently associated to the given prefix. If no
205 * namespace URI is associated, return null.
206 */
207 public String getNamespaceURI(String prefix) {
208 String uri = (String) decls.get(prefix);
209 if (uri != null)
210 return uri;
211
212 return nss.getURI(prefix);
213 }
214
215 public Iterator getPrefixes(String namespaceUri) {
216
217 Set s = new HashSet();
218
219 String prefix = (String) reverseDecls.get(namespaceUri);
220 if (prefix != null)
221 s.add(prefix);
222
223 if (nss.getURI("").equals(namespaceUri))
224 s.add("");
225
226 for (Enumeration e = nss.getPrefixes(namespaceUri); e.hasMoreElements();)
227 s.add(e.nextElement());
228
229 return s.iterator();
230 }
231
232 /***
233 * Sets the current bindings aside and starts a new element context.
234 *
235 * This method should be called at the beginning of the startElement method
236 * of the Serializer implementation.
237 */
238 public void startElement() {
239 nss.pushContext();
240 inCollectingMode = true;
241 }
242
243 /***
244 * Reconciles the namespace URI/prefix mapping requests since the last
245 * startElement method invocation and finalizes them.
246 *
247 * This method must be called after all the necessary namespace URIs for
248 * this element is reported through the declareNamespace method or the
249 * getPrefix method.
250 */
251 public void endNamespaceDecls() {
252 if (!decls.isEmpty()) {
253
254 for (Iterator itr = decls.entrySet().iterator(); itr.hasNext();) {
255 Map.Entry e = (Map.Entry) itr.next();
256 String prefix = (String) e.getKey();
257 String uri = (String) e.getValue();
258 if (!uri.equals(nss.getURI(prefix)))
259
260 nss.declarePrefix(prefix, uri);
261 }
262 decls.clear();
263 reverseDecls.clear();
264 }
265 inCollectingMode = false;
266 }
267
268 /***
269 * Ends the current element context and gets back to the parent context.
270 *
271 * This method should be called at the end of the endElement method of
272 * derived classes.
273 */
274 public void endElement() {
275 nss.popContext();
276 }
277
278 /*** Iterates all newly declared namespace prefixes for this element. */
279 public void iterateDeclaredPrefixes(PrefixCallback callback)
280 throws SAXException {
281 for (Enumeration e = nss.getDeclaredPrefixes(); e.hasMoreElements();) {
282 String p = (String) e.nextElement();
283 String uri = nss.getURI(p);
284
285 callback.onPrefixMapping(p, uri);
286 }
287 }
288
289 }