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 2001-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.impl.xs.traversers;
  
  import jaxp.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  import jaxp.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  import jaxp.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  import jaxp.sun.org.apache.xerces.internal.util.DOMUtil;
  import jaxp.sun.org.apache.xerces.internal.util.XMLSymbols;
  import jaxp.sun.org.apache.xerces.internal.xni.QName;
  import jaxp.sun.org.apache.xerces.internal.xs.XSConstants;
  import jaxp.sun.org.apache.xerces.internal.xs.XSObjectList;
  import jaxp.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  import org.w3c.dom.Element;
  
  /**
   * The attribute declaration schema component traverser.
   *
   * <attribute
   *   default = string
   *   fixed = string
   *   form = (qualified | unqualified)
   *   id = ID
   *   name = NCName
   *   ref = QName
   *   type = QName
   *   use = (optional | prohibited | required) : optional
   *   {any attributes with non-schema namespace . . .}>
   *   Content: (annotation?, (simpleType?))
   * </attribute>
   *
   * @xerces.internal
   *
   * @author Sandy Gao, IBM
   * @author Neeraj Bajaj, Sun Microsystems, inc.
   * @version $Id: XSDAttributeTraverser.java,v 1.7 2010-11-01 04:40:02 joehw Exp $
   */
  class XSDAttributeTraverser extends XSDAbstractTraverser {
  
      public XSDAttributeTraverser (XSDHandler handler,
              XSAttributeChecker gAttrCheck) {
          super(handler, gAttrCheck);
      }
  
      protected XSAttributeUseImpl traverseLocal(Element attrDecl,
                                                 XSDocumentInfo schemaDoc,
                                                 SchemaGrammar grammar,
                                                 XSComplexTypeDecl enclosingCT) {
  
          // General Attribute Checking
          Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, false, schemaDoc);
  
          String defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
          String fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
          String nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
          QName refAtt     = (QName)  attrValues[XSAttributeChecker.ATTIDX_REF];
          XInt useAtt     = (XInt)   attrValues[XSAttributeChecker.ATTIDX_USE];
  
          // get 'attribute declaration'
          XSAttributeDecl attribute = null;
          XSAnnotationImpl annotation = null;
          if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) != null) {
              if (refAtt != null) {
                  attribute = (XSAttributeDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ATTRIBUTE_TYPE, refAtt, attrDecl);
  
                  Element child = DOMUtil.getFirstChildElement(attrDecl);
                  if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
                      annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
                      child = DOMUtil.getNextSiblingElement(child);
                  }
                  else {
                      String text = DOMUtil.getSyntheticAnnotation(attrDecl);
                      if (text != null) {
                          annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
                      }
                  }
  
                  if (child != null) {
                      reportSchemaError("src-attribute.3.2", new Object[]{refAtt.rawname}, child);
                  }
                  // for error reporting
                  nameAtt = refAtt.localpart;
              } else {
                  attribute = null;
              }
          } else {
              attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, false, enclosingCT);
          }
  
          // get 'value constraint'
          short consType = XSConstants.VC_NONE;
          if (defaultAtt != null) {
              consType = XSConstants.VC_DEFAULT;
          } else if (fixedAtt != null) {
              consType = XSConstants.VC_FIXED;
              defaultAtt = fixedAtt;
              fixedAtt = null;
          }
  
          XSAttributeUseImpl attrUse = null;
          if (attribute != null) {
              if (fSchemaHandler.fDeclPool !=null) {
                  attrUse = fSchemaHandler.fDeclPool.getAttributeUse();
              } else {
                  attrUse = new XSAttributeUseImpl();
              }
              attrUse.fAttrDecl = attribute;
              attrUse.fUse = useAtt.shortValue();
              attrUse.fConstraintType = consType;
              if (defaultAtt != null) {
                  attrUse.fDefault = new ValidatedInfo();
                  attrUse.fDefault.normalizedValue = defaultAtt;
              }
              // Get the annotation associated witht the local attr decl
              if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) == null) {
                  attrUse.fAnnotations = attribute.getAnnotations();
              } else {
                  XSObjectList annotations;
                  if (annotation != null) {
                      annotations = new XSObjectListImpl();
                      ((XSObjectListImpl) annotations).addXSObject(annotation);
                  } else {
                      annotations = XSObjectListImpl.EMPTY_LIST;
                  }
                  attrUse.fAnnotations = annotations;
              }
          }
  
          //src-attribute
  
          // 1 default and fixed must not both be present.
          if (defaultAtt != null && fixedAtt != null) {
              reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
          }
  
          // 2 If default and use are both present, use must have the actual value optional.
          if (consType == XSConstants.VC_DEFAULT &&
                  useAtt != null && useAtt.intValue() != SchemaSymbols.USE_OPTIONAL) {
              reportSchemaError("src-attribute.2", new Object[]{nameAtt}, attrDecl);
              // Recover by honouring the default value
              attrUse.fUse = SchemaSymbols.USE_OPTIONAL;
          }
  
          // a-props-correct
  
          if (defaultAtt != null && attrUse != null) {
              // 2 if there is a {value constraint}, the canonical lexical representation of its value must be valid with respect to the {type definition} as defined in String Valid (3.14.4).
              fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
              try {
                  checkDefaultValid(attrUse);
              }
              catch (InvalidDatatypeValueException ide) {
                  reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
                  reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, defaultAtt}, attrDecl);
                  // Recover by removing the default value
                  attrUse.fDefault = null;
                  attrUse.fConstraintType = XSConstants.VC_NONE;
              }
  
              // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
              if (((XSSimpleType)attribute.getTypeDefinition()).isIDType() ) {
                  reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
                  // Recover by removing the default value
                  attrUse.fDefault = null;
                  attrUse.fConstraintType = XSConstants.VC_NONE;
              }
  
              // check 3.5.6 constraint
              // Attribute Use Correct
              // 2 If the {attribute declaration} has a fixed {value constraint}, then if the attribute use itself has a {value constraint}, it must also be fixed and its value must match that of the {attribute declaration}'s {value constraint}.
              if (attrUse.fAttrDecl.getConstraintType() == XSConstants.VC_FIXED &&
                      attrUse.fConstraintType != XSConstants.VC_NONE) {
                  if (attrUse.fConstraintType != XSConstants.VC_FIXED ||
                          !attrUse.fAttrDecl.getValInfo().actualValue.equals(attrUse.fDefault.actualValue)) {
                      reportSchemaError ("au-props-correct.2", new Object[]{nameAtt, attrUse.fAttrDecl.getValInfo().stringValue()}, attrDecl);
                      // Recover by using the decl's {value constraint}
                      attrUse.fDefault = attrUse.fAttrDecl.getValInfo();
                      attrUse.fConstraintType = XSConstants.VC_FIXED;
                  }
              }
          }
  
          fAttrChecker.returnAttrArray(attrValues, schemaDoc);
          return attrUse;
      }
  
      protected XSAttributeDecl traverseGlobal(Element attrDecl,
              XSDocumentInfo schemaDoc,
              SchemaGrammar grammar) {
  
          // General Attribute Checking
          Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, true, schemaDoc);
          XSAttributeDecl attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, true, null);
          fAttrChecker.returnAttrArray(attrValues, schemaDoc);
          return attribute;
  
      }
  
      /**
       * Traverse a globally declared attribute.
       *
       * @param  attrDecl
       * @param  attrValues
       * @param  schemaDoc
       * @param  grammar
       * @param  isGlobal
       * @return the attribute declaration index
       */
      XSAttributeDecl traverseNamedAttr(Element attrDecl,
              Object[] attrValues,
              XSDocumentInfo schemaDoc,
              SchemaGrammar grammar,
              boolean isGlobal,
              XSComplexTypeDecl enclosingCT) {
  
          String  defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
          String  fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
          XInt    formAtt    = (XInt)   attrValues[XSAttributeChecker.ATTIDX_FORM];
          String  nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
          QName   typeAtt    = (QName)  attrValues[XSAttributeChecker.ATTIDX_TYPE];
  
          // Step 1: get declaration information
          XSAttributeDecl attribute = null;
          if (fSchemaHandler.fDeclPool !=null) {
              attribute = fSchemaHandler.fDeclPool.getAttributeDecl();
          } else {
              attribute = new XSAttributeDecl();
          }
  
          // get 'name'
          if (nameAtt != null)
              nameAtt = fSymbolTable.addSymbol(nameAtt);
  
          // get 'target namespace'
          String tnsAtt = null;
          XSComplexTypeDecl enclCT = null;
          short scope = XSAttributeDecl.SCOPE_ABSENT;
          if (isGlobal) {
              tnsAtt = schemaDoc.fTargetNamespace;
              scope = XSAttributeDecl.SCOPE_GLOBAL;
          }
          else {
              if (enclosingCT != null) {
                  enclCT = enclosingCT;
                  scope = XSAttributeDecl.SCOPE_LOCAL;
              }
              if (formAtt != null) {
                  if (formAtt.intValue() == SchemaSymbols.FORM_QUALIFIED)
                      tnsAtt = schemaDoc.fTargetNamespace;
              } else if (schemaDoc.fAreLocalAttributesQualified) {
                  tnsAtt = schemaDoc.fTargetNamespace;
              }
          }
          // get 'value constraint'
          // for local named attribute, value constraint is absent
          ValidatedInfo attDefault = null;
          short constraintType = XSConstants.VC_NONE;
          if (isGlobal) {
              if (fixedAtt != null) {
                  attDefault = new ValidatedInfo();
                  attDefault.normalizedValue = fixedAtt;
                  constraintType = XSConstants.VC_FIXED;
              } else if (defaultAtt != null) {
                  attDefault = new ValidatedInfo();
                  attDefault.normalizedValue = defaultAtt;
                  constraintType = XSConstants.VC_DEFAULT;
              }
          }
  
          // get 'annotation'
          Element child = DOMUtil.getFirstChildElement(attrDecl);
          XSAnnotationImpl annotation = null;
          if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
              annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
              child = DOMUtil.getNextSiblingElement(child);
          }
          else {
              String text = DOMUtil.getSyntheticAnnotation(attrDecl);
              if (text != null) {
                  annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
              }
          }
  
          // get 'type definition'
          XSSimpleType attrType = null;
          boolean haveAnonType = false;
  
          // Handle Anonymous type if there is one
          if (child != null) {
              String childName = DOMUtil.getLocalName(child);
  
              if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
                  attrType = fSchemaHandler.fSimpleTypeTraverser.traverseLocal(child, schemaDoc, grammar);
                  haveAnonType = true;
                  child = DOMUtil.getNextSiblingElement(child);
              }
          }
  
          // Handle type attribute
          if (attrType == null && typeAtt != null) {
              XSTypeDefinition type = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, typeAtt, attrDecl);
              if (type != null && type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
                  attrType = (XSSimpleType)type;
              }
              else {
                  reportSchemaError("src-resolve", new Object[]{typeAtt.rawname, "simpleType definition"}, attrDecl);
                  if (type == null) {
                          attribute.fUnresolvedTypeName = typeAtt;
                  }
              }
          }
  
          if (attrType == null) {
              attrType = SchemaGrammar.fAnySimpleType;
          }
  
          XSObjectList annotations;
          if (annotation != null) {
              annotations = new XSObjectListImpl();
              ((XSObjectListImpl)annotations).addXSObject(annotation);
          } else {
              annotations = XSObjectListImpl.EMPTY_LIST;
          }
          attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
                  attDefault, enclCT, annotations);
  
          // Step 3: check against schema for schemas
  
          // required attributes
          if (nameAtt == null) {
              if (isGlobal)
                  reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ATTRIBUTE, SchemaSymbols.ATT_NAME}, attrDecl);
              else
                  reportSchemaError("src-attribute.3.1", null, attrDecl);
              nameAtt = NO_NAME;
          }
  
          // element
          if (child != null) {
              reportSchemaError("s4s-elt-must-match.1", new Object[]{nameAtt, "(annotation?, (simpleType?))", DOMUtil.getLocalName(child)}, child);
          }
  
          // Step 4: check 3.2.3 constraints
  
          // src-attribute
  
          // 1 default and fixed must not both be present.
          if (defaultAtt != null && fixedAtt != null) {
              reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
          }
  
          // 2 If default and use are both present, use must have the actual value optional.
          // This is checked in "traverse" method
  
          // 3 If the item's parent is not <schema>, then all of the following must be true:
          // 3.1 One of ref or name must be present, but not both.
          // This is checked in XSAttributeChecker
  
          // 3.2 If ref is present, then all of <simpleType>, form and type must be absent.
          // Attributes are checked in XSAttributeChecker, elements are checked in "traverse" method
  
          // 4 type and <simpleType> must not both be present.
          if (haveAnonType && (typeAtt != null)) {
              reportSchemaError( "src-attribute.4", new Object[]{nameAtt}, attrDecl);
          }
  
          // Step 5: check 3.2.6 constraints
          // check for NOTATION type
          checkNotationType(nameAtt, attrType, attrDecl);
  
          // a-props-correct
  
          // 2 if there is a {value constraint}, the canonical lexical representation of its value must be valid with respect to the {type definition} as defined in String Valid (3.14.4).
          if (attDefault != null) {
              fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
              try {
                  checkDefaultValid(attribute);
              }
              catch (InvalidDatatypeValueException ide) {
                  reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
                  reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, attDefault.normalizedValue}, attrDecl);
                  // Recover by removing the default value
                  attDefault = null;
                  constraintType = XSConstants.VC_NONE;
                  attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
                          attDefault, enclCT, annotations);
              }
          }
  
          // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
          if (attDefault != null) {
              if (attrType.isIDType() ) {
                  reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
                  // Recover by removing the default value
                  attDefault = null;
                  constraintType = XSConstants.VC_NONE;
                  attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
                          attDefault, enclCT, annotations);
              }
          }
  
          // no-xmlns
  
          // The {name} of an attribute declaration must not match xmlns.
          if (nameAtt != null && nameAtt.equals(XMLSymbols.PREFIX_XMLNS)) {
              reportSchemaError("no-xmlns", null, attrDecl);
              return null;
          }
  
          // no-xsi
  
          // The {target namespace} of an attribute declaration, whether local or top-level, must not match http://www.w3.org/2001/XMLSchema-instance (unless it is one of the four built-in declarations given in the next section).
          if (tnsAtt != null && tnsAtt.equals(SchemaSymbols.URI_XSI)) {
              reportSchemaError("no-xsi", new Object[]{SchemaSymbols.URI_XSI}, attrDecl);
              return null;
          }
  
          // Attribute without a name. Return null.
          if (nameAtt.equals(NO_NAME))
              return null;
  
          // Step 2: register attribute decl to the grammar
          if (isGlobal) {
              if (grammar.getGlobalAttributeDecl(nameAtt) == null) {
                  grammar.addGlobalAttributeDecl(attribute);
              }
  
              // also add it to extended map
              final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
              final XSAttributeDecl attribute2 = grammar.getGlobalAttributeDecl(nameAtt, loc);
              if (attribute2  == null) {
                  grammar.addGlobalAttributeDecl(attribute, loc);
              }
  
              if (fSchemaHandler.fTolerateDuplicates) {
                  if (attribute2  != null) {
                      attribute = attribute2;
                  }
                  fSchemaHandler.addGlobalAttributeDecl(attribute);
              }
          }
  
          return attribute;
      }
  
      // throws an error if the constraint value is invalid for the given type
      void checkDefaultValid(XSAttributeDecl attribute) throws InvalidDatatypeValueException {
          // validate the original lexical rep, and set the actual value
          ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().normalizedValue, fValidationState, attribute.getValInfo());
          // validate the canonical lexical rep
          ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().stringValue(), fValidationState, attribute.getValInfo());
      }
  
      // throws an error if the constraint value is invalid for the given type
      void checkDefaultValid(XSAttributeUseImpl attrUse) throws InvalidDatatypeValueException {
          // validate the original lexical rep, and set the actual value
          ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.normalizedValue, fValidationState, attrUse.fDefault);
          // validate the canonical lexical rep
          ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.stringValue(), fValidationState, attrUse.fDefault);
      }
  
  }
  