content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 1999-2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package jaxp.sun.org.apache.xerces.internal.dom;
  
  import jaxp.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
  import jaxp.sun.org.apache.xerces.internal.xni.NamespaceContext;
  
  import org.w3c.dom.DOMException;
  
  /**
   * AttrNSImpl inherits from AttrImpl and adds namespace support.
   * <P>
   * The qualified name is the node name, and we store localName which is also
   * used in all queries. On the other hand we recompute the prefix when
   * necessary.
   *
   * @xerces.internal
   *
   * @author Arnaud  Le Hors, IBM
   * @author Andy Clark, IBM
   * @author Ralf Pfeiffer, IBM
   * @version $Id: AttrNSImpl.java,v 1.7 2010-11-01 04:39:37 joehw Exp $
   */
  public class AttrNSImpl
      extends AttrImpl {
  
      //
      // Constants
      //
  
      /** Serialization version. */
      static final long serialVersionUID = -781906615369795414L;
  
      static final String xmlnsURI = "http://www.w3.org/2000/xmlns/";
      static final String xmlURI = "http://www.w3.org/XML/1998/namespace";
  
      //
      // Data
      //
  
      /** DOM2: Namespace URI. */
      protected String namespaceURI;
  
      /** DOM2: localName. */
      protected String localName;
  
      /*
       * Default constructor
       */
      public AttrNSImpl(){}
  
     /**
       * DOM2: Constructor for Namespace implementation.
       */
      protected AttrNSImpl(CoreDocumentImpl ownerDocument,
                           String namespaceURI,
                           String qualifiedName) {
  
          super(ownerDocument, qualifiedName);
          setName(namespaceURI, qualifiedName);
      }
  
      private void setName(String namespaceURI, String qname){
          CoreDocumentImpl ownerDocument = ownerDocument();
          String prefix;
          // DOM Level 3: namespace URI is never empty string.
          this.namespaceURI = namespaceURI;
          if (namespaceURI !=null) {
              this.namespaceURI = (namespaceURI.length() == 0)? null
                      : namespaceURI;
  
          }
          int colon1 = qname.indexOf(':');
          int colon2 = qname.lastIndexOf(':');
          ownerDocument.checkNamespaceWF(qname, colon1, colon2);
          if (colon1 < 0) {
              // there is no prefix
              localName = qname;
              if (ownerDocument.errorChecking) {
                  ownerDocument.checkQName(null, localName);
  
                  if (qname.equals("xmlns") && (namespaceURI == null
                      || !namespaceURI.equals(NamespaceContext.XMLNS_URI))
                      || (namespaceURI!=null && namespaceURI.equals(NamespaceContext.XMLNS_URI)
                      && !qname.equals("xmlns"))) {
                      String msg =
                          DOMMessageFormatter.formatMessage(
                                  DOMMessageFormatter.DOM_DOMAIN,
                                  "NAMESPACE_ERR",
                                  null);
                      throw new DOMException(DOMException.NAMESPACE_ERR, msg);
                  }
              }
          }
          else {
              prefix = qname.substring(0, colon1);
              localName = qname.substring(colon2+1);
              ownerDocument.checkQName(prefix, localName);
              ownerDocument.checkDOMNSErr(prefix, namespaceURI);
          }
      }
  
      // when local name is known
      public AttrNSImpl(CoreDocumentImpl ownerDocument,
                           String namespaceURI,
                           String qualifiedName,
                           String localName) {
          super(ownerDocument, qualifiedName);
  
          this.localName = localName;
          this.namespaceURI = namespaceURI;
      }
  
      // for DeferredAttrImpl
      protected AttrNSImpl(CoreDocumentImpl ownerDocument,
                           String value) {
          super(ownerDocument, value);
      }
  
      // Support for DOM Level 3 renameNode method.
      // Note: This only deals with part of the pb. It is expected to be
      // called after the Attr has been detached for one thing.
      // CoreDocumentImpl does all the work.
      void rename(String namespaceURI, String qualifiedName) {
          if (needsSyncData()) {
              synchronizeData();
          }
                  this.name = qualifiedName;
          setName(namespaceURI, qualifiedName);
      }
  
      /**
       * NON-DOM: resets this node and sets specified values for the node
       *
       * @param ownerDocument
       * @param namespaceURI
       * @param qualifiedName
       * @param localName
       */
      public void setValues (CoreDocumentImpl ownerDocument,
                           String namespaceURI,
                           String qualifiedName,
                           String localName){
  
          super.textNode = null;
          super.flags = 0;
          isSpecified(true);
          hasStringValue(true);
          super.setOwnerDocument(ownerDocument);
          this.localName = localName;
          this.namespaceURI = namespaceURI;
          super.name = qualifiedName;
          super.value = null;
      }
  
      //
      // DOM2: Namespace methods
      //
  
      /**
       * Introduced in DOM Level 2. <p>
       *
       * The namespace URI of this node, or null if it is unspecified.<p>
       *
       * This is not a computed value that is the result of a namespace lookup
       * based on an examination of the namespace declarations in scope. It is
       * merely the namespace URI given at creation time.<p>
       *
       * For nodes created with a DOM Level 1 method, such as createElement
       * from the Document interface, this is null.
       * @since WD-DOM-Level-2-19990923
       */
      public String getNamespaceURI()
      {
          if (needsSyncData()) {
              synchronizeData();
          }
          // REVIST: This code could/should be done at a lower-level, such that
          // the namespaceURI is set properly upon creation. However, there still
          // seems to be some DOM spec interpretation grey-area.
          return namespaceURI;
      }
  
      /**
       * Introduced in DOM Level 2. <p>
       *
       * The namespace prefix of this node, or null if it is unspecified. <p>
       *
       * For nodes created with a DOM Level 1 method, such as createElement
       * from the Document interface, this is null. <p>
       *
       * @since WD-DOM-Level-2-19990923
       */
      public String getPrefix()
      {
          if (needsSyncData()) {
              synchronizeData();
          }
          int index = name.indexOf(':');
          return index < 0 ? null : name.substring(0, index);
      }
  
      /**
       * Introduced in DOM Level 2. <p>
       *
       * Note that setting this attribute changes the nodeName attribute, which
       * holds the qualified name, as well as the tagName and name attributes of
       * the Element and Attr interfaces, when applicable.<p>
       *
       * @param prefix The namespace prefix of this node, or null(empty string) if it is unspecified.
       *
       * @exception INVALID_CHARACTER_ERR
       *                   Raised if the specified
       *                   prefix contains an invalid character.
       * @exception DOMException
       * @since WD-DOM-Level-2-19990923
       */
      public void setPrefix(String prefix)
          throws DOMException
      {
          if (needsSyncData()) {
              synchronizeData();
          }
          if (ownerDocument().errorChecking) {
              if (isReadOnly()) {
                  String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
                  throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
              }
              if (prefix != null && prefix.length() != 0) {
  
                  if (!CoreDocumentImpl.isXMLName(prefix,ownerDocument().isXML11Version())) {
                      String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INVALID_CHARACTER_ERR", null);
                      throw new DOMException(DOMException.INVALID_CHARACTER_ERR, msg);
                  }
                  if (namespaceURI == null || prefix.indexOf(':') >=0) {
                      String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
                      throw new DOMException(DOMException.NAMESPACE_ERR, msg);
  
                  }
                 if (prefix.equals("xmlns")) {
                      if (!namespaceURI.equals(xmlnsURI)){
                          String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
                          throw new DOMException(DOMException.NAMESPACE_ERR, msg);
                      }
                  } else if (prefix.equals("xml")) {
                      if (!namespaceURI.equals(xmlURI)) {
                          String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
                          throw new DOMException(DOMException.NAMESPACE_ERR, msg);
                      }
                  }else if (name.equals("xmlns")) {
                      String msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NAMESPACE_ERR", null);
                      throw new DOMException(DOMException.NAMESPACE_ERR, msg);
                  }
              }
          }
  
          // update node name with new qualifiedName
          if (prefix !=null && prefix.length() != 0) {
              name = prefix + ":" + localName;
          }
          else {
              name = localName;
          }
      }
  
      /**
       * Introduced in DOM Level 2. <p>
       *
       * Returns the local part of the qualified name of this node.
       * @since WD-DOM-Level-2-19990923
       */
      public String getLocalName()
      {
          if (needsSyncData()) {
              synchronizeData();
          }
          return localName;
      }
  
  
      /**
       * @see org.w3c.dom.TypeInfo#getTypeName()
       */
      public String getTypeName() {
          if (type !=null){
              if (type instanceof XSSimpleTypeDecl){
                  return ((XSSimpleTypeDecl)type).getName();
              }
              return (String)type;
          }
          return null;
      }
  
      /**
       * Introduced in DOM Level 3. <p>
       * Checks if a type is derived from another by restriction. See:
       * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
       *
       * @param ancestorNS
       *        The namspace of the ancestor type declaration
       * @param ancestorName
       *        The name of the ancestor type declaration
       * @param type
       *        The reference type definition
       *
       * @return boolean True if the type is derived by restriciton for the
       *         reference type
       */
      public boolean isDerivedFrom(String typeNamespaceArg,
                                   String typeNameArg,
                                   int derivationMethod) {
          if (type != null) {
              if (type instanceof XSSimpleTypeDecl) {
                  return ((XSSimpleTypeDecl) type).isDOMDerivedFrom(
                          typeNamespaceArg, typeNameArg, derivationMethod);
              }
          }
          return false;
      }
  
      /**
       * @see org.w3c.dom.TypeInfo#getTypeNamespace()
       */
      public String getTypeNamespace() {
          if (type !=null) {
              if (type instanceof XSSimpleTypeDecl){
                  return ((XSSimpleTypeDecl)type).getNamespace();
              }
              return DTD_URI;
          }
          return null;
      }
  
  }
  