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;
  
  import jaxp.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  import jaxp.sun.org.apache.xerces.internal.xs.XSAnnotation;
  import jaxp.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
  import jaxp.sun.org.apache.xerces.internal.xs.XSAttributeUse;
  import jaxp.sun.org.apache.xerces.internal.xs.XSConstants;
  import jaxp.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
  import jaxp.sun.org.apache.xerces.internal.xs.XSObjectList;
  import jaxp.sun.org.apache.xerces.internal.xs.XSWildcard;
  
  /**
   * The XML representation for an attribute group declaration
   * schema component is a global <attributeGroup> element information item
   *
   * @xerces.internal
   *
   * @author Sandy Gao, IBM
   * @author Rahul Srivastava, Sun Microsystems Inc.
   *
   * @version $Id: XSAttributeGroupDecl.java,v 1.7 2010-11-01 04:39:55 joehw Exp $
   */
  public class XSAttributeGroupDecl implements XSAttributeGroupDefinition {
  
      // name of the attribute group
      public String fName = null;
      // target namespace of the attribute group
      public String fTargetNamespace = null;
      // number of attribute uses included by this attribute group
      int fAttrUseNum = 0;
      // attribute uses included by this attribute group
      private static final int INITIAL_SIZE = 5;
      XSAttributeUseImpl[] fAttributeUses = new XSAttributeUseImpl[INITIAL_SIZE];
      // attribute wildcard included by this attribute group
      public XSWildcardDecl fAttributeWC = null;
      // whether there is an attribute use whose type is or is derived from ID.
      public String fIDAttrName = null;
  
      // optional annotation
      public XSObjectList fAnnotations;
  
      protected XSObjectListImpl fAttrUses = null;
  
      // The namespace schema information item corresponding to the target namespace
      // of the attribute group definition, if it is globally declared; or null otherwise.
      private XSNamespaceItem fNamespaceItem = null;
  
      // add an attribute use
      // if the type is derived from ID, but there is already another attribute
      // use of type ID, then return the name of the other attribute use;
      // otherwise, return null
      public String addAttributeUse(XSAttributeUseImpl attrUse) {
  
          // if this attribute use is prohibited, then don't check whether it's
          // of type ID
          if (attrUse.fUse != SchemaSymbols.USE_PROHIBITED) {
              if (attrUse.fAttrDecl.fType.isIDType()) {
                  // if there is already an attribute use of type ID,
                  // return its name (and don't add it to the list, to avoid
                  // interruption to instance validation.
                  if (fIDAttrName == null)
                      fIDAttrName = attrUse.fAttrDecl.fName;
                  else
                      return fIDAttrName;
              }
          }
  
          if (fAttrUseNum == fAttributeUses.length) {
              fAttributeUses = resize(fAttributeUses, fAttrUseNum*2);
          }
          fAttributeUses[fAttrUseNum++] = attrUse;
  
          return null;
      }
  
      public void replaceAttributeUse(XSAttributeUse oldUse, XSAttributeUseImpl newUse) {
          for (int i=0; i<fAttrUseNum; i++) {
              if (fAttributeUses[i] == oldUse) {
                  fAttributeUses[i] = newUse;
              }
          }
      }
  
      public XSAttributeUse getAttributeUse(String namespace, String name) {
          for (int i=0; i<fAttrUseNum; i++) {
              if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
                   (fAttributeUses[i].fAttrDecl.fName == name) )
                  return fAttributeUses[i];
          }
  
          return null;
      }
  
      public XSAttributeUse getAttributeUseNoProhibited(String namespace, String name) {
          for (int i=0; i<fAttrUseNum; i++) {
              if ( (fAttributeUses[i].fAttrDecl.fTargetNamespace == namespace) &&
                   (fAttributeUses[i].fAttrDecl.fName == name) &&
                   (fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED))
                  return fAttributeUses[i];
          }
  
          return null;
      }
  
      public void removeProhibitedAttrs() {
          if (fAttrUseNum == 0) return;
          // Remove all prohibited attributes.
          int count = 0;
          XSAttributeUseImpl[] uses = new XSAttributeUseImpl[fAttrUseNum];
          for (int i = 0; i < fAttrUseNum; i++) {
              if (fAttributeUses[i].fUse != SchemaSymbols.USE_PROHIBITED) {
                  uses[count++] = fAttributeUses[i];
              }
          }
          fAttributeUses = uses;
          fAttrUseNum = count;
  
          // Do not remove attributes that have the same name as the prohibited
          // ones, because they are specified at the same level. Prohibited
          // attributes are only to remove attributes from the base type in a
          // restriction.
  //        int newCount = 0;
  //        if (pCount > 0) {
  //            OUTER: for (int i = 0; i < fAttrUseNum; i++) {
  //                if (fAttributeUses[i].fUse == SchemaSymbols.USE_PROHIBITED)
  //                    continue;
  //                for (int j = 1; j <= pCount; j++) {
  //                    if (fAttributeUses[i].fAttrDecl.fName == pUses[fAttrUseNum-pCount].fAttrDecl.fName &&
  //                        fAttributeUses[i].fAttrDecl.fTargetNamespace == pUses[fAttrUseNum-pCount].fAttrDecl.fTargetNamespace) {
  //                        continue OUTER;
  //                    }
  //                }
  //                pUses[newCount++] = fAttributeUses[i];
  //            }
  //            fAttributeUses = pUses;
  //            fAttrUseNum = newCount;
  //        }
      }
  
      /**
       * Check that the attributes in this group validly restrict those from a base group.
       * If an error is found, an Object[] is returned. This contains the arguments for the error message
       * describing the error. The last element in the array (at index arr.length - 1) is the the error code.
       * Returns null if there is no error.
       *
       * REVISIT: is there a better way of returning the appropriate information for the error?
       *
       * @param typeName the name of the type containing this attribute group, used for error reporting purposes
       * @param baseGroup the XSAttributeGroupDecl that is the base we are checking against
       */
      public Object[] validRestrictionOf(String typeName, XSAttributeGroupDecl baseGroup) {
  
          Object[] errorArgs = null;
          XSAttributeUseImpl attrUse = null;
          XSAttributeDecl attrDecl = null;
          XSAttributeUseImpl baseAttrUse = null;
          XSAttributeDecl baseAttrDecl = null;
  
          for (int i=0; i<fAttrUseNum; i++) {
  
              attrUse = fAttributeUses[i];
              attrDecl = attrUse.fAttrDecl;
  
              // Look for a match in the base
              baseAttrUse = (XSAttributeUseImpl)baseGroup.getAttributeUse(attrDecl.fTargetNamespace,attrDecl.fName);
              if (baseAttrUse != null) {
                  //
                  // derivation-ok-restriction.  Constraint 2.1.1
                  //
  
                  if (baseAttrUse.getRequired() && !attrUse.getRequired()) {
                      errorArgs = new Object[]{typeName, attrDecl.fName,
                                               attrUse.fUse == SchemaSymbols.USE_OPTIONAL ? SchemaSymbols.ATTVAL_OPTIONAL : SchemaSymbols.ATTVAL_PROHIBITED,
                                               "derivation-ok-restriction.2.1.1"};
                      return errorArgs;
                  }
  
                  // if this attribute is prohibited in the derived type, don't
                  // need to check any of the following constraints.
                  if (attrUse.fUse == SchemaSymbols.USE_PROHIBITED) {
                      continue;
                  }
  
                  baseAttrDecl = baseAttrUse.fAttrDecl;
                  //
                  // derivation-ok-restriction.  Constraint 2.1.1
                  //
                  if (! XSConstraints.checkSimpleDerivationOk(attrDecl.fType,
                                                              baseAttrDecl.fType,
                                                              baseAttrDecl.fType.getFinal()) ) {
                                          errorArgs = new Object[]{typeName, attrDecl.fName, attrDecl.fType.getName(),
                                                                       baseAttrDecl.fType.getName(), "derivation-ok-restriction.2.1.2"};
                                          return errorArgs;
                  }
  
  
                  //
                  // derivation-ok-restriction.  Constraint 2.1.3
                  //
                  int baseConsType=baseAttrUse.fConstraintType!= XSConstants.VC_NONE?
                                   baseAttrUse.fConstraintType:baseAttrDecl.getConstraintType();
                  int thisConstType = attrUse.fConstraintType!=XSConstants.VC_NONE?
                                      attrUse.fConstraintType:attrDecl.getConstraintType();
  
                  if (baseConsType == XSConstants.VC_FIXED) {
  
                      if (thisConstType != XSConstants.VC_FIXED) {
                                                  errorArgs = new Object[]{typeName, attrDecl.fName,
                                                                                                   "derivation-ok-restriction.2.1.3.a"};
                                                  return errorArgs;
                      } else {
                          // check the values are the same.
                          ValidatedInfo baseFixedValue=(baseAttrUse.fDefault!=null ?
                                                        baseAttrUse.fDefault: baseAttrDecl.fDefault);
                          ValidatedInfo thisFixedValue=(attrUse.fDefault!=null ?
                                                        attrUse.fDefault: attrDecl.fDefault);
                          if (!baseFixedValue.actualValue.equals(thisFixedValue.actualValue)) {
                                                          errorArgs = new Object[]{typeName, attrDecl.fName, thisFixedValue.stringValue(),
                                                                                                           baseFixedValue.stringValue(), "derivation-ok-restriction.2.1.3.b"};
                                                          return errorArgs;
                          }
  
                      }
  
                  }
              } else {
                  // No matching attribute in base - there should be a matching wildcard
  
                  //
                  // derivation-ok-restriction.  Constraint 2.2
                  //
                  if (baseGroup.fAttributeWC == null) {
                                          errorArgs = new Object[]{typeName, attrDecl.fName,
                                                                                           "derivation-ok-restriction.2.2.a"};
                                          return errorArgs;
                  }
                  else if (!baseGroup.fAttributeWC.allowNamespace(attrDecl.fTargetNamespace)) {
                                          errorArgs = new Object[]{typeName, attrDecl.fName,
                                               attrDecl.fTargetNamespace==null?"":attrDecl.fTargetNamespace,
                                                                                           "derivation-ok-restriction.2.2.b"};
                                          return errorArgs;
                  }
              }
          }
  
          //
          // Check that any REQUIRED attributes in the base have matching attributes
          // in this group
          // derivation-ok-restriction.  Constraint 3
          //
          for (int i=0; i<baseGroup.fAttrUseNum; i++) {
  
              baseAttrUse = baseGroup.fAttributeUses[i];
  
              if (baseAttrUse.fUse == SchemaSymbols.USE_REQUIRED) {
  
                  baseAttrDecl = baseAttrUse.fAttrDecl;
                  // Look for a match in this group
                  if (getAttributeUse(baseAttrDecl.fTargetNamespace,baseAttrDecl.fName) == null) {
                                          errorArgs = new Object[]{typeName, baseAttrUse.fAttrDecl.fName,
                                                                                           "derivation-ok-restriction.3"};
                                          return errorArgs;
                  }
              }
          }
  
  
          // Now, check wildcards
          //
          // derivation-ok-restriction.  Constraint 4
          //
          if (fAttributeWC != null) {
              if (baseGroup.fAttributeWC == null) {
                                  errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.1"};
                                  return errorArgs;
              }
              if (! fAttributeWC.isSubsetOf(baseGroup.fAttributeWC)) {
                                  errorArgs = new Object[]{typeName, "derivation-ok-restriction.4.2"};
                                  return errorArgs;
              }
              if (fAttributeWC.weakerProcessContents(baseGroup.fAttributeWC)) {
                                  errorArgs = new Object[]{typeName,
                                                                                   fAttributeWC.getProcessContentsAsString(),
                                                                                   baseGroup.fAttributeWC.getProcessContentsAsString(),
                                                                                   "derivation-ok-restriction.4.3"};
                                  return errorArgs;
              }
          }
  
          return null;
  
      }
  
      static final XSAttributeUseImpl[] resize(XSAttributeUseImpl[] oldArray, int newSize) {
          XSAttributeUseImpl[] newArray = new XSAttributeUseImpl[newSize];
          System.arraycopy(oldArray, 0, newArray, 0, Math.min(oldArray.length, newSize));
          return newArray;
      }
  
      // reset the attribute group declaration
      public void reset(){
          fName = null;
          fTargetNamespace = null;
          // reset attribute uses
          for (int i=0;i<fAttrUseNum;i++) {
              fAttributeUses[i] = null;
          }
          fAttrUseNum = 0;
          fAttributeWC = null;
          fAnnotations = null;
          fIDAttrName = null;
  
      }
  
      /**
       * Get the type of the object, i.e ELEMENT_DECLARATION.
       */
      public short getType() {
          return XSConstants.ATTRIBUTE_GROUP;
      }
  
      /**
       * The <code>name</code> of this <code>XSObject</code> depending on the
       * <code>XSObject</code> type.
       */
      public String getName() {
          return fName;
      }
  
      /**
       * The namespace URI of this node, or <code>null</code> if it is
       * unspecified.  defines how a namespace URI is attached to schema
       * components.
       */
      public String getNamespace() {
          return fTargetNamespace;
      }
  
      /**
       * {attribute uses} A set of attribute uses.
       */
      public XSObjectList getAttributeUses() {
          if (fAttrUses == null){
              fAttrUses = new XSObjectListImpl(fAttributeUses, fAttrUseNum);
          }
          return fAttrUses;
      }
  
      /**
       * {attribute wildcard} Optional. A wildcard.
       */
      public XSWildcard getAttributeWildcard() {
          return fAttributeWC;
      }
  
      /**
       * Optional. Annotation.
       */
      public XSAnnotation getAnnotation() {
          return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
      }
  
      /**
       * Optional. Annotations.
       */
      public XSObjectList getAnnotations() {
          return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
      }
  
      /**
       * @see org.apache.xerces.xs.XSObject#getNamespaceItem()
       */
      public XSNamespaceItem getNamespaceItem() {
          return fNamespaceItem;
      }
  
      void setNamespaceItem(XSNamespaceItem namespaceItem) {
          fNamespaceItem = namespaceItem;
      }
  
  } // class XSAttributeGroupDecl
  