View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package javax.xml.namespace;
17  
18  import java.io.IOException;
19  import java.io.ObjectInputStream;
20  import java.io.Serializable;
21  
22  /**
23   * <code>QName</code> class represents the value of a qualified name
24   * as specified in <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML
25   * Schema Part2: Datatypes specification</a>.
26   * <p>
27   * The value of a QName contains a <b>namespaceURI</b>, a <b>localPart</b> and a
28   * <b>prefix</b>. The localPart provides the local part of the qualified name.
29   * The namespaceURI is a URI reference identifying the namespace.
30   *
31   * @version 1.1
32   */
33  public class QName implements Serializable {
34  
35      /** Comment/shared empty <code>String</code>. */
36      private static final String emptyString = "".intern();
37  
38      private String namespaceURI;
39  
40      private String localPart;
41  
42      private String prefix;
43  
44      /**
45       * Constructor for the QName.
46       *
47       * @param localPart local part of the QName
48       */
49      public QName(String localPart) {
50          this(emptyString, localPart, emptyString);
51      }
52  
53      /**
54       * Constructor for the QName.
55       *
56       * @param namespaceURI namespace URI for the QName
57       * @param localPart local part of the QName.
58       */
59      public QName(String namespaceURI, String localPart) {
60          this(namespaceURI, localPart, emptyString);
61      }
62  
63      /**
64       * Constructor for the QName.
65       *
66       * @param namespaceURI Namespace URI for the QName
67       * @param localPart Local part of the QName.
68       * @param prefix Prefix of the QName.
69       */
70      public QName(String namespaceURI, String localPart, String prefix) {
71          this.namespaceURI = (namespaceURI == null)
72                  ? emptyString
73                  : namespaceURI.intern();
74          if (localPart == null) {
75              throw new IllegalArgumentException("invalid QName local part");
76          } else {
77              this.localPart = localPart.intern();
78          }
79  
80          if (prefix == null) {
81              throw new IllegalArgumentException("invalid QName prefix");
82          } else {
83              this.prefix = prefix.intern();
84          }
85      }
86  
87      /**
88       * Gets the namespace URI for this QName.
89       *
90       * @return namespace URI
91       */
92      public String getNamespaceURI() {
93          return namespaceURI;
94      }
95  
96      /**
97       * Gets the local part for this QName.
98       *
99       * @return the local part
100      */
101     public String getLocalPart() {
102         return localPart;
103     }
104 
105     /**
106      * Gets the prefix for this QName.
107      *
108      * @return the prefix
109      */
110     public String getPrefix() {
111         return prefix;
112     }
113 
114     /**
115      * Returns a string representation of this QName.
116      *
117      * @return  a string representation of the QName
118      */
119     public String toString() {
120 
121         return ((namespaceURI == emptyString)
122                 ? localPart
123                 : '{' + namespaceURI + '}' + localPart);
124     }
125 
126     /**
127      * Tests this QName for equality with another object.
128      * <p>
129      * If the given object is not a QName or is null then this method
130      * returns <tt>false</tt>.
131      * <p>
132      * For two QNames to be considered equal requires that both
133      * localPart and namespaceURI must be equal. This method uses
134      * <code>String.equals</code> to check equality of localPart
135      * and namespaceURI. Any class that extends QName is required
136      * to satisfy this equality contract.
137      * <p>
138      * This method satisfies the general contract of the <code>Object.equals</code> method.
139      *
140      * @param obj the reference object with which to compare
141      *
142      * @return <code>true</code> if the given object is identical to this
143      *      QName: <code>false</code> otherwise.
144      */
145     public final boolean equals(Object obj) {
146 
147         if (obj == this) {
148             return true;
149         }
150 
151         if (!(obj instanceof QName)) {
152             return false;
153         }
154 
155         if ((namespaceURI == ((QName) obj).namespaceURI)
156                 && (localPart == ((QName) obj).localPart)) {
157             return true;
158         }
159 
160         return false;
161     }
162 
163     /**
164      * Returns a QName holding the value of the specified String.
165      * <p>
166      * The string must be in the form returned by the QName.toString()
167      * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}"
168      * part being optional.
169      * <p>
170      * This method doesn't do a full validation of the resulting QName.
171      * In particular, it doesn't check that the resulting namespace URI
172      * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting
173      * local part is a legal NCName per the XML Namespaces specification.
174      *
175      * @param s the string to be parsed
176      * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName
177      * @return QName corresponding to the given String
178      */
179     public static QName valueOf(String s) {
180 
181         if ((s == null) || s.equals("")) {
182             throw new IllegalArgumentException("invalid QName literal");
183         }
184 
185         if (s.charAt(0) == '{') {
186             int i = s.indexOf('}');
187 
188             if (i == -1) {
189                 throw new IllegalArgumentException("invalid QName literal");
190             }
191 
192             if (i == s.length() - 1) {
193                 throw new IllegalArgumentException("invalid QName literal");
194             } else {
195                 return new QName(s.substring(1, i), s.substring(i + 1));
196             }
197         } else {
198             return new QName(s);
199         }
200     }
201 
202     /**
203      * Returns a hash code value for this QName object. The hash code
204      * is based on both the localPart and namespaceURI parts of the
205      * QName. This method satisfies the  general contract of the
206      * <code>Object.hashCode</code> method.
207      *
208      * @return a hash code value for this Qname object
209      */
210     public final int hashCode() {
211         return namespaceURI.hashCode() ^ localPart.hashCode();
212     }
213 
214     /**
215      * Ensure that deserialization properly interns the results.
216      * @param in the ObjectInputStream to be read
217      * @throws IOException  if there was a failure in the object input stream
218      * @throws ClassNotFoundException   if the class of any sub-objects could
219      *              not be found
220      */
221     private void readObject(ObjectInputStream in) throws
222             IOException, ClassNotFoundException {
223         in.defaultReadObject();
224 
225         namespaceURI = namespaceURI.intern();
226         localPart = localPart.intern();
227         prefix = prefix.intern();
228     }
229 }