1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001, 2002,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.xs.SchemaGrammar;
  24 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  25 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
  26 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
  27 import com.sun.org.apache.xerces.internal.impl.xs.identity.KeyRef;
  28 import com.sun.org.apache.xerces.internal.impl.xs.identity.UniqueOrKey;
  29 import com.sun.org.apache.xerces.internal.xni.QName;
  30 import org.w3c.dom.Element;
  31 
  32 /**
  33  * This class contains code that is used to traverse <keyref>s.
  34  *
  35  * @xerces.internal
  36  *
  37  * @author Neil Graham, IBM
  38  */
  39 class XSDKeyrefTraverser extends XSDAbstractIDConstraintTraverser {
  40 
  41     public XSDKeyrefTraverser (XSDHandler handler,
  42                                   XSAttributeChecker gAttrCheck) {
  43         super(handler, gAttrCheck);
  44     }
  45 
  46     void traverse(Element krElem, XSElementDecl element,
  47             XSDocumentInfo schemaDoc, SchemaGrammar grammar) {
  48 
  49         // General Attribute Checking
  50         Object[] attrValues = fAttrChecker.checkAttributes(krElem, false, schemaDoc);
  51 
  52         // create identity constraint
  53         String krName = (String)attrValues[XSAttributeChecker.ATTIDX_NAME];
  54         if(krName == null){
  55             reportSchemaError("s4s-att-must-appear", new Object [] {SchemaSymbols.ELT_KEYREF , SchemaSymbols.ATT_NAME }, krElem);
  56             //return this array back to pool
  57             fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  58             return;
  59         }
  60         QName kName = (QName)attrValues[XSAttributeChecker.ATTIDX_REFER];
  61         if(kName == null){
  62             reportSchemaError("s4s-att-must-appear", new Object [] {SchemaSymbols.ELT_KEYREF , SchemaSymbols.ATT_REFER }, krElem);
  63             //return this array back to pool
  64             fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  65             return;
  66         }
  67 
  68         UniqueOrKey key = null;
  69         IdentityConstraint ret = (IdentityConstraint)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.IDENTITYCONSTRAINT_TYPE, kName, krElem);
  70         // if ret == null, we've already reported an error in getGlobalDecl
  71         // we report an error only when ret != null, and the return type keyref
  72         if (ret != null) {
  73             if (ret.getCategory() == IdentityConstraint.IC_KEY ||
  74                 ret.getCategory() == IdentityConstraint.IC_UNIQUE) {
  75                 key = (UniqueOrKey)ret;
  76             } else {
  77                 reportSchemaError("src-resolve", new Object[]{kName.rawname, "identity constraint key/unique"}, krElem);
  78             }
  79         }
  80 
  81         if(key == null) {
  82             fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  83             return;
  84         }
  85 
  86         KeyRef keyRef = new KeyRef(schemaDoc.fTargetNamespace, krName, element.fName, key);
  87 
  88         // If errors occurred in traversing the identity constraint, then don't
  89         // add it to the schema, to avoid errors when processing the instance.
  90         if (traverseIdentityConstraint(keyRef, krElem, schemaDoc, attrValues)) {
  91             //Schema Component Constraint: Identity-constraint Definition Properties Correct
  92             //2 If the {identity-constraint category} is keyref, the cardinality of the {fields} must equal that of the {fields} of the {referenced key}.
  93             if(key.getFieldCount() != keyRef.getFieldCount()) {
  94                 reportSchemaError("c-props-correct.2" , new Object [] {krName,key.getIdentityConstraintName()}, krElem);
  95             } else {
  96                 // add key reference to element decl
  97                 // and stuff this in the grammar
  98                 if (grammar.getIDConstraintDecl(keyRef.getIdentityConstraintName()) == null) {
  99                     grammar.addIDConstraintDecl(element, keyRef);
 100                 }
 101 
 102                 // also add it to extended map
 103                 final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
 104                 final IdentityConstraint idc = grammar.getIDConstraintDecl(keyRef.getIdentityConstraintName(), loc);
 105                 if (idc  == null) {
 106                     grammar.addIDConstraintDecl(element, keyRef, loc);
 107                 }
 108 
 109                 // handle duplicates
 110                 if (fSchemaHandler.fTolerateDuplicates) {
 111                     if (idc  != null) {
 112                         if (idc instanceof KeyRef) {
 113                             keyRef = (KeyRef) idc;
 114                         }
 115                     }
 116                     fSchemaHandler.addIDConstraintDecl(keyRef);
 117                 }
 118             }
 119         }
 120 
 121         // and put back attributes
 122         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 123     } // traverse(Element,int,XSDocumentInfo, SchemaGrammar)
 124 } // XSDKeyrefTraverser