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 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
  21 
  22 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  23 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  24 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
  25 import com.sun.org.apache.xerces.internal.impl.xs.XSConstraints;
  26 import com.sun.org.apache.xerces.internal.impl.xs.XSGroupDecl;
  27 import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl;
  28 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
  29 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
  30 import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
  31 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  32 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  33 import com.sun.org.apache.xerces.internal.xni.QName;
  34 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  35 import org.w3c.dom.Element;
  36 
  37 /**
  38  * The model group schema component traverser.
  39  *
  40  * <group
  41  *   name = NCName>
  42  *   Content: (annotation?, (all | choice | sequence))
  43  * </group>
  44  *
  45  * @xerces.internal
  46  *
  47  * @author Rahul Srivastava, Sun Microsystems Inc.
  48  * @author Elena Litani, IBM
  49  * @author Lisa Martin,  IBM
  50  */
  51 class  XSDGroupTraverser extends XSDAbstractParticleTraverser {
  52 
  53     XSDGroupTraverser (XSDHandler handler,
  54             XSAttributeChecker gAttrCheck) {
  55 
  56         super(handler, gAttrCheck);
  57     }
  58 
  59     XSParticleDecl traverseLocal(Element elmNode,
  60             XSDocumentInfo schemaDoc,
  61             SchemaGrammar grammar) {
  62 
  63         // General Attribute Checking for elmNode declared locally
  64         Object[] attrValues = fAttrChecker.checkAttributes(elmNode, false,
  65                 schemaDoc);
  66         QName refAttr = (QName) attrValues[XSAttributeChecker.ATTIDX_REF];
  67         XInt  minAttr = (XInt)  attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
  68         XInt  maxAttr = (XInt)  attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
  69 
  70         XSGroupDecl group = null;
  71 
  72         // ref should be here.
  73         if (refAttr == null) {
  74             reportSchemaError("s4s-att-must-appear", new Object[]{"group (local)", "ref"}, elmNode);
  75         } else {
  76             // get global decl
  77             // index is a particle index.
  78             group = (XSGroupDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.GROUP_TYPE, refAttr, elmNode);
  79         }
  80 
  81         XSAnnotationImpl annotation = null;
  82         // no children other than "annotation?" are allowed
  83         Element child = DOMUtil.getFirstChildElement(elmNode);
  84         if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
  85             annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
  86             child = DOMUtil.getNextSiblingElement(child);
  87         }
  88         else {
  89             String text = DOMUtil.getSyntheticAnnotation(elmNode);
  90             if (text != null) {
  91                 annotation = traverseSyntheticAnnotation(elmNode, text, attrValues, false, schemaDoc);
  92             }
  93         }
  94 
  95         if (child != null) {
  96             reportSchemaError("s4s-elt-must-match.1", new Object[]{"group (local)", "(annotation?)", DOMUtil.getLocalName(elmNode)}, elmNode);
  97         }
  98 
  99         int minOccurs = minAttr.intValue();
 100         int maxOccurs = maxAttr.intValue();
 101 
 102         XSParticleDecl particle = null;
 103 
 104         // not empty group, not empty particle
 105         if (group != null && group.fModelGroup != null &&
 106                 !(minOccurs == 0 && maxOccurs == 0)) {
 107             // create a particle to contain this model group
 108             if (fSchemaHandler.fDeclPool != null) {
 109                 particle = fSchemaHandler.fDeclPool.getParticleDecl();
 110             } else {
 111                 particle = new XSParticleDecl();
 112             }
 113             particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
 114             particle.fValue = group.fModelGroup;
 115             particle.fMinOccurs = minOccurs;
 116             particle.fMaxOccurs = maxOccurs;
 117             if (group.fModelGroup.fCompositor == XSModelGroupImpl.MODELGROUP_ALL) {
 118                 Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
 119                 particle = checkOccurrences(particle, SchemaSymbols.ELT_GROUP,
 120                         (Element)elmNode.getParentNode(), GROUP_REF_WITH_ALL,
 121                         defaultVals.longValue());
 122             }
 123             if (refAttr != null) {
 124                 XSObjectList annotations;
 125                 if (annotation != null) {
 126                     annotations = new XSObjectListImpl();
 127                     ((XSObjectListImpl) annotations).addXSObject(annotation);
 128                 } else {
 129                     annotations = XSObjectListImpl.EMPTY_LIST;
 130                 }
 131                 particle.fAnnotations = annotations;
 132             } else {
 133                 particle.fAnnotations = group.fAnnotations;
 134             }
 135         }
 136 
 137         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 138 
 139         return particle;
 140 
 141     } // traverseLocal
 142 
 143     XSGroupDecl traverseGlobal(Element elmNode,
 144             XSDocumentInfo schemaDoc,
 145             SchemaGrammar grammar) {
 146 
 147         // General Attribute Checking for elmNode declared globally
 148         Object[] attrValues = fAttrChecker.checkAttributes(elmNode, true,
 149                 schemaDoc);
 150         String  strNameAttr = (String)  attrValues[XSAttributeChecker.ATTIDX_NAME];
 151 
 152         // must have a name
 153         if (strNameAttr == null) {
 154             reportSchemaError("s4s-att-must-appear", new Object[]{"group (global)", "name"}, elmNode);
 155         }
 156 
 157         // Create the group defi up-front, so it can be passed
 158         // to the traversal methods
 159         XSGroupDecl group = new XSGroupDecl();
 160         XSParticleDecl particle = null;
 161 
 162         // must have at least one child
 163         Element l_elmChild = DOMUtil.getFirstChildElement(elmNode);
 164         XSAnnotationImpl annotation = null;
 165         if (l_elmChild == null) {
 166             reportSchemaError("s4s-elt-must-match.2",
 167                     new Object[]{"group (global)", "(annotation?, (all | choice | sequence))"},
 168                     elmNode);
 169         } else {
 170             String childName = l_elmChild.getLocalName();
 171             if (childName.equals(SchemaSymbols.ELT_ANNOTATION)) {
 172                 annotation = traverseAnnotationDecl(l_elmChild, attrValues, true, schemaDoc);
 173                 l_elmChild = DOMUtil.getNextSiblingElement(l_elmChild);
 174                 if (l_elmChild != null)
 175                     childName = l_elmChild.getLocalName();
 176             }
 177             else {
 178                 String text = DOMUtil.getSyntheticAnnotation(elmNode);
 179                 if (text != null) {
 180                     annotation = traverseSyntheticAnnotation(elmNode, text, attrValues, false, schemaDoc);
 181                 }
 182             }
 183 
 184             if (l_elmChild == null) {
 185                 reportSchemaError("s4s-elt-must-match.2",
 186                         new Object[]{"group (global)", "(annotation?, (all | choice | sequence))"},
 187                         elmNode);
 188             } else if (childName.equals(SchemaSymbols.ELT_ALL)) {
 189                 particle = traverseAll(l_elmChild, schemaDoc, grammar, CHILD_OF_GROUP, group);
 190             } else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
 191                 particle = traverseChoice(l_elmChild, schemaDoc, grammar, CHILD_OF_GROUP, group);
 192             } else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
 193                 particle = traverseSequence(l_elmChild, schemaDoc, grammar, CHILD_OF_GROUP, group);
 194             } else {
 195                 reportSchemaError("s4s-elt-must-match.1",
 196                         new Object[]{"group (global)", "(annotation?, (all | choice | sequence))", DOMUtil.getLocalName(l_elmChild)},
 197                         l_elmChild);
 198             }
 199 
 200             if (l_elmChild != null &&
 201                     DOMUtil.getNextSiblingElement(l_elmChild) != null) {
 202                 reportSchemaError("s4s-elt-must-match.1",
 203                         new Object[]{"group (global)", "(annotation?, (all | choice | sequence))",
 204                         DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(l_elmChild))},
 205                         DOMUtil.getNextSiblingElement(l_elmChild));
 206             }
 207         }
 208 
 209         // add global group declaration to the grammar
 210         if (strNameAttr != null) {
 211             group.fName = strNameAttr;
 212             group.fTargetNamespace = schemaDoc.fTargetNamespace;
 213             if (particle == null) {
 214                 particle = XSConstraints.getEmptySequence();
 215             }
 216             group.fModelGroup = (XSModelGroupImpl)particle.fValue;
 217             XSObjectList annotations;
 218             if (annotation != null) {
 219                 annotations = new XSObjectListImpl();
 220                 ((XSObjectListImpl) annotations).addXSObject(annotation);
 221             } else {
 222                 annotations = XSObjectListImpl.EMPTY_LIST;
 223             }
 224             group.fAnnotations = annotations;
 225             // Add group declaration to grammar
 226             if (grammar.getGlobalGroupDecl(group.fName) == null) {
 227                 grammar.addGlobalGroupDecl(group);
 228             }
 229 
 230             // also add it to extended map
 231             final String loc = fSchemaHandler.schemaDocument2SystemId(schemaDoc);
 232             final XSGroupDecl group2 = grammar.getGlobalGroupDecl(group.fName, loc);
 233             if (group2 == null) {
 234                 grammar.addGlobalGroupDecl(group, loc);
 235             }
 236 
 237             // handle duplicates
 238             if (fSchemaHandler.fTolerateDuplicates) {
 239                 if (group2 != null) {
 240                     group = group2;
 241                 }
 242                 fSchemaHandler.addGlobalGroupDecl(group);
 243             }
 244         }
 245         else {
 246             // name attribute is not there, don't return this group.
 247             group = null;
 248         }
 249 
 250         if (group != null) {
 251             // store groups redefined by restriction in the grammar so
 252             // that we can get at them at full-schema-checking time.
 253             Object redefinedGrp = fSchemaHandler.getGrpOrAttrGrpRedefinedByRestriction(XSDHandler.GROUP_TYPE,
 254                     new QName(XMLSymbols.EMPTY_STRING, strNameAttr, strNameAttr, schemaDoc.fTargetNamespace),
 255                     schemaDoc, elmNode);
 256             if (redefinedGrp != null) {
 257                 // store in grammar
 258                 grammar.addRedefinedGroupDecl(group, (XSGroupDecl)redefinedGrp,
 259                         fSchemaHandler.element2Locator(elmNode));
 260             }
 261         }
 262 
 263         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
 264 
 265         return group;
 266 
 267     } // traverseGlobal
 268 }