OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / javax / xml / namespace / QName.java
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 // $Id: QName.java 754581 2009-03-15 01:32:39Z mrglavas $
19
20 package javax.xml.namespace;
21
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.Serializable;
25 import java.security.AccessController;
26 import java.security.PrivilegedAction;
27 import javax.xml.XMLConstants;
28
29 /**
30  * <p><code>QName</code> represents a <strong>qualified name</strong>
31  * as defined in the XML specifications: <a
32  * href="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part2:
33  * Datatypes specification</a>, <a
34  * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
35  * in XML</a>, <a
36  * href="http://www.w3.org/XML/xml-names-19990114-errata">Namespaces
37  * in XML Errata</a>.</p>
38  *
39  * <p>The value of a <code>QName</code> contains a <strong>Namespace
40  * URI</strong>, <strong>local part</strong> and
41  * <strong>prefix</strong>.</p>
42  *
43  * <p>The prefix is included in <code>QName</code> to retain lexical
44  * information <strong><em>when present</em></strong> in an {@link
45  * javax.xml.transform.Source XML input source}. The prefix is
46  * <strong><em>NOT</em></strong> used in {@link #equals(Object)
47  * QName.equals(Object)} or to compute the {@link #hashCode()
48  * QName.hashCode()}.  Equality and the hash code are defined using
49  * <strong><em>only</em></strong> the Namespace URI and local part.</p>
50  *
51  * <p>If not specified, the Namespace URI is set to {@link
52  * javax.xml.XMLConstants#NULL_NS_URI XMLConstants.NULL_NS_URI}.
53  * If not specified, the prefix is set to {@link
54  * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
55  * XMLConstants.DEFAULT_NS_PREFIX}.</p>
56  *
57  * <p><code>QName</code> is immutable.</p>
58  *
59  * @author <a href="mailto:Jeff.Suttor@Sun.com">Jeff Suttor</a>
60  * @version $Revision: 754581 $, $Date: 2009-03-14 18:32:39 -0700 (Sat, 14 Mar 2009) $
61  * @see <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML Schema Part2: Datatypes specification</a>
62  * @see <a href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces in XML</a>
63  * @see <a href="http://www.w3.org/XML/xml-names-19990114-errata">Namespaces in XML Errata</a>
64  * @since 1.5
65  */
66
67 public class QName implements Serializable {
68
69     /**
70      * <p>Stream Unique Identifier.</p>
71      *
72      * <p>To enable the compatibility <code>serialVersionUID</code>
73      * set the System Property
74      * <code>org.apache.xml.namespace.QName.useCompatibleSerialVersionUID</code>
75      * to a value of "1.0".</p>
76      */
77     private static final long serialVersionUID;
78
79     /**
80      * <p>The original default Stream Unique Identifier.</p>
81      */
82     private static final long defaultSerialVersionUID = -9120448754896609940L;
83
84     /**
85      * <p>The compatibility Stream Unique Identifier that was introduced
86      * with Java 5 SE SDK.</p>
87      */
88     private static final long compatabilitySerialVersionUID = 4418622981026545151L;
89
90     static {
91         String compatPropValue = null;
92         try {
93             compatPropValue = (String)AccessController.doPrivileged(
94                     new PrivilegedAction() {
95                         public Object run() {
96                             return System.getProperty("org.apache.xml.namespace.QName.useCompatibleSerialVersionUID");
97                         }
98                     });
99         }
100         catch (Exception e) {}
101         // If 1.0 use compatibility serialVersionUID
102         serialVersionUID = !"1.0".equals(compatPropValue) ? defaultSerialVersionUID : compatabilitySerialVersionUID;
103     }
104
105     /**
106      * <p>Namespace URI of this <code>QName</code>.</p>
107      */
108     private final String namespaceURI;
109
110     /**
111      * <p>local part of this <code>QName</code>.</p>
112      */
113     private final String localPart;
114
115     /**
116      * <p>prefix of this <code>QName</code>.</p>
117      */
118     private String prefix;
119
120     /**
121      * <p><code>String</code> representation of this <code>QName</code>.</p>
122      */
123     private transient String qNameAsString;
124
125     /**
126      * <p><code>QName</code> constructor specifying the Namespace URI
127      * and local part.</p>
128      *
129      * <p>If the Namespace URI is <code>null</code>, it is set to
130      * {@link javax.xml.XMLConstants#NULL_NS_URI
131      * XMLConstants.NULL_NS_URI}.  This value represents no
132      * explicitly defined Namespace as defined by the <a
133      * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
134      * in XML</a> specification.  This action preserves compatible
135      * behavior with QName 1.0.  Explicitly providing the {@link
136      * javax.xml.XMLConstants#NULL_NS_URI
137      * XMLConstants.NULL_NS_URI} value is the preferred coding
138      * style.</p>
139      *
140      * <p>If the local part is <code>null</code> an
141      * <code>IllegalArgumentException</code> is thrown.
142      * A local part of "" is allowed to preserve
143      * compatible behavior with QName 1.0. </p>
144      *
145      * <p>When using this constructor, the prefix is set to {@link
146      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
147      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
148      *
149      * <p>The Namespace URI is not validated as a
150      * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
151      * The local part is not validated as a
152      * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
153      * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces
154      * in XML</a>.</p>
155      *
156      * @param namespaceURI Namespace URI of the <code>QName</code>
157      * @param localPart    local part of the <code>QName</code>
158      *
159      * @see #QName(String namespaceURI, String localPart, String
160      * prefix) QName(String namespaceURI, String localPart, String
161      * prefix)
162      */
163     public QName(final String namespaceURI, final String localPart) {
164         this(namespaceURI, localPart, XMLConstants.DEFAULT_NS_PREFIX);
165     }
166
167     /**
168      * <p><code>QName</code> constructor specifying the Namespace URI,
169      * local part and prefix.</p>
170      *
171      * <p>If the Namespace URI is <code>null</code>, it is set to
172      * {@link javax.xml.XMLConstants#NULL_NS_URI
173      * XMLConstants.NULL_NS_URI}.  This value represents no
174      * explicitly defined Namespace as defined by the <a
175      * href="http://www.w3.org/TR/REC-xml-names/#ns-qualnames">Namespaces
176      * in XML</a> specification.  This action preserves compatible
177      * behavior with QName 1.0.  Explicitly providing the {@link
178      * javax.xml.XMLConstants#NULL_NS_URI
179      * XMLConstants.NULL_NS_URI} value is the preferred coding
180      * style.</p>
181      *
182      * <p>If the local part is <code>null</code> an
183      * <code>IllegalArgumentException</code> is thrown.
184      * A local part of "" is allowed to preserve
185      * compatible behavior with QName 1.0. </p>
186      *
187      * <p>If the prefix is <code>null</code>, an
188      * <code>IllegalArgumentException</code> is thrown.  Use {@link
189      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
190      * XMLConstants.DEFAULT_NS_PREFIX} to explicitly indicate that no
191      * prefix is present or the prefix is not relevant.</p>
192      *
193      * <p>The Namespace URI is not validated as a
194      * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
195      * The local part and prefix are not validated as a
196      * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
197      * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces
198      * in XML</a>.</p>
199      *
200      * @param namespaceURI Namespace URI of the <code>QName</code>
201      * @param localPart    local part of the <code>QName</code>
202      * @param prefix       prefix of the <code>QName</code>
203      */
204     public QName(String namespaceURI, String localPart, String prefix) {
205
206         // map null Namespace URI to default to preserve compatibility with QName 1.0
207         if (namespaceURI == null) {
208             this.namespaceURI = XMLConstants.NULL_NS_URI;
209         } else {
210             this.namespaceURI = namespaceURI;
211         }
212
213         // local part is required.  "" is allowed to preserve compatibility with QName 1.0
214         if (localPart == null) {
215             throw new IllegalArgumentException("local part cannot be \"null\" when creating a QName");
216         }
217         this.localPart = localPart;
218
219         // prefix is required
220         if (prefix == null) {
221             throw new IllegalArgumentException("prefix cannot be \"null\" when creating a QName");
222         }
223         this.prefix = prefix;
224     }
225
226     /**
227      * <p><code>QName</code> constructor specifying the local part.</p>
228      *
229      * <p>If the local part is <code>null</code> an
230      * <code>IllegalArgumentException</code> is thrown.
231      * A local part of "" is allowed to preserve
232      * compatible behavior with QName 1.0. </p>
233      *
234      * <p>When using this constructor, the Namespace URI is set to
235      * {@link javax.xml.XMLConstants#NULL_NS_URI
236      * XMLConstants.NULL_NS_URI} and the prefix is set to {@link
237      * javax.xml.XMLConstants#DEFAULT_NS_PREFIX
238      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
239      *
240      * <p><em>In an XML context, all Element and Attribute names exist
241      * in the context of a Namespace.  Making this explicit during the
242      * construction of a <code>QName</code> helps prevent hard to
243      * diagnosis XML validity errors.  The constructors {@link
244      * #QName(String namespaceURI, String localPart) QName(String
245      * namespaceURI, String localPart)} and
246      * {@link #QName(String namespaceURI, String localPart, String prefix)}
247      * are preferred.</em></p>
248      *
249      * <p>The local part is not validated as a
250      * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
251      * as specified in <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces
252      * in XML</a>.</p>
253      *
254      * @param localPart local part of the <code>QName</code>
255      * @see #QName(String namespaceURI, String localPart) QName(String
256      * namespaceURI, String localPart)
257      * @see #QName(String namespaceURI, String localPart, String
258      * prefix) QName(String namespaceURI, String localPart, String
259      * prefix)
260      */
261     public QName(String localPart) {
262         this(
263             XMLConstants.NULL_NS_URI,
264             localPart,
265             XMLConstants.DEFAULT_NS_PREFIX);
266     }
267
268     /**
269      * <p>Get the Namespace URI of this <code>QName</code>.</p>
270      *
271      * @return Namespace URI of this <code>QName</code>
272      */
273     public String getNamespaceURI() {
274         return namespaceURI;
275     }
276
277     /**
278      * <p>Get the local part of this <code>QName</code>.</p>
279      *
280      *  @return local part of this <code>QName</code>
281      */
282     public String getLocalPart() {
283         return localPart;
284     }
285
286     /**
287      * <p>Get the prefix of this <code>QName</code>.</p>
288      *
289      * <p>The prefix assigned to a <code>QName</code> might
290      * <strong><em>NOT</em></strong> be valid in a different
291      * context. For example, a <code>QName</code> may be assigned a
292      * prefix in the context of parsing a document but that prefix may
293      * be invalid in the context of a different document.</p>
294      *
295      *  @return prefix of this <code>QName</code>
296      */
297     public String getPrefix() {
298         return prefix;
299     }
300
301     /**
302      * <p>Test this <code>QName</code> for equality with another
303      * <code>Object</code>.</p>
304      *
305      * <p>If the <code>Object</code> to be tested is not a
306      * <code>QName</code> or is <code>null</code>, then this method
307      * returns <code>false</code>.</p>
308      *
309      * <p>Two <code>QName</code>s are considered equal if and only if
310      * both the Namespace URI and local part are equal. This method
311      * uses <code>String.equals()</code> to check equality of the
312      * Namespace URI and local part. The prefix is
313      * <strong><em>NOT</em></strong> used to determine equality.</p>
314      *
315      * <p>This method satisfies the general contract of {@link
316      * java.lang.Object#equals(Object) Object.equals(Object)}</p>
317      *
318      * @param objectToTest the <code>Object</code> to test for
319      * equality with this <code>QName</code>
320      * @return <code>true</code> if the given <code>Object</code> is
321      * equal to this <code>QName</code> else <code>false</code>
322      */
323     public final boolean equals(Object objectToTest) {
324         // Is this the same object?
325         if (objectToTest == this) {
326             return true;
327         }
328         // Is this a QName?
329         if (objectToTest instanceof QName) {
330             QName qName = (QName) objectToTest;
331             return localPart.equals(qName.localPart) && namespaceURI.equals(qName.namespaceURI);
332         }
333         return false;
334     }
335
336     /**
337      * <p>Generate the hash code for this <code>QName</code>.</p>
338      *
339      * <p>The hash code is calculated using both the Namespace URI and
340      * the local part of the <code>QName</code>.  The prefix is
341      * <strong><em>NOT</em></strong> used to calculate the hash
342      * code.</p>
343      *
344      * <p>This method satisfies the general contract of {@link
345      * java.lang.Object#hashCode() Object.hashCode()}.</p>
346      *
347      * @return hash code for this <code>QName</code> <code>Object</code>
348      */
349     public final int hashCode() {
350         return namespaceURI.hashCode() ^ localPart.hashCode();
351     }
352
353     /**
354      * <p><code>String</code> representation of this
355      * <code>QName</code>.</p>
356      *
357      * <p>The commonly accepted way of representing a <code>QName</code>
358      * as a <code>String</code> was <a href="http://jclark.com/xml/xmlns.htm">defined</a>
359      * by James Clark.  Although this is not a <em>standard</em>
360      * specification, it is in common use,  e.g. {@link javax.xml.transform.Transformer#setParameter(String name, Object value)}.
361      * This implementation represents a <code>QName</code> as:
362      * "{" + Namespace URI + "}" + local part.  If the Namespace URI
363      * <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the
364      * local part is returned.  An appropriate use of this method is
365      * for debugging or logging for human consumption.</p>
366      *
367      * <p>Note the prefix value is <strong><em>NOT</em></strong>
368      * returned as part of the <code>String</code> representation.</p>
369      *
370      * <p>This method satisfies the general contract of {@link
371      * java.lang.Object#toString() Object.toString()}.</p>
372      *
373      * @return <code>String</code> representation of this <code>QName</code>
374      */
375     public String toString() {
376         String _qNameAsString = qNameAsString;
377         if (_qNameAsString == null) {
378             final int nsLength = namespaceURI.length();
379             if (nsLength == 0) {
380                 _qNameAsString = localPart;
381             }
382             else {
383                 StringBuilder buffer = new StringBuilder(nsLength + localPart.length() + 2);
384                 buffer.append('{');
385                 buffer.append(namespaceURI);
386                 buffer.append('}');
387                 buffer.append(localPart);
388                 _qNameAsString = buffer.toString();
389             }
390             qNameAsString = _qNameAsString;
391         }
392         return _qNameAsString;
393     }
394
395     /**
396      * <p><code>QName</code> derived from parsing the formatted
397      * <code>String</code>.</p>
398      *
399      * <p>If the <code>String</code> is <code>null</code> or does not conform to
400      * {@link #toString() QName.toString()} formatting, an
401      * <code>IllegalArgumentException</code> is thrown.</p>
402      *
403      * <p><em>The <code>String</code> <strong>MUST</strong> be in the
404      * form returned by {@link #toString() QName.toString()}.</em></p>
405      *
406      * <p>The commonly accepted way of representing a <code>QName</code>
407      * as a <code>String</code> was <a href="http://jclark.com/xml/xmlns.htm">defined</a>
408      * by James Clark.  Although this is not a <em>standard</em>
409      * specification, it is in common use,  e.g. {@link javax.xml.transform.Transformer#setParameter(String name, Object value)}.
410      * This implementation parses a <code>String</code> formatted
411      * as: "{" + Namespace URI + "}" + local part.  If the Namespace
412      * URI <code>.equals(XMLConstants.NULL_NS_URI)</code>, only the
413      * local part should be provided.</p>
414      *
415      * <p>The prefix value <strong><em>CANNOT</em></strong> be
416      * represented in the <code>String</code> and will be set to
417      * {@link javax.xml.XMLConstants#DEFAULT_NS_PREFIX
418      * XMLConstants.DEFAULT_NS_PREFIX}.</p>
419      *
420      * <p>This method does not do full validation of the resulting
421      * <code>QName</code>.
422      * <p>The Namespace URI is not validated as a
423      * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI reference</a>.
424      * The local part is not validated as a
425      * <a href="http://www.w3.org/TR/REC-xml-names/#NT-NCName">NCName</a>
426      * as specified in
427      * <a href="http://www.w3.org/TR/REC-xml-names/">Namespaces in XML</a>.</p>
428      *
429      * @param qNameAsString <code>String</code> representation
430      * of the <code>QName</code>
431      * @return <code>QName</code> corresponding to the given <code>String</code>
432      * @see #toString() QName.toString()
433      */
434     public static QName valueOf(String qNameAsString) {
435
436         // null is not valid
437         if (qNameAsString == null) {
438             throw new IllegalArgumentException("cannot create QName from \"null\" or \"\" String");
439         }
440
441         // "" local part is valid to preserve compatible behavior with QName 1.0
442         if (qNameAsString.length() == 0) {
443             return new QName(
444                 XMLConstants.NULL_NS_URI,
445                 qNameAsString,
446                 XMLConstants.DEFAULT_NS_PREFIX);
447         }
448
449         // local part only?
450         if (qNameAsString.charAt(0) != '{') {
451             return new QName(
452                 XMLConstants.NULL_NS_URI,
453                 qNameAsString,
454                 XMLConstants.DEFAULT_NS_PREFIX);
455         }
456
457         // Namespace URI improperly specified?
458         if (qNameAsString.startsWith("{" + XMLConstants.NULL_NS_URI + "}")) {
459             throw new IllegalArgumentException(
460                 "Namespace URI .equals(XMLConstants.NULL_NS_URI), "
461                 + ".equals(\"" + XMLConstants.NULL_NS_URI + "\"), "
462                 + "only the local part, "
463                 + "\"" + qNameAsString.substring(2 + XMLConstants.NULL_NS_URI.length()) + "\", "
464                 + "should be provided.");
465         }
466
467         // Namespace URI and local part specified
468         int endOfNamespaceURI = qNameAsString.indexOf('}');
469         if (endOfNamespaceURI == -1) {
470             throw new IllegalArgumentException(
471                 "cannot create QName from \""
472                     + qNameAsString
473                     + "\", missing closing \"}\"");
474         }
475         return new QName(
476             qNameAsString.substring(1, endOfNamespaceURI),
477             qNameAsString.substring(endOfNamespaceURI + 1),
478             XMLConstants.DEFAULT_NS_PREFIX);
479     }
480
481     /*
482      * For old versions of QName which didn't have a prefix field,
483      * <code>ObjectInputStream.defaultReadObject()</code> will initialize
484      * the prefix to <code>null</code> instead of the empty string. This
485      * method fixes up the prefix field if it didn't exist in the serialized
486      * object.
487      */
488     private void readObject(ObjectInputStream in)
489         throws IOException, ClassNotFoundException {
490         in.defaultReadObject();
491         if (prefix == null) {
492             prefix = XMLConstants.DEFAULT_NS_PREFIX;
493         }
494     }
495 }