1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 1999-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xerces.internal.dom; 22 23 import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; 24 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 25 import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; 26 import org.w3c.dom.DOMException; 27 28 /** 29 * AttrNSImpl inherits from AttrImpl and adds namespace support. 30 * <P> 31 * The qualified name is the node name, and we store localName which is also 32 * used in all queries. On the other hand we recompute the prefix when 33 * necessary. 34 * 35 * @xerces.internal 36 * 37 * @author Arnaud Le Hors, IBM 38 * @author Andy Clark, IBM 39 * @author Ralf Pfeiffer, IBM 40 */ 41 public class AttrNSImpl 42 extends AttrImpl { 43 44 // 45 // Constants 46 // 47 48 /** Serialization version. */ 49 static final long serialVersionUID = -781906615369795414L; 50 51 static final String xmlnsURI = "http://www.w3.org/2000/xmlns/"; 52 static final String xmlURI = "http://www.w3.org/XML/1998/namespace"; 53 54 // 55 // Data 56 // 57 58 /** DOM2: Namespace URI. */ 59 protected String namespaceURI; 60 61 /** DOM2: localName. */ 62 protected String localName; 63 64 /* 65 * Default constructor 66 */ 67 public AttrNSImpl(){} 68 69 /** 70 * DOM2: Constructor for Namespace implementation. 71 */ 72 protected AttrNSImpl(CoreDocumentImpl ownerDocument, 73 String namespaceURI, 74 String qualifiedName) { 75 76 super(ownerDocument, qualifiedName); 77 setName(namespaceURI, qualifiedName); 78 } 79 80 private void setName(String namespaceURI, String qname){ 81 CoreDocumentImpl ownerDocument = ownerDocument(); 82 String prefix; 83 // DOM Level 3: namespace URI is never empty string. 84 this.namespaceURI = namespaceURI; 85 if (namespaceURI !=null) { 86 this.namespaceURI = (namespaceURI.length() == 0)? null 87 : namespaceURI; 88 89 } 90 int colon1 = qname.indexOf(':'); 91 int colon2 = qname.lastIndexOf(':'); 92 ownerDocument.checkNamespaceWF(qname, colon1, colon2); 93 if (colon1 < 0) { 94 // there is no prefix 95 localName = qname; 96 if (ownerDocument.errorChecking) { 97 ownerDocument.checkQName(null, localName); 98 99 if (qname.equals("xmlns") && (namespaceURI == null 100 || !namespaceURI.equals(NamespaceContext.XMLNS_URI)) 101 || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI) 102 && !qname.equals("xmlns"))) { 103 String msg = 104 DOMMessageFormatter.formatMessage( 105 DOMMessageFormatter.DOM_DOMAIN, 106 "NAMESPACE_ERR", 107 null); 108 throw new DOMException(DOMException.NAMESPACE_ERR, msg); 109 } 110 } 111 } 112 else { 113 prefix = qname.substring(0, colon1); 114 localName = qname.substring(colon2+1); 115 ownerDocument.checkQName(prefix, localName); 116 ownerDocument.checkDOMNSErr(prefix, namespaceURI); 117 } 118 } 119 120 // when local name is known 121 public AttrNSImpl(CoreDocumentImpl ownerDocument, 122 String namespaceURI, 123 String qualifiedName, 124 String localName) { 125 super(ownerDocument, qualifiedName); 126 127 this.localName = localName; 128 this.namespaceURI = namespaceURI; 129 } 130 131 // for DeferredAttrImpl 132 protected AttrNSImpl(CoreDocumentImpl ownerDocument, 133 String value) { 134 super(ownerDocument, value); 135 } 136 137 // Support for DOM Level 3 renameNode method. 138 // Note: This only deals with part of the pb. It is expected to be 139 // called after the Attr has been detached for one thing. 140 // CoreDocumentImpl does all the work. 141 void rename(String namespaceURI, String qualifiedName) { 142 if (needsSyncData()) { 143 synchronizeData(); 144 } 145 this.name = qualifiedName; 146 setName(namespaceURI, qualifiedName); 147 } 148 149 /** 150 * NON-DOM: resets this node and sets specified values for the node 151 * 152 * @param ownerDocument 153 * @param namespaceURI 154 * @param qualifiedName 155 * @param localName 156 */ 157 public void setValues (CoreDocumentImpl ownerDocument, 158 String namespaceURI, 159 String qualifiedName, 160 String localName){ 161 162 super.textNode = null; 163 super.flags = 0; 164 isSpecified(true); 165 hasStringValue(true); 166 super.setOwnerDocument(ownerDocument); 167 this.localName = localName; 168 this.namespaceURI = namespaceURI; 169 super.name = qualifiedName; 170 super.value = null; 171 } 172 173 // 174 // DOM2: Namespace methods 175 // 176 177 /** 178 * Introduced in DOM Level 2. <p> 179 * 180 * The namespace URI of this node, or null if it is unspecified.<p> 181 * 182 * This is not a computed value that is the result of a namespace lookup 183 * based on an examination of the namespace declarations in scope. It is 184 * merely the namespace URI given at creation time.<p> 185 * 186 * For nodes created with a DOM Level 1 method, such as createElement 187 * from the Document interface, this is null. 188 * @since WD-DOM-Level-2-19990923 189 */ 190 public String getNamespaceURI() 191 { 192 if (needsSyncData()) { 193 synchronizeData(); 194 } 195 // REVIST: This code could/should be done at a lower-level, such that 196 // the namespaceURI is set properly upon creation. However, there still 197 // seems to be some DOM spec interpretation grey-area. 198 return namespaceURI; 199 } 200 201 /** 202 * Introduced in DOM Level 2. <p> 203 * 204 * The namespace prefix of this node, or null if it is unspecified. <p> 205 * 206 * For nodes created with a DOM Level 1 method, such as createElement 207 * from the Document interface, this is null. <p> 208 * 209 * @since WD-DOM-Level-2-19990923 210 */ 211 public String getPrefix() 212 { 213 if (needsSyncData()) { 214 synchronizeData(); 215 } 216 int index = name.indexOf(':'); 217 return index < 0 ? null : name.substring(0, index); 218 } 219 220 /** 221 * Introduced in DOM Level 2. <p> 222 * 223 * Note that setting this attribute changes the nodeName attribute, which 224 * holds the qualified name, as well as the tagName and name attributes of 225 * the Element and Attr interfaces, when applicable.<p> 226 * 227 * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified. 228 * 229 * @exception INVALID_CHARACTER_ERR 230 * Raised if the specified 231 * prefix contains an invalid character. 232 * @exception DOMException 233 * @since WD-DOM-Level-2-19990923 234 */ 235 public void setPrefix(String prefix) 236 throws DOMException 237 { 238 if (needsSyncData()) { 239 synchronizeData(); 240 } 241 if (ownerDocument().errorChecking) { 242 if (isReadOnly()) { 243 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null); 244 throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg); 245 } 246 if (prefix != null && prefix.length() != 0) { 247 248 if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument().isXML11Version())) { 249 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null); 250 throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg); 251 } 252 if (namespaceURI == null || prefix.indexOf(':') >=0) { 253 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null); 254 throw new DOMException(DOMException.NAMESPACE_ERR, msg); 255 256 } 257 if (prefix.equals("xmlns")) { 258 if (!namespaceURI.equals(xmlnsURI)){ 259 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null); 260 throw new DOMException(DOMException.NAMESPACE_ERR, msg); 261 } 262 } else if (prefix.equals("xml")) { 263 if (!namespaceURI.equals(xmlURI)) { 264 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null); 265 throw new DOMException(DOMException.NAMESPACE_ERR, msg); 266 } 267 }else if (name.equals("xmlns")) { 268 String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null); 269 throw new DOMException(DOMException.NAMESPACE_ERR, msg); 270 } 271 } 272 } 273 274 // update node name with new qualifiedName 275 if (prefix !=null && prefix.length() != 0) { 276 name = prefix + ":" + localName; 277 } 278 else { 279 name = localName; 280 } 281 } 282 283 /** 284 * Introduced in DOM Level 2. <p> 285 * 286 * Returns the local part of the qualified name of this node. 287 * @since WD-DOM-Level-2-19990923 288 */ 289 public String getLocalName() 290 { 291 if (needsSyncData()) { 292 synchronizeData(); 293 } 294 return localName; 295 } 296 297 298 /** 299 * @see org.w3c.dom.TypeInfo#getTypeName() 300 */ 301 public String getTypeName() { 302 if (type !=null){ 303 if (type instanceof XSSimpleTypeDecl){ 304 return ((XSSimpleTypeDecl)type).getName(); 305 } 306 return (String)type; 307 } 308 return null; 309 } 310 311 /** 312 * Introduced in DOM Level 3. <p> 313 * Checks if a type is derived from another by restriction. See: 314 * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom 315 * 316 * @param ancestorNS 317 * The namspace of the ancestor type declaration 318 * @param ancestorName 319 * The name of the ancestor type declaration 320 * @param type 321 * The reference type definition 322 * 323 * @return boolean True if the type is derived by restriciton for the 324 * reference type 325 */ 326 public boolean isDerivedFrom(String typeNamespaceArg, 327 String typeNameArg, 328 int derivationMethod) { 329 if (type != null) { 330 if (type instanceof XSSimpleTypeDecl) { 331 return ((XSSimpleTypeDecl) type).isDOMDerivedFrom( 332 typeNamespaceArg, typeNameArg, derivationMethod); 333 } 334 } 335 return false; 336 } 337 338 /** 339 * @see org.w3c.dom.TypeInfo#getTypeNamespace() 340 */ 341 public String getTypeNamespace() { 342 if (type !=null) { 343 if (type instanceof XSSimpleTypeDecl){ 344 return ((XSSimpleTypeDecl)type).getNamespace(); 345 } 346 return DTD_URI; 347 } 348 return null; 349 } 350 351 }