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