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

Save This Page
Home » xml-commons-external-1.4.01-src » javax » xml » namespace » [javadoc | source]