KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xml > utils > QName


1 /*
2  * Copyright 1999-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 /*
17  * $Id: QName.java,v 1.15 2004/02/17 04:21:14 minchau Exp $
18  */

19 package org.apache.xml.utils;
20
21 import java.util.Stack JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23
24 import org.apache.xml.res.XMLErrorResources;
25 import org.apache.xml.res.XMLMessages;
26
27 import org.w3c.dom.Element JavaDoc;
28
29 /**
30  * Class to represent a qualified name: "The name of an internal XSLT object,
31  * specifically a named template (see [7 Named Templates]), a mode (see [6.7 Modes]),
32  * an attribute set (see [8.1.4 Named Attribute Sets]), a key (see [14.2 Keys]),
33  * a locale (see [14.3 Number Formatting]), a variable or a parameter (see
34  * [12 Variables and Parameters]) is specified as a QName. If it has a prefix,
35  * then the prefix is expanded into a URI reference using the namespace declarations
36  * in effect on the attribute in which the name occurs. The expanded name
37  * consisting of the local part of the name and the possibly null URI reference
38  * is used as the name of the object. The default namespace is not used for
39  * unprefixed names."
40  * @xsl.usage general
41  */

42 public class QName implements java.io.Serializable JavaDoc
43 {
44
45   /**
46    * The local name.
47    * @serial
48    */

49   protected String JavaDoc _localName;
50
51   /**
52    * The namespace URI.
53    * @serial
54    */

55   protected String JavaDoc _namespaceURI;
56
57   /**
58    * The namespace prefix.
59    * @serial
60    */

61   protected String JavaDoc _prefix;
62
63   /**
64    * The XML namespace.
65    */

66   public static final String JavaDoc S_XMLNAMESPACEURI =
67     "http://www.w3.org/XML/1998/namespace";
68
69   /**
70    * The cached hashcode, which is calculated at construction time.
71    * @serial
72    */

73   private int m_hashCode;
74
75   /**
76    * Constructs an empty QName.
77    * 20001019: Try making this public, to support Serializable? -- JKESS
78    */

79   public QName(){}
80
81   /**
82    * Constructs a new QName with the specified namespace URI and
83    * local name.
84    *
85    * @param namespaceURI The namespace URI if known, or null
86    * @param localName The local name
87    */

88   public QName(String JavaDoc namespaceURI, String JavaDoc localName)
89   {
90     this(namespaceURI, localName, false);
91   }
92
93   /**
94    * Constructs a new QName with the specified namespace URI and
95    * local name.
96    *
97    * @param namespaceURI The namespace URI if known, or null
98    * @param localName The local name
99    * @param validate If true the new QName will be validated and an IllegalArgumentException will
100    * be thrown if it is invalid.
101    */

102   public QName(String JavaDoc namespaceURI, String JavaDoc localName, boolean validate)
103   {
104
105     // This check was already here. So, for now, I will not add it to the validation
106
// that is done when the validate parameter is true.
107
if (localName == null)
108       throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
109             XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
110

111     if (validate)
112     {
113         if (!XMLChar.isValidNCName(localName))
114         {
115             throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
116             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
117
}
118     }
119     
120     _namespaceURI = namespaceURI;
121     _localName = localName;
122     m_hashCode = toString().hashCode();
123   }
124   
125   /**
126    * Constructs a new QName with the specified namespace URI, prefix
127    * and local name.
128    *
129    * @param namespaceURI The namespace URI if known, or null
130    * @param prefix The namespace prefix is known, or null
131    * @param localName The local name
132    *
133    */

134   public QName(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName)
135   {
136      this(namespaceURI, prefix, localName, false);
137   }
138   
139  /**
140    * Constructs a new QName with the specified namespace URI, prefix
141    * and local name.
142    *
143    * @param namespaceURI The namespace URI if known, or null
144    * @param prefix The namespace prefix is known, or null
145    * @param localName The local name
146    * @param validate If true the new QName will be validated and an IllegalArgumentException will
147    * be thrown if it is invalid.
148    */

149   public QName(String JavaDoc namespaceURI, String JavaDoc prefix, String JavaDoc localName, boolean validate)
150   {
151
152     // This check was already here. So, for now, I will not add it to the validation
153
// that is done when the validate parameter is true.
154
if (localName == null)
155       throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
156             XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
157

158     if (validate)
159     {
160         if (!XMLChar.isValidNCName(localName))
161         {
162             throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
163             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
164
}
165
166         if ((null != prefix) && (!XMLChar.isValidNCName(prefix)))
167         {
168             throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
169             XMLErrorResources.ER_ARG_PREFIX_INVALID,null )); //"Argument 'prefix' not a valid NCName");
170
}
171
172     }
173     _namespaceURI = namespaceURI;
174     _prefix = prefix;
175     _localName = localName;
176     m_hashCode = toString().hashCode();
177   }
178
179   /**
180    * Construct a QName from a string, without namespace resolution. Good
181    * for a few odd cases.
182    *
183    * @param localName Local part of qualified name
184    *
185    */

186   public QName(String JavaDoc localName)
187   {
188     this(localName, false);
189   }
190   
191   /**
192    * Construct a QName from a string, without namespace resolution. Good
193    * for a few odd cases.
194    *
195    * @param localName Local part of qualified name
196    * @param validate If true the new QName will be validated and an IllegalArgumentException will
197    * be thrown if it is invalid.
198    */

199   public QName(String JavaDoc localName, boolean validate)
200   {
201
202     // This check was already here. So, for now, I will not add it to the validation
203
// that is done when the validate parameter is true.
204
if (localName == null)
205       throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
206             XMLErrorResources.ER_ARG_LOCALNAME_NULL, null)); //"Argument 'localName' is null");
207

208     if (validate)
209     {
210         if (!XMLChar.isValidNCName(localName))
211         {
212             throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
213             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
214
}
215     }
216     _namespaceURI = null;
217     _localName = localName;
218     m_hashCode = toString().hashCode();
219   }
220
221   /**
222    * Construct a QName from a string, resolving the prefix
223    * using the given namespace stack. The default namespace is
224    * not resolved.
225    *
226    * @param qname Qualified name to resolve
227    * @param namespaces Namespace stack to use to resolve namespace
228    */

229   public QName(String JavaDoc qname, Stack JavaDoc namespaces)
230   {
231     this(qname, namespaces, false);
232   }
233
234   /**
235    * Construct a QName from a string, resolving the prefix
236    * using the given namespace stack. The default namespace is
237    * not resolved.
238    *
239    * @param qname Qualified name to resolve
240    * @param namespaces Namespace stack to use to resolve namespace
241    * @param validate If true the new QName will be validated and an IllegalArgumentException will
242    * be thrown if it is invalid.
243    */

244   public QName(String JavaDoc qname, Stack JavaDoc namespaces, boolean validate)
245   {
246
247     String JavaDoc namespace = null;
248     String JavaDoc prefix = null;
249     int indexOfNSSep = qname.indexOf(':');
250
251     if (indexOfNSSep > 0)
252     {
253       prefix = qname.substring(0, indexOfNSSep);
254
255       if (prefix.equals("xml"))
256       {
257         namespace = S_XMLNAMESPACEURI;
258       }
259       // Do we want this?
260
else if (prefix.equals("xmlns"))
261       {
262         return;
263       }
264       else
265       {
266         int depth = namespaces.size();
267
268         for (int i = depth - 1; i >= 0; i--)
269         {
270           NameSpace ns = (NameSpace) namespaces.elementAt(i);
271
272           while (null != ns)
273           {
274             if ((null != ns.m_prefix) && prefix.equals(ns.m_prefix))
275             {
276               namespace = ns.m_uri;
277               i = -1;
278
279               break;
280             }
281
282             ns = ns.m_next;
283           }
284         }
285       }
286
287       if (null == namespace)
288       {
289         throw new RuntimeException JavaDoc(
290           XMLMessages.createXMLMessage(
291             XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
292             new Object JavaDoc[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
293
}
294     }
295
296     _localName = (indexOfNSSep < 0)
297                  ? qname : qname.substring(indexOfNSSep + 1);
298                  
299     if (validate)
300     {
301         if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
302         {
303            throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
304             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
305
}
306     }
307     _namespaceURI = namespace;
308     _prefix = prefix;
309     m_hashCode = toString().hashCode();
310   }
311
312   /**
313    * Construct a QName from a string, resolving the prefix
314    * using the given namespace context and prefix resolver.
315    * The default namespace is not resolved.
316    *
317    * @param qname Qualified name to resolve
318    * @param namespaceContext Namespace Context to use
319    * @param resolver Prefix resolver for this context
320    */

321   public QName(String JavaDoc qname, Element JavaDoc namespaceContext,
322                PrefixResolver resolver)
323   {
324       this(qname, namespaceContext, resolver, false);
325   }
326
327   /**
328    * Construct a QName from a string, resolving the prefix
329    * using the given namespace context and prefix resolver.
330    * The default namespace is not resolved.
331    *
332    * @param qname Qualified name to resolve
333    * @param namespaceContext Namespace Context to use
334    * @param resolver Prefix resolver for this context
335    * @param validate If true the new QName will be validated and an IllegalArgumentException will
336    * be thrown if it is invalid.
337    */

338   public QName(String JavaDoc qname, Element JavaDoc namespaceContext,
339                PrefixResolver resolver, boolean validate)
340   {
341
342     _namespaceURI = null;
343
344     int indexOfNSSep = qname.indexOf(':');
345
346     if (indexOfNSSep > 0)
347     {
348       if (null != namespaceContext)
349       {
350         String JavaDoc prefix = qname.substring(0, indexOfNSSep);
351
352         _prefix = prefix;
353
354         if (prefix.equals("xml"))
355         {
356           _namespaceURI = S_XMLNAMESPACEURI;
357         }
358         
359         // Do we want this?
360
else if (prefix.equals("xmlns"))
361         {
362           return;
363         }
364         else
365         {
366           _namespaceURI = resolver.getNamespaceForPrefix(prefix,
367                   namespaceContext);
368         }
369
370         if (null == _namespaceURI)
371         {
372           throw new RuntimeException JavaDoc(
373             XMLMessages.createXMLMessage(
374               XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
375               new Object JavaDoc[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
376
}
377       }
378       else
379       {
380
381         // TODO: error or warning...
382
}
383     }
384
385     _localName = (indexOfNSSep < 0)
386                  ? qname : qname.substring(indexOfNSSep + 1);
387
388     if (validate)
389     {
390         if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
391         {
392            throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
393             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
394
}
395     }
396                  
397     m_hashCode = toString().hashCode();
398   }
399
400
401   /**
402    * Construct a QName from a string, resolving the prefix
403    * using the given namespace stack. The default namespace is
404    * not resolved.
405    *
406    * @param qname Qualified name to resolve
407    * @param resolver Prefix resolver for this context
408    */

409   public QName(String JavaDoc qname, PrefixResolver resolver)
410   {
411     this(qname, resolver, false);
412   }
413
414   /**
415    * Construct a QName from a string, resolving the prefix
416    * using the given namespace stack. The default namespace is
417    * not resolved.
418    *
419    * @param qname Qualified name to resolve
420    * @param resolver Prefix resolver for this context
421    * @param validate If true the new QName will be validated and an IllegalArgumentException will
422    * be thrown if it is invalid.
423    */

424   public QName(String JavaDoc qname, PrefixResolver resolver, boolean validate)
425   {
426
427     String JavaDoc prefix = null;
428     _namespaceURI = null;
429
430     int indexOfNSSep = qname.indexOf(':');
431
432     if (indexOfNSSep > 0)
433     {
434       prefix = qname.substring(0, indexOfNSSep);
435
436       if (prefix.equals("xml"))
437       {
438         _namespaceURI = S_XMLNAMESPACEURI;
439       }
440       else
441       {
442         _namespaceURI = resolver.getNamespaceForPrefix(prefix);
443       }
444
445       if (null == _namespaceURI)
446       {
447         throw new RuntimeException JavaDoc(
448           XMLMessages.createXMLMessage(
449             XMLErrorResources.ER_PREFIX_MUST_RESOLVE,
450             new Object JavaDoc[]{ prefix })); //"Prefix must resolve to a namespace: "+prefix);
451
}
452       _localName = qname.substring(indexOfNSSep + 1);
453     }
454     else if (indexOfNSSep == 0)
455     {
456       throw new RuntimeException JavaDoc(
457          XMLMessages.createXMLMessage(
458            XMLErrorResources.ER_NAME_CANT_START_WITH_COLON,
459            null));
460     }
461     else
462     {
463       _localName = qname;
464     }
465                  
466     if (validate)
467     {
468         if ((_localName == null) || (!XMLChar.isValidNCName(_localName)))
469         {
470            throw new IllegalArgumentException JavaDoc(XMLMessages.createXMLMessage(
471             XMLErrorResources.ER_ARG_LOCALNAME_INVALID,null )); //"Argument 'localName' not a valid NCName");
472
}
473     }
474
475               
476     m_hashCode = toString().hashCode();
477     _prefix = prefix;
478   }
479
480   /**
481    * Returns the namespace URI. Returns null if the namespace URI
482    * is not known.
483    *
484    * @return The namespace URI, or null
485    */

486   public String JavaDoc getNamespaceURI()
487   {
488     return _namespaceURI;
489   }
490
491   /**
492    * Returns the namespace prefix. Returns null if the namespace
493    * prefix is not known.
494    *
495    * @return The namespace prefix, or null
496    */

497   public String JavaDoc getPrefix()
498   {
499     return _prefix;
500   }
501
502   /**
503    * Returns the local part of the qualified name.
504    *
505    * @return The local part of the qualified name
506    */

507   public String JavaDoc getLocalName()
508   {
509     return _localName;
510   }
511
512   /**
513    * Return the string representation of the qualified name, using the
514    * prefix if available, or the '{ns}foo' notation if not. Performs
515    * string concatenation, so beware of performance issues.
516    *
517    * @return the string representation of the namespace
518    */

519   public String JavaDoc toString()
520   {
521
522     return _prefix != null
523            ? (_prefix + ":" + _localName)
524            : (_namespaceURI != null
525               ? ("{"+_namespaceURI + "}" + _localName) : _localName);
526   }
527   
528   /**
529    * Return the string representation of the qualified name using the
530    * the '{ns}foo' notation. Performs
531    * string concatenation, so beware of performance issues.
532    *
533    * @return the string representation of the namespace
534    */

535   public String JavaDoc toNamespacedString()
536   {
537
538     return (_namespaceURI != null
539               ? ("{"+_namespaceURI + "}" + _localName) : _localName);
540   }
541
542
543   /**
544    * Get the namespace of the qualified name.
545    *
546    * @return the namespace URI of the qualified name
547    */

548   public String JavaDoc getNamespace()
549   {
550     return getNamespaceURI();
551   }
552
553   /**
554    * Get the local part of the qualified name.
555    *
556    * @return the local part of the qualified name
557    */

558   public String JavaDoc getLocalPart()
559   {
560     return getLocalName();
561   }
562
563   /**
564    * Return the cached hashcode of the qualified name.
565    *
566    * @return the cached hashcode of the qualified name
567    */

568   public int hashCode()
569   {
570     return m_hashCode;
571   }
572
573   /**
574    * Override equals and agree that we're equal if
575    * the passed object is a string and it matches
576    * the name of the arg.
577    *
578    * @param ns Namespace URI to compare to
579    * @param localPart Local part of qualified name to compare to
580    *
581    * @return True if the local name and uri match
582    */

583   public boolean equals(String JavaDoc ns, String JavaDoc localPart)
584   {
585
586     String JavaDoc thisnamespace = getNamespaceURI();
587
588     return getLocalName().equals(localPart)
589            && (((null != thisnamespace) && (null != ns))
590                ? thisnamespace.equals(ns)
591                : ((null == thisnamespace) && (null == ns)));
592   }
593
594   /**
595    * Override equals and agree that we're equal if
596    * the passed object is a QName and it matches
597    * the name of the arg.
598    *
599    * @param qname Qualified name to compare to
600    *
601    * @return True if the qualified names are equal
602    */

603   public boolean equals(Object JavaDoc object)
604   {
605
606     if (object == this)
607       return true;
608
609     if (object instanceof QName) {
610       QName qname = (QName) object;
611       String JavaDoc thisnamespace = getNamespaceURI();
612       String JavaDoc thatnamespace = qname.getNamespaceURI();
613
614       return getLocalName().equals(qname.getLocalName())
615              && (((null != thisnamespace) && (null != thatnamespace))
616                  ? thisnamespace.equals(thatnamespace)
617                  : ((null == thisnamespace) && (null == thatnamespace)));
618     }
619     else
620       return false;
621   }
622
623   /**
624    * Given a string, create and return a QName object
625    *
626    *
627    * @param name String to use to create QName
628    *
629    * @return a QName object
630    */

631   public static QName getQNameFromString(String JavaDoc name)
632   {
633
634     StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(name, "{}", false);
635     QName qname;
636     String JavaDoc s1 = tokenizer.nextToken();
637     String JavaDoc s2 = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null;
638
639     if (null == s2)
640       qname = new QName(null, s1);
641     else
642       qname = new QName(s1, s2);
643
644     return qname;
645   }
646
647   /**
648    * This function tells if a raw attribute name is a
649    * xmlns attribute.
650    *
651    * @param attRawName Raw name of attribute
652    *
653    * @return True if the attribute starts with or is equal to xmlns
654    */

655   public static boolean isXMLNSDecl(String JavaDoc attRawName)
656   {
657
658     return (attRawName.startsWith("xmlns")
659             && (attRawName.equals("xmlns")
660                 || attRawName.startsWith("xmlns:")));
661   }
662
663   /**
664    * This function tells if a raw attribute name is a
665    * xmlns attribute.
666    *
667    * @param attRawName Raw name of attribute
668    *
669    * @return Prefix of attribute
670    */

671   public static String JavaDoc getPrefixFromXMLNSDecl(String JavaDoc attRawName)
672   {
673
674     int index = attRawName.indexOf(':');
675
676     return (index >= 0) ? attRawName.substring(index + 1) : "";
677   }
678
679   /**
680    * Returns the local name of the given node.
681    *
682    * @param qname Input name
683    *
684    * @return Local part of the name if prefixed, or the given name if not
685    */

686   public static String JavaDoc getLocalPart(String JavaDoc qname)
687   {
688
689     int index = qname.indexOf(':');
690
691     return (index < 0) ? qname : qname.substring(index + 1);
692   }
693
694   /**
695    * Returns the local name of the given node.
696    *
697    * @param qname Input name
698    *
699    * @return Prefix of name or empty string if none there
700    */

701   public static String JavaDoc getPrefixPart(String JavaDoc qname)
702   {
703
704     int index = qname.indexOf(':');
705
706     return (index >= 0) ? qname.substring(0, index) : "";
707   }
708 }
709
Popular Tags