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