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 }