View Javadoc

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