001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package javax.xml.namespace; 021 022 import java.io.IOException; 023 import java.io.ObjectInputStream; 024 import java.io.Serializable; 025 026 /** 027 * <code>QName</code> class represents the value of a qualified name 028 * as specified in <a href="http://www.w3.org/TR/xmlschema-2/#QName">XML 029 * Schema Part2: Datatypes specification</a>. 030 * <p> 031 * The value of a QName contains a <b>namespaceURI</b>, a <b>localPart</b> and a 032 * <b>prefix</b>. The localPart provides the local part of the qualified name. 033 * The namespaceURI is a URI reference identifying the namespace. 034 * 035 * @version 1.1 036 */ 037 public class QName implements Serializable { 038 039 /** Comment/shared empty <code>String</code>. */ 040 private static final String emptyString = "".intern(); 041 042 private String namespaceURI; 043 044 private String localPart; 045 046 private String prefix; 047 048 /** 049 * Constructor for the QName. 050 * 051 * @param localPart local part of the QName 052 */ 053 public QName(String localPart) { 054 this(emptyString, localPart, emptyString); 055 } 056 057 /** 058 * Constructor for the QName. 059 * 060 * @param namespaceURI namespace URI for the QName 061 * @param localPart local part of the QName. 062 */ 063 public QName(String namespaceURI, String localPart) { 064 this(namespaceURI, localPart, emptyString); 065 } 066 067 /** 068 * Constructor for the QName. 069 * 070 * @param namespaceURI Namespace URI for the QName 071 * @param localPart Local part of the QName. 072 * @param prefix Prefix of the QName. 073 */ 074 public QName(String namespaceURI, String localPart, String prefix) { 075 this.namespaceURI = (namespaceURI == null) 076 ? emptyString 077 : namespaceURI.intern(); 078 if (localPart == null) { 079 throw new IllegalArgumentException("invalid QName local part"); 080 } else { 081 this.localPart = localPart.intern(); 082 } 083 084 if (prefix == null) { 085 throw new IllegalArgumentException("invalid QName prefix"); 086 } else { 087 this.prefix = prefix.intern(); 088 } 089 } 090 091 /** 092 * Gets the namespace URI for this QName. 093 * 094 * @return namespace URI 095 */ 096 public String getNamespaceURI() { 097 return namespaceURI; 098 } 099 100 /** 101 * Gets the local part for this QName. 102 * 103 * @return the local part 104 */ 105 public String getLocalPart() { 106 return localPart; 107 } 108 109 /** 110 * Gets the prefix for this QName. 111 * 112 * @return the prefix 113 */ 114 public String getPrefix() { 115 return prefix; 116 } 117 118 /** 119 * Returns a string representation of this QName. 120 * 121 * @return a string representation of the QName 122 */ 123 public String toString() { 124 125 return ((namespaceURI == emptyString) 126 ? localPart 127 : '{' + namespaceURI + '}' + localPart); 128 } 129 130 /** 131 * Tests this QName for equality with another object. 132 * <p> 133 * If the given object is not a QName or is null then this method 134 * returns <tt>false</tt>. 135 * <p> 136 * For two QNames to be considered equal requires that both 137 * localPart and namespaceURI must be equal. This method uses 138 * <code>String.equals</code> to check equality of localPart 139 * and namespaceURI. Any class that extends QName is required 140 * to satisfy this equality contract. 141 * <p> 142 * This method satisfies the general contract of the <code>Object.equals</code> method. 143 * 144 * @param obj the reference object with which to compare 145 * 146 * @return <code>true</code> if the given object is identical to this 147 * QName: <code>false</code> otherwise. 148 */ 149 public final boolean equals(Object obj) { 150 151 if (obj == this) { 152 return true; 153 } 154 155 if (!(obj instanceof QName)) { 156 return false; 157 } 158 159 if ((namespaceURI == ((QName) obj).namespaceURI) 160 && (localPart == ((QName) obj).localPart)) { 161 return true; 162 } 163 164 return false; 165 } 166 167 /** 168 * Returns a QName holding the value of the specified String. 169 * <p> 170 * The string must be in the form returned by the QName.toString() 171 * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}" 172 * part being optional. 173 * <p> 174 * This method doesn't do a full validation of the resulting QName. 175 * In particular, it doesn't check that the resulting namespace URI 176 * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting 177 * local part is a legal NCName per the XML Namespaces specification. 178 * 179 * @param s the string to be parsed 180 * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName 181 * @return QName corresponding to the given String 182 */ 183 public static QName valueOf(String s) { 184 185 if ((s == null) || s.equals("")) { 186 throw new IllegalArgumentException("invalid QName literal"); 187 } 188 189 if (s.charAt(0) == '{') { 190 int i = s.indexOf('}'); 191 192 if (i == -1) { 193 throw new IllegalArgumentException("invalid QName literal"); 194 } 195 196 if (i == s.length() - 1) { 197 throw new IllegalArgumentException("invalid QName literal"); 198 } else { 199 return new QName(s.substring(1, i), s.substring(i + 1)); 200 } 201 } else { 202 return new QName(s); 203 } 204 } 205 206 /** 207 * Returns a hash code value for this QName object. The hash code 208 * is based on both the localPart and namespaceURI parts of the 209 * QName. This method satisfies the general contract of the 210 * <code>Object.hashCode</code> method. 211 * 212 * @return a hash code value for this Qname object 213 */ 214 public final int hashCode() { 215 return namespaceURI.hashCode() ^ localPart.hashCode(); 216 } 217 218 /** 219 * Ensure that deserialization properly interns the results. 220 * @param in the ObjectInputStream to be read 221 * @throws IOException if there was a failure in the object input stream 222 * @throws ClassNotFoundException if the class of any sub-objects could 223 * not be found 224 */ 225 private void readObject(ObjectInputStream in) throws 226 IOException, ClassNotFoundException { 227 in.defaultReadObject(); 228 229 namespaceURI = namespaceURI.intern(); 230 localPart = localPart.intern(); 231 prefix = prefix.intern(); 232 } 233 }