KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > xml > namespace > QName


1 // $Id: QName.java,v 1.10 2004/02/09 23:41:21 jsuttor Exp $
2

3 /*
4  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.xml.namespace;
9
10 import java.io.Serializable JavaDoc;
11 import java.security.AccessController JavaDoc;
12 import java.security.PrivilegedAction JavaDoc;
13 import javax.xml.XMLConstants JavaDoc;
14
15 /**
16  * <p><code>QName</code> represents a <strong>qualified name</strong>
17  * as defined in the XML specifications: <a
18  * HREF="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part2:
19  * Datatypes specification</a>, <a
20  * HREF="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
21  * in XML</a>, <a
22  * HREF="http://www.w3.org/XML/xml-names-19990114-errata">Namespaces
23  * in XML Errata</a>.</p>
24  *
25  * <p>The value of a <code>QName</code> contains a <strong>Namespace
26  * URI</strong>, <strong>local part</strong> and
27  * <strong>prefix</strong>.</p>
28  *
29  * <p>The prefix is included in <code>QName</code> to retain lexical
30  * information <strong><em>when present</em></strong> in an {@link
31  * javax.xml.transform.Source XML input source}. The prefix is
32  * <strong><em>NOT</em></strong> used in {@link #equals(Object)
33  * QName.equals(Object)} or to compute the {@link #hashCode()
34  * QName.hashCode()}. Equality and the hash code are defined using
35  * <strong><em>only</em></strong> the Namespace URI and local part.</p>
36  *
37  * <p>If not specified, the Namespace URI is set to {@link
38  * javax.xml.XMLConstants#NULL_NS_URI XMLConstants.NULL_NS_URI}.
39  * If not specified, the prefix is set to {@link
40  * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
41  * XMLConstants.DEFAULT_NS_PREFIX}.</p>
42  *
43  * <p><code>QName</code> is immutable.</p>
44  *
45  * @author <a HREF="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
46  * @version $Revision: 1.10 $, $Date: 2004/02/09 23:41:21 $
47  * @see <a HREF="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part2: Datatypes specification</a>
48  * @see <a HREF="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces in XML</a>
49  * @see <a HREF="http://www.w3.org/XML/xml-names-19990114-errata">Namespaces in XML Errata</a>
50  * @since 1.5
51  */

52
53 public class QName implements Serializable JavaDoc {
54
55     /**
56      * <p>Stream Unique Identifier.</p>
57      *
58      * <p>Due to a historical defect, QName was released with multiple
59      * serialVersionUID values even though its serialization was the
60      * same.</p>
61      *
62      * <p>To workaround this issue, serialVersionUID is set with either
63      * a default value or a compatibility value. To use the
64      * compatiblity value, set the system property:</p>
65      *
66      * <code>com.sun.xml.namespace.QName.useCompatibleSerialVersionUID=1.0</code>
67      *
68      * <p>This workaround was inspired by classes in the javax.management
69      * package, e.g. ObjectName, etc.
70      * See CR6267224 for original defect report.</p>
71      */

72     private static final long serialVersionUID;
73     /**
74      * <p>Default <code>serialVersionUID</code> value.</p>
75      */

76     private static final long defaultSerialVersionUID = -9120448754896609940L;
77     /**
78      * <p>Compatibility <code>serialVersionUID</code> value.</p>
79      */

80     private static final long compatibleSerialVersionUID = 4418622981026545151L;
81     /**
82      * <p>Flag to use default or campatible serialVersionUID.</p>
83      */

84     private static boolean useDefaultSerialVersionUID = true;
85     static {
86         try {
87             // use a privileged block as reading a system property
88
String JavaDoc valueUseCompatibleSerialVersionUID = (String JavaDoc) AccessController.doPrivileged(
89                     new PrivilegedAction JavaDoc() {
90                         public Object JavaDoc run() {
91                             return System.getProperty("com.sun.xml.namespace.QName.useCompatibleSerialVersionUID");
92                         }
93                     }
94             );
95             useDefaultSerialVersionUID =
96                        (valueUseCompatibleSerialVersionUID != null && valueUseCompatibleSerialVersionUID.equals("1.0")) ? false : true;
97         } catch (Exception JavaDoc exception) {
98             // use default if any Exceptions
99
useDefaultSerialVersionUID = true;
100         }
101         // set serialVersionUID to desired value
102
if (useDefaultSerialVersionUID)
103         {
104             serialVersionUID = defaultSerialVersionUID;
105         } else {
106             serialVersionUID = compatibleSerialVersionUID;
107         }
108     }
109     /**
110      * <p>Namespace URI of this <code>QName</code>.</p>
111      */

112     private final String JavaDoc namespaceURI;
113
114     /**
115      * <p>local part of this <code>QName</code>.</p>
116      */

117     private final String JavaDoc localPart;
118
119     /**
120      * <p>prefix of this <code>QName</code>.</p>
121      */

122     private final String JavaDoc prefix;
123
124     /**
125      * <p><code>QName</code> constructor specifying the Namespace URI
126      * and local part.</p>
127      *
128      * <p>If the Namespace URI is <code>null</code>, it is set to
129      * {@link javax.xml.XMLConstants#NULL_NS_URI
130      * XMLConstants.NULL_NS_URI}. This value represents no
131      * explicitly defined Namespace as defined by the <a
132      * HREF="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
133      * in XML</a> specification. This action preserves compatible
134      * behavior with QName 1.0. Explicitly providing the {@link
135      * javax.xml.XMLConstants#NULL_NS_URI
136      * XMLConstants.NULL_NS_URI} value is the preferred coding
137      * style.</p>
138      *
139      * <p>If the local part is <code>null</code> an
140      * <code>IllegalArgumentException</code> is thrown.
141      * A local part of "" is allowed to preserve
142      * compatible behavior with QName 1.0. </p>
143      *
144      * <p>When using this constructor, the prefix is set to {@link
145      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
146      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
147      *
148      * <p>The Namespace URI is not validated as a
149      * <a HREF="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
150      * The local part is not validated as a
151      * <a HREF="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
152      * as specified in <a HREF="http://www.w3.org/TR/REC-xml-names/">Namespaces
153      * in XML</a>.</p>
154      *
155      * @param namespaceURI Namespace URI of the <code>QName</code>
156      * @param localPart local part of the <code>QName</code>
157      *
158      * @see #QName(String namespaceURI, String localPart, String
159      * prefix) QName(String namespaceURI, String localPart, String
160      * prefix)
161      */

162     public QName(final String JavaDoc namespaceURI, final String JavaDoc localPart) {
163         this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX);
164     }
165
166     /**
167      * <p><code>QName</code> constructor specifying the Namespace URI,
168      * local part and prefix.</p>
169      *
170      * <p>If the Namespace URI is <code>null</code>, it is set to
171      * {@link javax.xml.XMLConstants#NULL_NS_URI
172      * XMLConstants.NULL_NS_URI}. This value represents no
173      * explicitly defined Namespace as defined by the <a
174      * HREF="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
175      * in XML</a> specification. This action preserves compatible
176      * behavior with QName 1.0. Explicitly providing the {@link
177      * javax.xml.XMLConstants#NULL_NS_URI
178      * XMLConstants.NULL_NS_URI} value is the preferred coding
179      * style.</p>
180      *
181      * <p>If the local part is <code>null</code> an
182      * <code>IllegalArgumentException</code> is thrown.
183      * A local part of "" is allowed to preserve
184      * compatible behavior with QName 1.0. </p>
185      *
186      * <p>If the prefix is <code>null</code>, an
187      * <code>IllegalArgumentException</code> is thrown. Use {@link
188      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
189      * XMLConstants.DEFAULT_NS_PREFIX} to explicitly indicate that no
190      * prefix is present or the prefix is not relevant.</p>
191      *
192      * <p>The Namespace URI is not validated as a
193      * <a HREF="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
194      * The local part and prefix are not validated as a
195      * <a HREF="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
196      * as specified in <a HREF="http://www.w3.org/TR/REC-xml-names/">Namespaces
197      * in XML</a>.</p>
198      *
199      * @param namespaceURI Namespace URI of the <code>QName<code>
200      * @param localPart local part of the <code>QName<code>
201      * @param prefix prefix of the <code>QName<code>
202      */

203     public QName(String JavaDoc namespaceURI, String JavaDoc localPart, String JavaDoc prefix) {
204
205         // map null Namespace URI to default to preserve compatibility with QName 1.0
206
if (namespaceURI == null) {
207             this.namespaceURI = XMLConstants.NULL_NS_URI;
208         } else {
209             this.namespaceURI = namespaceURI;
210         }
211
212         // local part is required. "" is allowed to preserve compatibility with QName 1.0
213
if (localPart == null) {
214             throw new IllegalArgumentException JavaDoc("local part cannot be \"null\" when creating a QName");
215         }
216         this.localPart = localPart;
217
218         // prefix is required
219
if (prefix == null) {
220             throw new IllegalArgumentException JavaDoc("prefix cannot be \"null\" when creating a QName");
221         }
222         this.prefix = prefix;
223     }
224
225     /**
226      * <p><code>QName</code> constructor specifying the local part.</p>
227      *
228      * <p>If the local part is <code>null</code> an
229      * <code>IllegalArgumentException</code> is thrown.
230      * A local part of "" is allowed to preserve
231      * compatible behavior with QName 1.0. </p>
232      *
233      * <p>When using this constructor, the Namespace URI is set to
234      * {@link javax.xml.XMLConstants#NULL_NS_URI
235      * XMLConstants.NULL_NS_URI} and the prefix is set to {@link
236      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
237      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
238      *
239      * <p><em>In an XML context, all Element and Attribute names exist
240      * in the context of a Namespace. Making this explicit during the
241      * construction of a <code>QName</code> helps prevent hard to
242      * diagnosis XML validity errors. The constructors {@link
243      * #QName(String namespaceURI, String localPart) QName(String
244      * namespaceURI, String localPart)} and
245      * {@link #QName(String namespaceURI, String localPart, String prefix)}
246      * are preferred.</em></p>
247      *
248      * <p>The local part is not validated as a
249      * <a HREF="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
250      * as specified in <a HREF="http://www.w3.org/TR/REC-xml-names/">Namespaces
251      * in XML</a>.</p>
252      *
253      * @param localPart local part of the <code>QName</code>
254      * @see #QName(String namespaceURI, String localPart) QName(String
255      * namespaceURI, String localPart)
256      * @see #QName(String namespaceURI, String localPart, String
257      * prefix) QName(String namespaceURI, String localPart, String
258      * prefix)
259      */

260     public QName(String JavaDoc localPart) {
261         this(
262             XMLConstants.NULL_NS_URI,
263             localPart,
264             XMLConstants.DEFAULT_NS_PREFIX);
265     }
266     
267     /**
268      * <p>Get the Namespace URI of this <code>QName</code>.</p>
269      *
270      * @return Namespace URI of this <code>QName</code>
271      */

272     public String JavaDoc getNamespaceURI() {
273         return namespaceURI;
274     }
275
276     /**
277      * <p>Get the local part of this <code>QName</code>.</p>
278      *
279      * @return local part of this <code>QName</code>
280      */

281     public String JavaDoc getLocalPart() {
282         return localPart;
283     }
284
285     /**
286      * <p>Get the prefix of this <code>QName</code>.</p>
287      *
288      * <p>The prefix assigned to a <code>QName</code> might
289      * <strong><em>NOT</em></strong> be valid in a different
290      * context. For example, a <code>QName</code> may be assigned a
291      * prefix in the context of parsing a document but that prefix may
292      * be invalid in the context of a different document.</p>
293      *
294      * @return prefix of this <code>QName</code>
295      */

296     public String JavaDoc getPrefix() {
297         return prefix;
298     }
299
300     /**
301      * <p>Test this <code>QName</code> for equality with another
302      * <code>Object</code>.</p>
303      *
304      * <p>If the <code>Object</code> to be tested is not a
305      * <code>QName</code> or is <code>null</code>, then this method
306      * returns <code>false</code>.</p>
307      *
308      * <p>Two <code>QName</code>s are considered equal if and only if
309      * both the Namespace URI and local part are equal. This method
310      * uses <code>String.equals()</code> to check equality of the
311      * Namespace URI and local part. The prefix is
312      * <strong><em>NOT</em></strong> used to determine equality.</p>
313      *
314      * <p>This method satisfies the general contract of {@link
315      * java.lang.Object#equals(Object) Object.equals(Object)}</p>
316      *
317      * @param objectToTest the <code>Object</code> to test for
318      * equality with this <code>QName</code>
319      * @return <code>true</code> if the given <code>Object</code> is
320      * equal to this <code>QName</code> else <code>false</code>
321      */

322     public final boolean equals(Object JavaDoc objectToTest) {
323         if (objectToTest == null || !(objectToTest instanceof QName JavaDoc)) {
324             return false;
325         }
326
327         QName JavaDoc qName = (QName JavaDoc) objectToTest;
328
329         return namespaceURI.equals(qName.namespaceURI)
330             && localPart.equals(qName.localPart);
331     }
332
333     /**
334      * <p>Generate the hash code for this <code>QName</code>.</p>
335      *
336      * <p>The hash code is calculated using both the Namespace URI and
337      * the local part of the <code>QName</code>. The prefix is
338      * <strong><em>NOT</em></strong> used to calculate the hash
339      * code.</p>
340      *
341      * <p>This method satisfies the general contract of {@link
342      * java.lang.Object#hashCode() Object.hashCode()}.</p>
343      *
344      * @return hash code for this <code>QName</code> <code>Object</code>
345      */

346     public final int hashCode() {
347         return namespaceURI.hashCode() ^ localPart.hashCode();
348     }
349
350     /**
351      * <p><code>String</code> representation of this
352      * <code>QName</code>.</p>
353      *
354      * <p>The commonly accepted way of representing a <code>QName</code>
355      * as a <code>String</code> was <a HREF="http://jclark.com/xml/xmlns.htm">defined</a>
356      * by James Clark. Although this is not a <em>standard</em>
357      * specification, it is in common use, e.g. {@link javax.xml.transform.Transformer#setParameter(String name, Object value)}.
358      * This implementation represents a <code>QName</code> as:
359      * "{" + Namespace URI + "}" + local part. If the Namespace URI
360      * <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the
361      * local part is returned. An appropriate use of this method is
362      * for debugging or logging for human consumption.</p>
363      *
364      * <p>Note the prefix value is <strong><em>NOT</em></strong>
365      * returned as part of the <code>String</code> representation.</p>
366      *
367      * <p>This method satisfies the general contract of {@link
368      * java.lang.Object#toString() Object.toString()}.</p>
369      *
370      * @return <code>String</code> representation of this <code>QName</code>
371      */

372     public String JavaDoc toString() {
373         if (namespaceURI.equals(XMLConstants.NULL_NS_URI)) {
374             return localPart;
375         } else {
376             return "{" + namespaceURI + "}" + localPart;
377         }
378     }
379
380     /**
381      * <p><code>QName</code> derived from parsing the formatted
382      * <code>String</code>.</p>
383      *
384      * <p>If the <code>String</code> is <code>null</code> or does not conform to
385      * {@link #toString() QName.toString()} formatting, an
386      * <code>IllegalArgumentException</code> is thrown.</p>
387      *
388      * <p><em>The <code>String</code> <strong>MUST</strong> be in the
389      * form returned by {@link #toString() QName.toString()}.</em></p>
390
391      * <p>The commonly accepted way of representing a <code>QName</code>
392      * as a <code>String</code> was <a HREF="http://jclark.com/xml/xmlns.htm">defined</a>
393      * by James Clark. Although this is not a <em>standard</em>
394      * specification, it is in common use, e.g. {@link javax.xml.transform.Transformer#setParameter(String name, Object value)}.
395      * This implementation parses a <code>String</code> formatted
396      * as: "{" + Namespace URI + "}" + local part. If the Namespace
397      * URI <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the
398      * local part should be provided.</p>
399      *
400      * <p>The prefix value <strong><em>CANNOT</em></strong> be
401      * represented in the <code>String</code> and will be set to
402      * {@link javax.xml.XMLConstants#DEFAULT_NS_PREFIX
403      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
404      *
405      * <p>This method does not do full validation of the resulting
406      * <code>QName</code>.
407      * <p>The Namespace URI is not validated as a
408      * <a HREF="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
409      * The local part is not validated as a
410      * <a HREF="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
411      * as specified in
412      * <a HREF="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>.</p>
413      *
414      * @param qNameAsString <code>String</code> representation
415      * of the <code>QName</code>
416      * @return <code>QName</code> corresponding to the given <code>String</code>
417      * @see #toString() QName.toString()
418      */

419     public static QName JavaDoc valueOf(String JavaDoc qNameAsString) {
420
421         // null is not valid
422
if (qNameAsString == null) {
423             throw new IllegalArgumentException JavaDoc("cannot create QName from \"null\" or \"\" String");
424         }
425
426         // "" local part is valid to preserve compatible behavior with QName 1.0
427
if (qNameAsString.length() == 0) {
428             return new QName JavaDoc(
429                 XMLConstants.NULL_NS_URI,
430                 qNameAsString,
431                 XMLConstants.DEFAULT_NS_PREFIX);
432         }
433
434         // local part only?
435
if (qNameAsString.charAt(0) != '{') {
436             return new QName JavaDoc(
437                 XMLConstants.NULL_NS_URI,
438                 qNameAsString,
439                 XMLConstants.DEFAULT_NS_PREFIX);
440         }
441
442         // Namespace URI improperly specified?
443
if (qNameAsString.startsWith("{" + XMLConstants.NULL_NS_URI + "}")) {
444             throw new IllegalArgumentException JavaDoc(
445                 "Namespace URI .equals(XMLConstants.NULL_NS_URI), "
446                 + ".equals(\"" + XMLConstants.NULL_NS_URI + "\"), "
447                 + "only the local part, "
448                 + "\"" + qNameAsString.substring(2 + XMLConstants.NULL_NS_URI.length()) + "\", "
449                 + "should be provided.");
450         }
451
452         // Namespace URI and local part specified
453
int endOfNamespaceURI = qNameAsString.indexOf('}');
454         if (endOfNamespaceURI == -1) {
455             throw new IllegalArgumentException JavaDoc(
456                 "cannot create QName from \""
457                     + qNameAsString
458                     + "\", missing closing \"}\"");
459         }
460         return new QName JavaDoc(
461             qNameAsString.substring(1, endOfNamespaceURI),
462             qNameAsString.substring(endOfNamespaceURI + 1),
463             XMLConstants.DEFAULT_NS_PREFIX);
464     }
465 }
466
Popular Tags