KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > dom4j > tree > NamespaceStack


1 /*
2  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3  *
4  * This software is open source.
5  * See the bottom of this file for the licence.
6  */

7
8 package org.dom4j.tree;
9
10 import java.util.ArrayList JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13
14 import org.dom4j.DocumentFactory;
15 import org.dom4j.Namespace;
16 import org.dom4j.QName;
17
18 /**
19  * NamespaceStack implements a stack of namespaces and optionally maintains a
20  * cache of all the fully qualified names (<code>QName</code>) which are in
21  * scope. This is useful when building or navigating a <i>dom4j </i> document.
22  *
23  * @author <a HREF="mailto:jstrachan@apache.org">James Strachan </a>
24  * @version $Revision: 1.13 $
25  */

26 public class NamespaceStack {
27     /** The factory used to create new <code>Namespace</code> instances */
28     private DocumentFactory documentFactory;
29
30     /** The Stack of namespaces */
31     private ArrayList JavaDoc namespaceStack = new ArrayList JavaDoc();
32
33     /** The cache of qualifiedNames to QNames per namespace context */
34     private ArrayList JavaDoc namespaceCacheList = new ArrayList JavaDoc();
35
36     /**
37      * A cache of current namespace context cache of mapping from qualifiedName
38      * to QName
39      */

40     private Map JavaDoc currentNamespaceCache;
41
42     /**
43      * A cache of mapping from qualifiedName to QName before any namespaces are
44      * declared
45      */

46     private Map JavaDoc rootNamespaceCache = new HashMap JavaDoc();
47
48     /** Caches the default namespace defined via xmlns="" */
49     private Namespace defaultNamespace;
50
51     public NamespaceStack() {
52         this.documentFactory = DocumentFactory.getInstance();
53     }
54
55     public NamespaceStack(DocumentFactory documentFactory) {
56         this.documentFactory = documentFactory;
57     }
58
59     /**
60      * Pushes the given namespace onto the stack so that its prefix becomes
61      * available.
62      *
63      * @param namespace
64      * is the <code>Namespace</code> to add to the stack.
65      */

66     public void push(Namespace namespace) {
67         namespaceStack.add(namespace);
68         namespaceCacheList.add(null);
69         currentNamespaceCache = null;
70
71         String JavaDoc prefix = namespace.getPrefix();
72
73         if ((prefix == null) || (prefix.length() == 0)) {
74             defaultNamespace = namespace;
75         }
76     }
77
78     /**
79      * Pops the most recently used <code>Namespace</code> from the stack
80      *
81      * @return Namespace popped from the stack
82      */

83     public Namespace pop() {
84         return remove(namespaceStack.size() - 1);
85     }
86
87     /**
88      * DOCUMENT ME!
89      *
90      * @return the number of namespaces on the stackce stack.
91      */

92     public int size() {
93         return namespaceStack.size();
94     }
95
96     /**
97      * Clears the stack
98      */

99     public void clear() {
100         namespaceStack.clear();
101         namespaceCacheList.clear();
102         rootNamespaceCache.clear();
103         currentNamespaceCache = null;
104     }
105
106     /**
107      * DOCUMENT ME!
108      *
109      * @param index
110      * DOCUMENT ME!
111      *
112      * @return the namespace at the specified index on the stack
113      */

114     public Namespace getNamespace(int index) {
115         return (Namespace) namespaceStack.get(index);
116     }
117
118     /**
119      * DOCUMENT ME!
120      *
121      * @param prefix
122      * DOCUMENT ME!
123      *
124      * @return the namespace for the given prefix or null if it could not be
125      * found.
126      */

127     public Namespace getNamespaceForPrefix(String JavaDoc prefix) {
128         if (prefix == null) {
129             prefix = "";
130         }
131
132         for (int i = namespaceStack.size() - 1; i >= 0; i--) {
133             Namespace namespace = (Namespace) namespaceStack.get(i);
134
135             if (prefix.equals(namespace.getPrefix())) {
136                 return namespace;
137             }
138         }
139
140         return null;
141     }
142
143     /**
144      * DOCUMENT ME!
145      *
146      * @param prefix
147      * DOCUMENT ME!
148      *
149      * @return the URI for the given prefix or null if it could not be found.
150      */

151     public String JavaDoc getURI(String JavaDoc prefix) {
152         Namespace namespace = getNamespaceForPrefix(prefix);
153
154         return (namespace != null) ? namespace.getURI() : null;
155     }
156
157     /**
158      * DOCUMENT ME!
159      *
160      * @param namespace
161      * DOCUMENT ME!
162      *
163      * @return true if the given prefix is in the stack.
164      */

165     public boolean contains(Namespace namespace) {
166         String JavaDoc prefix = namespace.getPrefix();
167         Namespace current = null;
168
169         if ((prefix == null) || (prefix.length() == 0)) {
170             current = getDefaultNamespace();
171         } else {
172             current = getNamespaceForPrefix(prefix);
173         }
174
175         if (current == null) {
176             return false;
177         }
178
179         if (current == namespace) {
180             return true;
181         }
182
183         return namespace.getURI().equals(current.getURI());
184     }
185
186     public QName getQName(String JavaDoc namespaceURI, String JavaDoc localName,
187             String JavaDoc qualifiedName) {
188         if (localName == null) {
189             localName = qualifiedName;
190         } else if (qualifiedName == null) {
191             qualifiedName = localName;
192         }
193
194         if (namespaceURI == null) {
195             namespaceURI = "";
196         }
197
198         String JavaDoc prefix = "";
199         int index = qualifiedName.indexOf(":");
200
201         if (index > 0) {
202             prefix = qualifiedName.substring(0, index);
203
204             if (localName.trim().length() == 0) {
205                 localName = qualifiedName.substring(index + 1);
206             }
207         } else if (localName.trim().length() == 0) {
208             localName = qualifiedName;
209         }
210
211         Namespace namespace = createNamespace(prefix, namespaceURI);
212
213         return pushQName(localName, qualifiedName, namespace, prefix);
214     }
215
216     public QName getAttributeQName(String JavaDoc namespaceURI, String JavaDoc localName,
217             String JavaDoc qualifiedName) {
218         if (qualifiedName == null) {
219             qualifiedName = localName;
220         }
221
222         Map JavaDoc map = getNamespaceCache();
223         QName answer = (QName) map.get(qualifiedName);
224
225         if (answer != null) {
226             return answer;
227         }
228
229         if (localName == null) {
230             localName = qualifiedName;
231         }
232
233         if (namespaceURI == null) {
234             namespaceURI = "";
235         }
236
237         Namespace namespace = null;
238         String JavaDoc prefix = "";
239         int index = qualifiedName.indexOf(":");
240
241         if (index > 0) {
242             prefix = qualifiedName.substring(0, index);
243             namespace = createNamespace(prefix, namespaceURI);
244
245             if (localName.trim().length() == 0) {
246                 localName = qualifiedName.substring(index + 1);
247             }
248         } else {
249             // attributes with no prefix have no namespace
250
namespace = Namespace.NO_NAMESPACE;
251
252             if (localName.trim().length() == 0) {
253                 localName = qualifiedName;
254             }
255         }
256
257         answer = pushQName(localName, qualifiedName, namespace, prefix);
258         map.put(qualifiedName, answer);
259
260         return answer;
261     }
262
263     /**
264      * Adds a namepace to the stack with the given prefix and URI
265      *
266      * @param prefix
267      * DOCUMENT ME!
268      * @param uri
269      * DOCUMENT ME!
270      */

271     public void push(String JavaDoc prefix, String JavaDoc uri) {
272         if (uri == null) {
273             uri = "";
274         }
275
276         Namespace namespace = createNamespace(prefix, uri);
277         push(namespace);
278     }
279
280     /**
281      * Adds a new namespace to the stack
282      *
283      * @param prefix
284      * DOCUMENT ME!
285      * @param uri
286      * DOCUMENT ME!
287      *
288      * @return DOCUMENT ME!
289      */

290     public Namespace addNamespace(String JavaDoc prefix, String JavaDoc uri) {
291         Namespace namespace = createNamespace(prefix, uri);
292         push(namespace);
293
294         return namespace;
295     }
296
297     /**
298      * Pops a namepace from the stack with the given prefix and URI
299      *
300      * @param prefix
301      * DOCUMENT ME!
302      *
303      * @return DOCUMENT ME!
304      */

305     public Namespace pop(String JavaDoc prefix) {
306         if (prefix == null) {
307             prefix = "";
308         }
309
310         Namespace namespace = null;
311
312         for (int i = namespaceStack.size() - 1; i >= 0; i--) {
313             Namespace ns = (Namespace) namespaceStack.get(i);
314
315             if (prefix.equals(ns.getPrefix())) {
316                 remove(i);
317                 namespace = ns;
318
319                 break;
320             }
321         }
322
323         if (namespace == null) {
324             System.out.println("Warning: missing namespace prefix ignored: "
325                     + prefix);
326         }
327
328         return namespace;
329     }
330
331     public String JavaDoc toString() {
332         return super.toString() + " Stack: " + namespaceStack.toString();
333     }
334
335     public DocumentFactory getDocumentFactory() {
336         return documentFactory;
337     }
338
339     public void setDocumentFactory(DocumentFactory documentFactory) {
340         this.documentFactory = documentFactory;
341     }
342
343     public Namespace getDefaultNamespace() {
344         if (defaultNamespace == null) {
345             defaultNamespace = findDefaultNamespace();
346         }
347
348         return defaultNamespace;
349     }
350
351     // Implementation methods
352
// -------------------------------------------------------------------------
353

354     /**
355      * Adds the QName to the stack of available QNames
356      *
357      * @param localName
358      * DOCUMENT ME!
359      * @param qualifiedName
360      * DOCUMENT ME!
361      * @param namespace
362      * DOCUMENT ME!
363      * @param prefix
364      * DOCUMENT ME!
365      *
366      * @return DOCUMENT ME!
367      */

368     protected QName pushQName(String JavaDoc localName, String JavaDoc qualifiedName,
369             Namespace namespace, String JavaDoc prefix) {
370         if ((prefix == null) || (prefix.length() == 0)) {
371             this.defaultNamespace = null;
372         }
373
374         return createQName(localName, qualifiedName, namespace);
375     }
376
377     /**
378      * Factory method to creeate new QName instances. By default this method
379      * interns the QName
380      *
381      * @param localName
382      * DOCUMENT ME!
383      * @param qualifiedName
384      * DOCUMENT ME!
385      * @param namespace
386      * DOCUMENT ME!
387      *
388      * @return DOCUMENT ME!
389      */

390     protected QName createQName(String JavaDoc localName, String JavaDoc qualifiedName,
391             Namespace namespace) {
392         return documentFactory.createQName(localName, namespace);
393     }
394
395     /**
396      * Factory method to creeate new Namespace instances. By default this method
397      * interns the Namespace
398      *
399      * @param prefix
400      * DOCUMENT ME!
401      * @param namespaceURI
402      * DOCUMENT ME!
403      *
404      * @return DOCUMENT ME!
405      */

406     protected Namespace createNamespace(String JavaDoc prefix, String JavaDoc namespaceURI) {
407         return documentFactory.createNamespace(prefix, namespaceURI);
408     }
409
410     /**
411      * Attempts to find the current default namespace on the stack right now or
412      * returns null if one could not be found
413      *
414      * @return DOCUMENT ME!
415      */

416     protected Namespace findDefaultNamespace() {
417         for (int i = namespaceStack.size() - 1; i >= 0; i--) {
418             Namespace namespace = (Namespace) namespaceStack.get(i);
419
420             if (namespace != null) {
421                 String JavaDoc prefix = namespace.getPrefix();
422
423                 if ((prefix == null) || (namespace.getPrefix().length() == 0)) {
424                     return namespace;
425                 }
426             }
427         }
428
429         return null;
430     }
431
432     /**
433      * Removes the namespace at the given index of the stack
434      *
435      * @param index
436      * DOCUMENT ME!
437      *
438      * @return DOCUMENT ME!
439      */

440     protected Namespace remove(int index) {
441         Namespace namespace = (Namespace) namespaceStack.remove(index);
442         namespaceCacheList.remove(index);
443         defaultNamespace = null;
444         currentNamespaceCache = null;
445
446         return namespace;
447     }
448
449     protected Map JavaDoc getNamespaceCache() {
450         if (currentNamespaceCache == null) {
451             int index = namespaceStack.size() - 1;
452
453             if (index < 0) {
454                 currentNamespaceCache = rootNamespaceCache;
455             } else {
456                 currentNamespaceCache = (Map JavaDoc) namespaceCacheList.get(index);
457
458                 if (currentNamespaceCache == null) {
459                     currentNamespaceCache = new HashMap JavaDoc();
460                     namespaceCacheList.set(index, currentNamespaceCache);
461                 }
462             }
463         }
464
465         return currentNamespaceCache;
466     }
467 }
468
469 /*
470  * Redistribution and use of this software and associated documentation
471  * ("Software"), with or without modification, are permitted provided that the
472  * following conditions are met:
473  *
474  * 1. Redistributions of source code must retain copyright statements and
475  * notices. Redistributions must also contain a copy of this document.
476  *
477  * 2. Redistributions in binary form must reproduce the above copyright notice,
478  * this list of conditions and the following disclaimer in the documentation
479  * and/or other materials provided with the distribution.
480  *
481  * 3. The name "DOM4J" must not be used to endorse or promote products derived
482  * from this Software without prior written permission of MetaStuff, Ltd. For
483  * written permission, please contact dom4j-info@metastuff.com.
484  *
485  * 4. Products derived from this Software may not be called "DOM4J" nor may
486  * "DOM4J" appear in their names without prior written permission of MetaStuff,
487  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
488  *
489  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
490  *
491  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
492  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
493  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
494  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
495  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
496  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
497  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
498  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
499  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
500  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
501  * POSSIBILITY OF SUCH DAMAGE.
502  *
503  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
504  */

505
Popular Tags