1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-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.impl.xs.traversers;
  22 
  23 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  24 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  25 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  26 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  27 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  28 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
  29 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl;
  30 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeUseImpl;
  31 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
  32 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  33 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  34 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  35 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  36 import com.sun.org.apache.xerces.internal.xni.QName;
  37 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  38 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  39 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  40 import org.w3c.dom.Element;
  41 
  42 /**
  43  * The attribute declaration schema component traverser.
  44  *
  45  * <attribute
  46  *   default = string
  47  *   fixed = string
  48  *   form = (qualified | unqualified)
  49  *   id = ID
  50  *   name = NCName
  51  *   ref = QName
  52  *   type = QName
  53  *   use = (optional | prohibited | required) : optional
  54  *   {any attributes with non-schema namespace . . .}>
  55  *   Content: (annotation?, (simpleType?))
  56  * </attribute>
  57  *
  58  * @xerces.internal
  59  *
  60  * @author Sandy Gao, IBM
  61  * @author Neeraj Bajaj, Sun Microsystems, inc.
  62  * @version $Id: XSDAttributeTraverser.java,v 1.7 2010-11-01 04:40:02 joehw Exp $
  63  */
  64 class XSDAttributeTraverser extends XSDAbstractTraverser {
  65 
  66     public XSDAttributeTraverser (XSDHandler handler,
  67             XSAttributeChecker gAttrCheck) {
  68         super(handler, gAttrCheck);
  69     }
  70 
  71     protected XSAttributeUseImpl traverseLocal(Element attrDecl,
  72             XSDocumentInfo schemaDoc,
  73             SchemaGrammar grammar,
  74             XSComplexTypeDecl enclosingCT) {
  75 
  76         // General Attribute Checking
  77         Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, false, schemaDoc);
  78 
  79         String defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
  80         String fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
  81         String nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
  82         QName  refAtt     = (QName)  attrValues[XSAttributeChecker.ATTIDX_REF];
  83         XInt   useAtt     = (XInt)   attrValues[XSAttributeChecker.ATTIDX_USE];
  84 
  85         // get 'attribute declaration'
  86         XSAttributeDecl attribute = null;
  87         XSAnnotationImpl annotation = null;
  88         if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) != null) {
  89             if (refAtt != null) {
  90                 attribute = (XSAttributeDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ATTRIBUTE_TYPE, refAtt, attrDecl);
  91 
  92                 Element child = DOMUtil.getFirstChildElement(attrDecl);
  93                 if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
  94                     annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
  95                     child = DOMUtil.getNextSiblingElement(child);
  96                 }
  97                 else {
  98                     String text = DOMUtil.getSyntheticAnnotation(attrDecl);
  99                     if (text != null) {
 100                         annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
 101                     }
 102                 }
 103 
 104                 if (child != null) {
 105                     reportSchemaError("src-attribute.3.2", new Object[]{refAtt.rawname}, child);
 106                 }
 107                 // for error reporting
 108                 nameAtt = refAtt.localpart;
 109             } else {
 110                 attribute = null;
 111             }
 112         } else {
 113             attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, false, enclosingCT);
 114         }
 115 
 116         // get 'value constraint'
 117         short consType = XSConstants.VC_NONE;
 118         if (defaultAtt != null) {
 119             consType = XSConstants.VC_DEFAULT;
 120         } else if (fixedAtt != null) {
 121             consType = XSConstants.VC_FIXED;
 122             defaultAtt = fixedAtt;
 123             fixedAtt = null;
 124         }
 125 
 126         XSAttributeUseImpl attrUse = null;
 127         if (attribute != null) {
 128             if (fSchemaHandler.fDeclPool !=null) {
 129                 attrUse = fSchemaHandler.fDeclPool.getAttributeUse();
 130             } else {
 131                 attrUse = new XSAttributeUseImpl();
 132             }
 133             attrUse.fAttrDecl = attribute;
 134             attrUse.fUse = useAtt.shortValue();
 135             attrUse.fConstraintType = consType;
 136             if (defaultAtt != null) {
 137                 attrUse.fDefault = new ValidatedInfo();
 138                 attrUse.fDefault.normalizedValue = defaultAtt;
 139             }
 140             // Get the annotation associated witht the local attr decl
 141             if (attrDecl.getAttributeNode(SchemaSymbols.ATT_REF) == null) {
 142                 attrUse.fAnnotations = attribute.getAnnotations();
 143             } else {
 144                 XSObjectList annotations;
 145                 if (annotation != null) {
 146                     annotations = new XSObjectListImpl();
 147                     ((XSObjectListImpl) annotations).addXSObject(annotation);
 148                 } else {
 149                     annotations = XSObjectListImpl.EMPTY_LIST;
 150                 }
 151                 attrUse.fAnnotations = annotations;
 152             }
 153         }
 154 
 155         //src-attribute
 156 
 157         // 1 default and fixed must not both be present.
 158         if (defaultAtt != null && fixedAtt != null) {
 159             reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
 160         }
 161 
 162         // 2 If default and use are both present, use must have the actual value optional.
 163         if (consType == XSConstants.VC_DEFAULT &&
 164                 useAtt != null && useAtt.intValue() != SchemaSymbols.USE_OPTIONAL) {
 165             reportSchemaError("src-attribute.2", new Object[]{nameAtt}, attrDecl);
 166             // Recover by honouring the default value
 167             attrUse.fUse = SchemaSymbols.USE_OPTIONAL;
 168         }
 169 
 170         // a-props-correct
 171 
 172         if (defaultAtt != null && attrUse != null) {
 173             // 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).
 174             fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
 175             try {
 176                 checkDefaultValid(attrUse);
 177             }
 178             catch (InvalidDatatypeValueException ide) {
 179                 reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
 180                 reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, defaultAtt}, attrDecl);
 181                 // Recover by removing the default value
 182                 attrUse.fDefault = null;
 183                 attrUse.fConstraintType = XSConstants.VC_NONE;
 184             }
 185 
 186             // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
 187             if (((XSSimpleType)attribute.getTypeDefinition()).isIDType() ) {
 188                 reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
 189                 // Recover by removing the default value
 190                 attrUse.fDefault = null;
 191                 attrUse.fConstraintType = XSConstants.VC_NONE;
 192             }
 193 
 194             // check 3.5.6 constraint
 195             // Attribute Use Correct
 196             // 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}.
 197             if (attrUse.fAttrDecl.getConstraintType() == XSConstants.VC_FIXED &&
 198                     attrUse.fConstraintType != XSConstants.VC_NONE) {
 199                 if (attrUse.fConstraintType != XSConstants.VC_FIXED ||
 200                         !attrUse.fAttrDecl.getValInfo().actualValue.equals(attrUse.fDefault.actualValue)) {
 201                     reportSchemaError ("au-props-correct.2", new Object[]{nameAtt, attrUse.fAttrDecl.getValInfo().stringValue()}, attrDecl);
 202                     // Recover by using the decl's {value constraint}
 203                     attrUse.fDefault = attrUse.fAttrDecl.getValInfo();
 204                     attrUse.fConstraintType = XSConstants.VC_FIXED;
 205                 }
 206             }
 207         }
 208 
 209         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 210         return attrUse;
 211     }
 212 
 213     protected XSAttributeDecl traverseGlobal(Element attrDecl,
 214             XSDocumentInfo schemaDoc,
 215             SchemaGrammar grammar) {
 216 
 217         // General Attribute Checking
 218         Object[] attrValues = fAttrChecker.checkAttributes(attrDecl, true, schemaDoc);
 219         XSAttributeDecl attribute = traverseNamedAttr(attrDecl, attrValues, schemaDoc, grammar, true, null);
 220         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 221         return attribute;
 222 
 223     }
 224 
 225     /**
 226      * Traverse a globally declared attribute.
 227      *
 228      * @param  attrDecl
 229      * @param  attrValues
 230      * @param  schemaDoc
 231      * @param  grammar
 232      * @param  isGlobal
 233      * @return the attribute declaration index
 234      */
 235     XSAttributeDecl traverseNamedAttr(Element attrDecl,
 236             Object[] attrValues,
 237             XSDocumentInfo schemaDoc,
 238             SchemaGrammar grammar,
 239             boolean isGlobal,
 240             XSComplexTypeDecl enclosingCT) {
 241 
 242         String  defaultAtt = (String) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
 243         String  fixedAtt   = (String) attrValues[XSAttributeChecker.ATTIDX_FIXED];
 244         XInt    formAtt    = (XInt)   attrValues[XSAttributeChecker.ATTIDX_FORM];
 245         String  nameAtt    = (String) attrValues[XSAttributeChecker.ATTIDX_NAME];
 246         QName   typeAtt    = (QName)  attrValues[XSAttributeChecker.ATTIDX_TYPE];
 247 
 248         // Step 1: get declaration information
 249         XSAttributeDecl attribute = null;
 250         if (fSchemaHandler.fDeclPool !=null) {
 251             attribute = fSchemaHandler.fDeclPool.getAttributeDecl();
 252         } else {
 253             attribute = new XSAttributeDecl();
 254         }
 255 
 256         // get 'name'
 257         if (nameAtt != null)
 258             nameAtt = fSymbolTable.addSymbol(nameAtt);
 259 
 260         // get 'target namespace'
 261         String tnsAtt = null;
 262         XSComplexTypeDecl enclCT = null;
 263         short scope = XSAttributeDecl.SCOPE_ABSENT;
 264         if (isGlobal) {
 265             tnsAtt = schemaDoc.fTargetNamespace;
 266             scope = XSAttributeDecl.SCOPE_GLOBAL;
 267         }
 268         else {
 269             if (enclosingCT != null) {
 270                 enclCT = enclosingCT;
 271                 scope = XSAttributeDecl.SCOPE_LOCAL;
 272             }
 273             if (formAtt != null) {
 274                 if (formAtt.intValue() == SchemaSymbols.FORM_QUALIFIED)
 275                     tnsAtt = schemaDoc.fTargetNamespace;
 276             } else if (schemaDoc.fAreLocalAttributesQualified) {
 277                 tnsAtt = schemaDoc.fTargetNamespace;
 278             }
 279         }
 280         // get 'value constraint'
 281         // for local named attribute, value constraint is absent
 282         ValidatedInfo attDefault = null;
 283         short constraintType = XSConstants.VC_NONE;
 284         if (isGlobal) {
 285             if (fixedAtt != null) {
 286                 attDefault = new ValidatedInfo();
 287                 attDefault.normalizedValue = fixedAtt;
 288                 constraintType = XSConstants.VC_FIXED;
 289             } else if (defaultAtt != null) {
 290                 attDefault = new ValidatedInfo();
 291                 attDefault.normalizedValue = defaultAtt;
 292                 constraintType = XSConstants.VC_DEFAULT;
 293             }
 294         }
 295 
 296         // get 'annotation'
 297         Element child = DOMUtil.getFirstChildElement(attrDecl);
 298         XSAnnotationImpl annotation = null;
 299         if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
 300             annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
 301             child = DOMUtil.getNextSiblingElement(child);
 302         }
 303         else {
 304             String text = DOMUtil.getSyntheticAnnotation(attrDecl);
 305             if (text != null) {
 306                 annotation = traverseSyntheticAnnotation(attrDecl, text, attrValues, false, schemaDoc);
 307             }
 308         }
 309 
 310         // get 'type definition'
 311         XSSimpleType attrType = null;
 312         boolean haveAnonType = false;
 313 
 314         // Handle Anonymous type if there is one
 315         if (child != null) {
 316             String childName = DOMUtil.getLocalName(child);
 317 
 318             if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
 319                 attrType = fSchemaHandler.fSimpleTypeTraverser.traverseLocal(child, schemaDoc, grammar);
 320                 haveAnonType = true;
 321                 child = DOMUtil.getNextSiblingElement(child);
 322             }
 323         }
 324 
 325         // Handle type attribute
 326         if (attrType == null && typeAtt != null) {
 327             XSTypeDefinition type = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, typeAtt, attrDecl);
 328             if (type != null && type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
 329                 attrType = (XSSimpleType)type;
 330             }
 331             else {
 332                 reportSchemaError("src-resolve", new Object[]{typeAtt.rawname, "simpleType definition"}, attrDecl);
 333                 if (type == null) {
 334                         attribute.fUnresolvedTypeName = typeAtt;
 335                 }
 336             }
 337         }
 338 
 339         if (attrType == null) {
 340             attrType = SchemaGrammar.fAnySimpleType;
 341         }
 342 
 343         XSObjectList annotations;
 344         if (annotation != null) {
 345             annotations = new XSObjectListImpl();
 346             ((XSObjectListImpl)annotations).addXSObject(annotation);
 347         } else {
 348             annotations = XSObjectListImpl.EMPTY_LIST;
 349         }
 350         attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
 351                 attDefault, enclCT, annotations);
 352 
 353         // Step 3: check against schema for schemas
 354 
 355         // required attributes
 356         if (nameAtt == null) {
 357             if (isGlobal)
 358                 reportSchemaError("s4s-att-must-appear", new Object[]{SchemaSymbols.ELT_ATTRIBUTE, SchemaSymbols.ATT_NAME}, attrDecl);
 359             else
 360                 reportSchemaError("src-attribute.3.1", null, attrDecl);
 361             nameAtt = NO_NAME;
 362         }
 363 
 364         // element
 365         if (child != null) {
 366             reportSchemaError("s4s-elt-must-match.1", new Object[]{nameAtt, "(annotation?, (simpleType?))", DOMUtil.getLocalName(child)}, child);
 367         }
 368 
 369         // Step 4: check 3.2.3 constraints
 370 
 371         // src-attribute
 372 
 373         // 1 default and fixed must not both be present.
 374         if (defaultAtt != null && fixedAtt != null) {
 375             reportSchemaError("src-attribute.1", new Object[]{nameAtt}, attrDecl);
 376         }
 377 
 378         // 2 If default and use are both present, use must have the actual value optional.
 379         // This is checked in "traverse" method
 380 
 381         // 3 If the item's parent is not <schema>, then all of the following must be true:
 382         // 3.1 One of ref or name must be present, but not both.
 383         // This is checked in XSAttributeChecker
 384 
 385         // 3.2 If ref is present, then all of <simpleType>, form and type must be absent.
 386         // Attributes are checked in XSAttributeChecker, elements are checked in "traverse" method
 387 
 388         // 4 type and <simpleType> must not both be present.
 389         if (haveAnonType && (typeAtt != null)) {
 390             reportSchemaError( "src-attribute.4", new Object[]{nameAtt}, attrDecl);
 391         }
 392 
 393         // Step 5: check 3.2.6 constraints
 394         // check for NOTATION type
 395         checkNotationType(nameAtt, attrType, attrDecl);
 396 
 397         // a-props-correct
 398 
 399         // 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).
 400         if (attDefault != null) {
 401             fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
 402             try {
 403                 checkDefaultValid(attribute);
 404             }
 405             catch (InvalidDatatypeValueException ide) {
 406                 reportSchemaError (ide.getKey(), ide.getArgs(), attrDecl);
 407                 reportSchemaError ("a-props-correct.2", new Object[]{nameAtt, attDefault.normalizedValue}, attrDecl);
 408                 // Recover by removing the default value
 409                 attDefault = null;
 410                 constraintType = XSConstants.VC_NONE;
 411                 attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
 412                         attDefault, enclCT, annotations);
 413             }
 414         }
 415 
 416         // 3 If the {type definition} is or is derived from ID then there must not be a {value constraint}.
 417         if (attDefault != null) {
 418             if (attrType.isIDType() ) {
 419                 reportSchemaError ("a-props-correct.3", new Object[]{nameAtt}, attrDecl);
 420                 // Recover by removing the default value
 421                 attDefault = null;
 422                 constraintType = XSConstants.VC_NONE;
 423                 attribute.setValues(nameAtt, tnsAtt, attrType, constraintType, scope,
 424                         attDefault, enclCT, annotations);
 425             }
 426         }
 427 
 428         // no-xmlns
 429 
 430         // The {name} of an attribute declaration must not match xmlns.
 431         if (nameAtt != null && nameAtt.equals(XMLSymbols.PREFIX_XMLNS)) {
 432             reportSchemaError("no-xmlns", null, attrDecl);
 433             return null;
 434         }
 435 
 436         // no-xsi
 437 
 438         // 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).
 439         if (tnsAtt != null && tnsAtt.equals(SchemaSymbols.URI_XSI)) {
 440             reportSchemaError("no-xsi", new Object[]{SchemaSymbols.URI_XSI}, attrDecl);
 441             return null;
 442         }
 443 
 444         // Attribute without a name. Return null.
 445         if (nameAtt.equals(NO_NAME))
 446             return null;
 447 
 448         // Step 2: register attribute decl to the grammar
 449         if (isGlobal) {
 450             if (grammar.getGlobalAttributeDecl(nameAtt) == null) {
 451                 grammar.addGlobalAttributeDecl(attribute);
 452             }
 453 
 454             // also add it to extended map
 455             final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
 456             final XSAttributeDecl attribute2 = grammar.getGlobalAttributeDecl(nameAtt, loc);
 457             if (attribute2  == null) {
 458                 grammar.addGlobalAttributeDecl(attribute, loc);
 459             }
 460 
 461             if (fSchemaHandler.fTolerateDuplicates) {
 462                 if (attribute2  != null) {
 463                     attribute = attribute2;
 464                 }
 465                 fSchemaHandler.addGlobalAttributeDecl(attribute);
 466             }
 467         }
 468 
 469         return attribute;
 470     }
 471 
 472     // throws an error if the constraint value is invalid for the given type
 473     void checkDefaultValid(XSAttributeDecl attribute) throws InvalidDatatypeValueException {
 474         // validate the original lexical rep, and set the actual value
 475         ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().normalizedValue, fValidationState, attribute.getValInfo());
 476         // validate the canonical lexical rep
 477         ((XSSimpleType)attribute.getTypeDefinition()).validate(attribute.getValInfo().stringValue(), fValidationState, attribute.getValInfo());
 478     }
 479 
 480     // throws an error if the constraint value is invalid for the given type
 481     void checkDefaultValid(XSAttributeUseImpl attrUse) throws InvalidDatatypeValueException {
 482         // validate the original lexical rep, and set the actual value
 483         ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.normalizedValue, fValidationState, attrUse.fDefault);
 484         // validate the canonical lexical rep
 485         ((XSSimpleType)attrUse.fAttrDecl.getTypeDefinition()).validate(attrUse.fDefault.stringValue(), fValidationState, attrUse.fDefault);
 486     }
 487 
 488 }