1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 package org.exolab.castor.xml;
37
38 import java.util.ArrayList;
39 import java.util.Enumeration;
40 import java.util.HashMap;
41 import java.util.Iterator;
42 import java.util.List;
43 import java.util.Map;
44 import org.castor.core.util.Assert;
45 import org.xml.sax.ContentHandler;
46 import org.xml.sax.SAXException;
47 import org.xml.sax.helpers.AttributeListImpl;
48
49
50
51
52
53
54
55 public final class Namespaces {
56
57
58
59
60 public static final String XML_NAMESPACE_PREFIX = "xml";
61
62
63
64
65 public static final String XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
66
67
68
69
70 private static final String CDATA = "CDATA";
71
72
73
74
75 private static final String XMLNS = "xmlns";
76
77
78
79
80 private final List<Namespace> namespaces = new ArrayList<Namespace>();
81
82
83
84
85 private final Map<String, Namespace> namespaceMap = new HashMap<String, Namespace>();
86
87 public Namespaces() {
88 super();
89 namespaceMap.put(XML_NAMESPACE_PREFIX, new Namespace(XML_NAMESPACE_PREFIX, XML_NAMESPACE));
90 }
91
92
93
94
95
96
97
98
99
100 public synchronized void addNamespace(String prefix, String uri) {
101
102
103 Assert.notNull(uri, "Namespace URI must not be null");
104
105
106 if (prefix == null)
107 prefix = "";
108
109
110 if (XML_NAMESPACE_PREFIX.equalsIgnoreCase(prefix)) {
111 if (!XML_NAMESPACE.equals(uri)) {
112 String err =
113 "The prefix 'xml' is reserved (XML 1.0 Specification) " + "and cannot be declared.";
114 throw new IllegalArgumentException(err);
115 }
116
117
118 return;
119 }
120
121 else if (XML_NAMESPACE.equals(uri)) {
122 String err = "The namespace '" + XML_NAMESPACE;
123 err += "' is reserved (XML 1.0 Specification) and cannot be declared.";
124 throw new IllegalArgumentException(err);
125 }
126
127
128 Namespace namespace;
129 if (namespaceMap.containsKey(prefix)) {
130 namespaceMap.get(prefix).setUri(uri);
131 } else {
132 namespace = new Namespace(prefix, uri);
133 namespaces.add(namespace);
134 namespaceMap.put(prefix, namespace);
135 }
136 }
137
138
139
140
141
142
143 public Enumeration<String> getLocalNamespaces() {
144 return new NamespaceEnumerator(namespaces.iterator());
145 }
146
147
148
149
150
151
152
153
154 public String getNamespaceURI(String prefix) {
155
156 if (prefix == null)
157 prefix = "";
158
159
160
161
162
163
164 Namespace namespace = namespaceMap.get(prefix);
165
166 if (namespace != null) {
167 return namespace.getUri();
168 }
169
170 return null;
171 }
172
173
174
175
176
177
178
179
180
181
182
183 public String getNamespacePrefix(String nsURI) {
184
185
186 Assert.notNull(nsURI, "Namespace URI must not be null.");
187
188 for (Namespace namespace : namespaces) {
189
190 if (nsURI.equals(namespace.getUri())) {
191 return namespace.getPrefix();
192 }
193 }
194
195
196 if (XML_NAMESPACE.equals(nsURI)) {
197 return XML_NAMESPACE_PREFIX;
198 }
199
200 return null;
201
202 }
203
204
205
206
207
208
209 public Enumeration<String> getLocalNamespacePrefixes() {
210 return new NamespaceEnumerator(namespaces.iterator(), NamespaceEnumerator.PREFIX);
211 }
212
213
214
215
216
217
218
219
220
221
222 public String[] getNamespacePrefixes(String nsURI) {
223
224
225 Assert.notNull(nsURI, "Namespace URI must not be null.");
226
227 List<String> prefixes = new ArrayList<String>();
228 for (Namespace namespace : namespaces) {
229 if (namespace.getUri().equals(nsURI)) {
230 prefixes.add(namespace.getPrefix());
231 }
232 }
233
234 return prefixes.toArray(new String[0]);
235 }
236
237
238
239
240
241
242
243
244
245
246
247 public String getNonDefaultNamespacePrefix(String nsURI) {
248 Assert.notNull(nsURI, "Namespace URI must not be null.");
249 for (Namespace namespace : namespaces) {
250 if (nsURI.equals(namespace.getUri()) && namespace.getPrefix().length() > 0) {
251 return namespace.getPrefix();
252 }
253 }
254
255
256 if (XML_NAMESPACE.equals(nsURI)) {
257 return XML_NAMESPACE_PREFIX;
258 }
259
260 return null;
261
262 }
263
264
265
266
267
268
269
270
271 public synchronized boolean removeNamespace(String prefix) {
272 if (prefix == null) {
273 return false;
274 }
275
276 if (namespaceMap.containsKey(prefix)) {
277 Namespace namespace = namespaceMap.get(prefix);
278 namespaceMap.remove(prefix);
279 namespaces.remove(namespace);
280
281 return true;
282 }
283
284 return false;
285 }
286
287
288
289
290
291
292 public void sendEndEvents(ContentHandler handler) throws SAXException {
293 for (Namespace namespace : namespaces) {
294 handler.endPrefixMapping(namespace.getPrefix());
295 }
296 }
297
298
299
300
301
302
303 public void sendStartEvents(ContentHandler handler) throws SAXException {
304 for (Namespace namespace : namespaces) {
305 handler.startPrefixMapping(namespace.getPrefix(), namespace.getUri());
306 }
307 }
308
309
310
311
312
313
314 @SuppressWarnings("deprecation")
315 public void declareAsAttributes(AttributeListImpl atts) {
316
317 String attName = null;
318 for (Namespace ns : namespaces) {
319 if (ns.prefix != null) {
320 int len = ns.prefix.length();
321 if (len > 0) {
322 attName =
323 new StringBuilder(6 + len).append(XMLNS).append(':').append(ns.prefix).toString();
324 atts.addAttribute(attName, CDATA, ns.uri);
325 }
326
327 else {
328 atts.addAttribute(XMLNS, CDATA, ns.uri);
329 }
330 }
331 else {
332 atts.addAttribute(XMLNS, CDATA, ns.uri);
333 }
334 }
335 }
336
337
338
339
340 class Namespace {
341
342
343
344
345 private String uri;
346
347
348
349
350 private String prefix;
351
352
353
354
355
356 Namespace() {
357 super();
358 }
359
360 Namespace(String prefix, String uri) {
361 this.prefix = prefix;
362 this.uri = uri;
363 }
364
365
366
367
368
369
370 public String getPrefix() {
371 return prefix;
372 }
373
374
375
376
377
378
379 public void setPrefix(String prefix) {
380 this.prefix = prefix;
381 }
382
383
384
385
386
387
388 public String getUri() {
389 return uri;
390 }
391
392
393
394
395
396
397 public void setUri(String uri) {
398 this.uri = uri;
399 }
400
401
402
403
404 @Override
405 public boolean equals(Object object) {
406 if (this == object) {
407 return true;
408 }
409 if (object == null || getClass() != object.getClass()) {
410 return false;
411 }
412
413 Namespace namespace = (Namespace) object;
414
415 if (prefix != null ? !prefix.equals(namespace.prefix) : namespace.prefix != null)
416 return false;
417 if (uri != null ? !uri.equals(namespace.uri) : namespace.uri != null)
418 return false;
419
420 return true;
421 }
422
423
424
425
426 @Override
427 public int hashCode() {
428 int result = prefix != null ? prefix.hashCode() : 0;
429 result = 31 * result + (uri != null ? uri.hashCode() : 0);
430 return result;
431 }
432 }
433
434
435
436
437 static class NamespaceEnumerator implements java.util.Enumeration<String> {
438 public static final int URI = 0;
439 public static final int PREFIX = 1;
440
441 private int _returnType = URI;
442
443 private Iterator<Namespace> namespaceIterator;
444
445 NamespaceEnumerator(Iterator<Namespace> namespaceIterator) {
446 this.namespaceIterator = namespaceIterator;
447 }
448
449 NamespaceEnumerator(Iterator<Namespace> namespaceIterator, int returnType) {
450 this.namespaceIterator = namespaceIterator;
451 _returnType = returnType;
452 }
453
454 public boolean hasMoreElements() {
455 return namespaceIterator.hasNext();
456 }
457
458 public String nextElement() {
459
460 String result;
461 Namespace ns = namespaceIterator.next();
462
463 if (_returnType == URI) {
464 result = ns.getUri();
465 } else {
466 result = ns.getPrefix();
467 }
468
469 return result;
470 }
471
472 }
473
474 }