View Javadoc

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;
11  import java.util.Collections;
12  import java.util.HashMap;
13  import java.util.Iterator;
14  import java.util.List;
15  import java.util.Map;
16  import java.util.WeakHashMap;
17  
18  import org.dom4j.DocumentFactory;
19  import org.dom4j.Namespace;
20  import org.dom4j.QName;
21  
22  /***
23   * <p>
24   * <code>QNameCache</code> caches instances of <code>QName</code> for reuse
25   * both across documents and within documents.
26   * </p>< < < < < < < QNameCache.java
27   * 
28   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
29   * @version $Revision: 1.16 $ =======
30   * 
31   * @author <a href="mailto:james.strachan@metastuff.com">James Strachan </a>
32   * @version $Revision: 1.16 $ >>>>>>> 1.15
33   */
34  public class QNameCache {
35      /*** Cache of {@link QName}instances with no namespace */
36      protected Map noNamespaceCache = Collections
37              .synchronizedMap(new WeakHashMap());
38  
39      /***
40       * Cache of {@link Map}instances indexed by namespace which contain caches
41       * of {@link QName}for each name
42       */
43      protected Map namespaceCache = Collections
44              .synchronizedMap(new WeakHashMap());
45  
46      /***
47       * The document factory associated with new QNames instances in this cache
48       * or null if no instances should be associated by default
49       */
50      private DocumentFactory documentFactory;
51  
52      public QNameCache() {
53      }
54  
55      public QNameCache(DocumentFactory documentFactory) {
56          this.documentFactory = documentFactory;
57      }
58  
59      /***
60       * Returns a list of all the QName instances currently used
61       * 
62       * @return DOCUMENT ME!
63       */
64      public List getQNames() {
65          List answer = new ArrayList();
66          answer.addAll(noNamespaceCache.values());
67  
68          for (Iterator it = namespaceCache.values().iterator(); it.hasNext();) {
69              Map map = (Map) it.next();
70              answer.addAll(map.values());
71          }
72  
73          return answer;
74      }
75  
76      /***
77       * DOCUMENT ME!
78       * 
79       * @param name
80       *            DOCUMENT ME!
81       * 
82       * @return the QName for the given name and no namepsace
83       */
84      public QName get(String name) {
85          QName answer = null;
86  
87          if (name != null) {
88              answer = (QName) noNamespaceCache.get(name);
89          } else {
90              name = "";
91          }
92  
93          if (answer == null) {
94              answer = createQName(name);
95              answer.setDocumentFactory(documentFactory);
96              noNamespaceCache.put(name, answer);
97          }
98  
99          return answer;
100     }
101 
102     /***
103      * DOCUMENT ME!
104      * 
105      * @param name
106      *            DOCUMENT ME!
107      * @param namespace
108      *            DOCUMENT ME!
109      * 
110      * @return the QName for the given local name and namepsace
111      */
112     public QName get(String name, Namespace namespace) {
113         Map cache = getNamespaceCache(namespace);
114         QName answer = null;
115 
116         if (name != null) {
117             answer = (QName) cache.get(name);
118         } else {
119             name = "";
120         }
121 
122         if (answer == null) {
123             answer = createQName(name, namespace);
124             answer.setDocumentFactory(documentFactory);
125             cache.put(name, answer);
126         }
127 
128         return answer;
129     }
130 
131     /***
132      * DOCUMENT ME!
133      * 
134      * @param localName
135      *            DOCUMENT ME!
136      * @param namespace
137      *            DOCUMENT ME!
138      * @param qName
139      *            DOCUMENT ME!
140      * 
141      * @return the QName for the given local name, qualified name and namepsace
142      */
143     public QName get(String localName, Namespace namespace, String qName) {
144         Map cache = getNamespaceCache(namespace);
145         QName answer = null;
146 
147         if (localName != null) {
148             answer = (QName) cache.get(localName);
149         } else {
150             localName = "";
151         }
152 
153         if (answer == null) {
154             answer = createQName(localName, namespace, qName);
155             answer.setDocumentFactory(documentFactory);
156             cache.put(localName, answer);
157         }
158 
159         return answer;
160     }
161 
162     public QName get(String qualifiedName, String uri) {
163         int index = qualifiedName.indexOf(':');
164 
165         if (index < 0) {
166             return get(qualifiedName, Namespace.get(uri));
167         } else {
168             String name = qualifiedName.substring(index + 1);
169             String prefix = qualifiedName.substring(0, index);
170 
171             return get(name, Namespace.get(prefix, uri));
172         }
173     }
174 
175     /***
176      * DOCUMENT ME!
177      * 
178      * @param qname
179      *            DOCUMENT ME!
180      * 
181      * @return the cached QName instance if there is one or adds the given qname
182      *         to the cache if not
183      */
184     public QName intern(QName qname) {
185         return get(qname.getName(), qname.getNamespace(), qname
186                 .getQualifiedName());
187     }
188 
189     /***
190      * DOCUMENT ME!
191      * 
192      * @param namespace
193      *            DOCUMENT ME!
194      * 
195      * @return the cache for the given namespace. If one does not currently
196      *         exist it is created.
197      */
198     protected Map getNamespaceCache(Namespace namespace) {
199         if (namespace == Namespace.NO_NAMESPACE) {
200             return noNamespaceCache;
201         }
202 
203         Map answer = null;
204 
205         if (namespace != null) {
206             answer = (Map) namespaceCache.get(namespace);
207         }
208 
209         if (answer == null) {
210             answer = createMap();
211             namespaceCache.put(namespace, answer);
212         }
213 
214         return answer;
215     }
216 
217     /***
218      * A factory method
219      * 
220      * @return a newly created {@link Map}instance.
221      */
222     protected Map createMap() {
223         return Collections.synchronizedMap(new HashMap());
224     }
225 
226     /***
227      * Factory method to create a new QName object which can be overloaded to
228      * create derived QName instances
229      * 
230      * @param name
231      *            DOCUMENT ME!
232      * 
233      * @return DOCUMENT ME!
234      */
235     protected QName createQName(String name) {
236         return new QName(name);
237     }
238 
239     /***
240      * Factory method to create a new QName object which can be overloaded to
241      * create derived QName instances
242      * 
243      * @param name
244      *            DOCUMENT ME!
245      * @param namespace
246      *            DOCUMENT ME!
247      * 
248      * @return DOCUMENT ME!
249      */
250     protected QName createQName(String name, Namespace namespace) {
251         return new QName(name, namespace);
252     }
253 
254     /***
255      * Factory method to create a new QName object which can be overloaded to
256      * create derived QName instances
257      * 
258      * @param name
259      *            DOCUMENT ME!
260      * @param namespace
261      *            DOCUMENT ME!
262      * @param qualifiedName
263      *            DOCUMENT ME!
264      * 
265      * @return DOCUMENT ME!
266      */
267     protected QName createQName(String name, Namespace namespace,
268             String qualifiedName) {
269         return new QName(name, namespace, qualifiedName);
270     }
271 }
272 
273 
274 
275 /*
276  * Redistribution and use of this software and associated documentation
277  * ("Software"), with or without modification, are permitted provided that the
278  * following conditions are met:
279  * 
280  * 1. Redistributions of source code must retain copyright statements and
281  * notices. Redistributions must also contain a copy of this document.
282  * 
283  * 2. Redistributions in binary form must reproduce the above copyright notice,
284  * this list of conditions and the following disclaimer in the documentation
285  * and/or other materials provided with the distribution.
286  * 
287  * 3. The name "DOM4J" must not be used to endorse or promote products derived
288  * from this Software without prior written permission of MetaStuff, Ltd. For
289  * written permission, please contact dom4j-info@metastuff.com.
290  * 
291  * 4. Products derived from this Software may not be called "DOM4J" nor may
292  * "DOM4J" appear in their names without prior written permission of MetaStuff,
293  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
294  * 
295  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
296  * 
297  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
298  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
299  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
300  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
301  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
302  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
303  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
304  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
305  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
306  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
307  * POSSIBILITY OF SUCH DAMAGE.
308  * 
309  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
310  */