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;
9   
10  import java.io.IOException;
11  import java.io.ObjectInputStream;
12  import java.io.ObjectOutputStream;
13  import java.io.Serializable;
14  
15  import org.dom4j.tree.QNameCache;
16  import org.dom4j.util.SingletonStrategy;
17  
18  /***
19   * <p>
20   * <code>QName</code> represents a qualified name value of an XML element or
21   * attribute. It consists of a local name and a {@link Namespace}instance. This
22   * object is immutable.
23   * </p>
24   * 
25   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
26   */
27  public class QName implements Serializable {
28      /*** The Singleton instance */
29      private static SingletonStrategy singleton = null;
30  
31      static {
32          try {
33              String defaultSingletonClass = "org.dom4j.util.SimpleSingleton";
34              Class clazz = null;
35              try {
36                  String singletonClass = defaultSingletonClass;
37                  singletonClass = System.getProperty(
38                          "org.dom4j.QName.singleton.strategy", singletonClass);
39                  clazz = Class.forName(singletonClass);
40              } catch (Exception exc1) {
41                  try {
42                      String singletonClass = defaultSingletonClass;
43                      clazz = Class.forName(singletonClass);
44                  } catch (Exception exc2) {
45                  }
46              }
47              singleton = (SingletonStrategy) clazz.newInstance();
48              singleton.setSingletonClassName(QNameCache.class.getName());
49          } catch (Exception exc3) {
50          }
51      }
52  
53      /*** The local name of the element or attribute */
54      private String name;
55  
56      /*** The qualified name of the element or attribute */
57      private String qualifiedName;
58  
59      /*** The Namespace of this element or attribute */
60      private transient Namespace namespace;
61  
62      /*** A cached version of the hashcode for efficiency */
63      private int hashCode;
64  
65      /*** The document factory used for this QName if specified or null */
66      private DocumentFactory documentFactory;
67  
68      public QName(String name) {
69          this(name, Namespace.NO_NAMESPACE);
70      }
71  
72      public QName(String name, Namespace namespace) {
73          this.name = (name == null) ? "" : name;
74          this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE
75                  : namespace;
76      }
77  
78      public QName(String name, Namespace namespace, String qualifiedName) {
79          this.name = (name == null) ? "" : name;
80          this.qualifiedName = qualifiedName;
81          this.namespace = (namespace == null) ? Namespace.NO_NAMESPACE
82                  : namespace;
83      }
84  
85      public static QName get(String name) {
86          return getCache().get(name);
87      }
88  
89      public static QName get(String name, Namespace namespace) {
90          return getCache().get(name, namespace);
91      }
92  
93      public static QName get(String name, String prefix, String uri) {
94          if (((prefix == null) || (prefix.length() == 0)) && (uri == null)) {
95              return QName.get(name);
96          } else if ((prefix == null) || (prefix.length() == 0)) {
97              return getCache().get(name, Namespace.get(uri));
98          } else if (uri == null) {
99              return QName.get(name);
100         } else {
101             return getCache().get(name, Namespace.get(prefix, uri));
102         }
103     }
104 
105     public static QName get(String qualifiedName, String uri) {
106         if (uri == null) {
107             return getCache().get(qualifiedName);
108         } else {
109             return getCache().get(qualifiedName, uri);
110         }
111     }
112 
113     public static QName get(String localName, Namespace namespace,
114             String qualifiedName) {
115         return getCache().get(localName, namespace, qualifiedName);
116     }
117 
118     /***
119      * DOCUMENT ME!
120      * 
121      * @return the local name
122      */
123     public String getName() {
124         return name;
125     }
126 
127     /***
128      * DOCUMENT ME!
129      * 
130      * @return the qualified name in the format <code>prefix:localName</code>
131      */
132     public String getQualifiedName() {
133         if (qualifiedName == null) {
134             String prefix = getNamespacePrefix();
135 
136             if ((prefix != null) && (prefix.length() > 0)) {
137                 qualifiedName = prefix + ":" + name;
138             } else {
139                 qualifiedName = name;
140             }
141         }
142 
143         return qualifiedName;
144     }
145 
146     /***
147      * DOCUMENT ME!
148      * 
149      * @return the namespace of this QName
150      */
151     public Namespace getNamespace() {
152         return namespace;
153     }
154 
155     /***
156      * DOCUMENT ME!
157      * 
158      * @return the namespace URI of this QName
159      */
160     public String getNamespacePrefix() {
161         if (namespace == null) {
162             return "";
163         }
164 
165         return namespace.getPrefix();
166     }
167 
168     /***
169      * DOCUMENT ME!
170      * 
171      * @return the namespace URI of this QName
172      */
173     public String getNamespaceURI() {
174         if (namespace == null) {
175             return "";
176         }
177 
178         return namespace.getURI();
179     }
180 
181     /***
182      * DOCUMENT ME!
183      * 
184      * @return the hash code based on the qualified name and the URI of the
185      *         namespace.
186      */
187     public int hashCode() {
188         if (hashCode == 0) {
189             hashCode = getName().hashCode() ^ getNamespaceURI().hashCode();
190 
191             if (hashCode == 0) {
192                 hashCode = 0xbabe;
193             }
194         }
195 
196         return hashCode;
197     }
198 
199     public boolean equals(Object object) {
200         if (this == object) {
201             return true;
202         } else if (object instanceof QName) {
203             QName that = (QName) object;
204 
205             // we cache hash codes so this should be quick
206             if (hashCode() == that.hashCode()) {
207                 return getName().equals(that.getName())
208                         && getNamespaceURI().equals(that.getNamespaceURI());
209             }
210         }
211 
212         return false;
213     }
214 
215     public String toString() {
216         return super.toString() + " [name: " + getName() + " namespace: \""
217                 + getNamespace() + "\"]";
218     }
219 
220     /***
221      * DOCUMENT ME!
222      * 
223      * @return the factory that should be used for Elements of this QName
224      */
225     public DocumentFactory getDocumentFactory() {
226         return documentFactory;
227     }
228 
229     public void setDocumentFactory(DocumentFactory documentFactory) {
230         this.documentFactory = documentFactory;
231     }
232 
233     private void writeObject(ObjectOutputStream out) throws IOException {
234         // We use writeObject() and not writeUTF() to minimize space
235         // This allows for writing pointers to already written strings
236         out.writeObject(namespace.getPrefix());
237         out.writeObject(namespace.getURI());
238 
239         out.defaultWriteObject();
240     }
241 
242     private void readObject(ObjectInputStream in) throws IOException,
243             ClassNotFoundException {
244         String prefix = (String) in.readObject();
245         String uri = (String) in.readObject();
246 
247         in.defaultReadObject();
248 
249         namespace = Namespace.get(prefix, uri);
250     }
251 
252     private static QNameCache getCache() {
253         QNameCache cache = (QNameCache) singleton.instance();
254         return cache;
255     }
256 }
257 
258 
259 
260 /*
261  * Redistribution and use of this software and associated documentation
262  * ("Software"), with or without modification, are permitted provided that the
263  * following conditions are met:
264  * 
265  * 1. Redistributions of source code must retain copyright statements and
266  * notices. Redistributions must also contain a copy of this document.
267  * 
268  * 2. Redistributions in binary form must reproduce the above copyright notice,
269  * this list of conditions and the following disclaimer in the documentation
270  * and/or other materials provided with the distribution.
271  * 
272  * 3. The name "DOM4J" must not be used to endorse or promote products derived
273  * from this Software without prior written permission of MetaStuff, Ltd. For
274  * written permission, please contact dom4j-info@metastuff.com.
275  * 
276  * 4. Products derived from this Software may not be called "DOM4J" nor may
277  * "DOM4J" appear in their names without prior written permission of MetaStuff,
278  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
279  * 
280  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
281  * 
282  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
283  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
284  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
285  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
286  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
287  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
289  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
290  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
291  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292  * POSSIBILITY OF SUCH DAMAGE.
293  * 
294  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
295  */