You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by sa...@apache.org on 2002/04/27 00:03:43 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/impl/xs/traversers XSDAbstractParticleTraverser.java XSDComplexTypeTraverser.java XSDGroupTraverser.java

sandygao    02/04/26 15:03:43

  Modified:    java/src/org/apache/xerces/impl/xs SchemaGrammar.java
                        XMLSchemaValidator.java XSConstraints.java
                        XSDeclarationPool.java XSGroupDecl.java
                        XSParticleDecl.java
               java/src/org/apache/xerces/impl/xs/models CMBuilder.java
                        XSCMBinOp.java XSCMLeaf.java XSDFACM.java
               java/src/org/apache/xerces/impl/xs/traversers
                        XSDAbstractParticleTraverser.java
                        XSDComplexTypeTraverser.java XSDGroupTraverser.java
  Added:       java/src/org/apache/xerces/impl/xs XSModelGroup.java
  Removed:     java/src/org/apache/xerces/impl/xs/models XSSimpleCM.java
  Log:
  Many files are modified, mainly for reason 1 listed below. The other problems
  are discovered and solved during this big change.
  1. Use separate classes to represent "model group" and "particle";
  2. Removed the simple content model, because it's not simpler than DFA
  3. Rewrite the why how syntax tree is created: we only go through the tree
  once, and create the CM tree at the same time, instead of creating a temprory
  particle tree, then traverse it and create the CM tree;
  4. Improved how UPA is checked in DFA: avoid cloning particles, but use
  some distinct integer to differentiate leaf particles.
  5. Fixed a bug in particle derivation: all/sequence/choice restricting wildcard.
  
  Revision  Changes    Path
  1.17      +19 -10    xml-xerces/java/src/org/apache/xerces/impl/xs/SchemaGrammar.java
  
  Index: SchemaGrammar.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/SchemaGrammar.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- SchemaGrammar.java	24 Apr 2002 15:04:32 -0000	1.16
  +++ SchemaGrammar.java	26 Apr 2002 22:03:42 -0000	1.17
  @@ -82,7 +82,7 @@
    * @author Sandy Gao, IBM
    * @author Elena Litani, IBM
    *
  - * @version $Id: SchemaGrammar.java,v 1.16 2002/04/24 15:04:32 sandygao Exp $
  + * @version $Id: SchemaGrammar.java,v 1.17 2002/04/26 22:03:42 sandygao Exp $
    */
   
   public class SchemaGrammar implements Grammar {
  @@ -143,16 +143,16 @@
        */
       protected SchemaGrammar(int grammar) {
           SchemaDVFactory schemaFactory = SchemaDVFactory.getInstance();
  -        
  +
           if (grammar == GRAMMAR_XS) {
               // target namespace
               fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;
  -
  +    
               // grammar description
               fGrammarDescription = new XSDDescription();
               fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
               fGrammarDescription.fTargetNamespace = SchemaSymbols.URI_SCHEMAFORSCHEMA;
  -
  +    
               // no global decls other than types
               fGlobalAttrDecls  = new SymbolHash(1);
               fGlobalAttrGrpDecls = new SymbolHash(1);
  @@ -160,7 +160,7 @@
               fGlobalGroupDecls = new SymbolHash(1);
               fGlobalNotationDecls = new SymbolHash(1);
               fGlobalIDConstraintDecls = new SymbolHash(1);
  -
  +    
               // get all built-in types
               fGlobalTypeDecls = schemaFactory.getBuiltInTypes();
               // add anyType
  @@ -169,7 +169,6 @@
           else if (grammar == GRAMMAR_XSI) {
               // target namespace
               fTargetNamespace = SchemaSymbols.URI_XSI;
  -    
               // grammar description
               fGrammarDescription = new XSDDescription();
               fGrammarDescription.fContextType = XSDDescription.CONTEXT_PREPARSE;
  @@ -483,18 +482,28 @@
           fAnyType.fBaseType = fAnyType;
           fAnyType.fDerivedBy = SchemaSymbols.RESTRICTION;
           fAnyType.fContentType = XSComplexTypeDecl.CONTENTTYPE_MIXED;
  -        XSWildcardDecl wildcard = new XSWildcardDecl();
  +
  +        // the wildcard used in anyType (content and attribute)
           // the spec will change strict to lax for anyType
  +        XSWildcardDecl wildcard = new XSWildcardDecl();
           wildcard.fProcessContents = SchemaSymbols.ANY_LAX;
  +        // the particle for the content wildcard
           XSParticleDecl particleW = new XSParticleDecl();
           particleW.fMinOccurs = 0;
           particleW.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED;
           particleW.fType = XSParticleDecl.PARTICLE_WILDCARD;
           particleW.fValue = wildcard;
  +        // the model group of a sequence of the above particle
  +        XSModelGroup group = new XSModelGroup();
  +        group.fCompositor = XSModelGroup.MODELGROUP_SEQUENCE;
  +        group.fParticleCount = 1;
  +        group.fParticles = new XSParticleDecl[1];
  +        group.fParticles[0] = particleW;
  +        // the content of anyType: particle of the above model group
           XSParticleDecl particleG = new XSParticleDecl();
  -        particleG.fType = XSParticleDecl.PARTICLE_SEQUENCE;
  -        particleG.fValue = particleW;
  -        particleG.fOtherValue = null;
  +        particleG.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +        particleG.fValue = group;
  +        
           fAnyType.fParticle = particleG;
           fAnyType.fAttrGrp.fAttributeWC = wildcard;
       }
  
  
  
  1.57      +0 -5      xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java
  
  Index: XMLSchemaValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XMLSchemaValidator.java,v
  retrieving revision 1.56
  retrieving revision 1.57
  diff -u -r1.56 -r1.57
  --- XMLSchemaValidator.java	26 Apr 2002 21:30:57 -0000	1.56
  +++ XMLSchemaValidator.java	26 Apr 2002 22:03:42 -0000	1.57
  @@ -141,7 +141,7 @@
    * @author Elena Litani IBM
    * @author Andy Clark IBM
    * @author Neeraj Bajaj, Sun Microsystems, inc.
  - * @version $Id: XMLSchemaValidator.java,v 1.56 2002/04/26 21:30:57 sandygao Exp $
  + * @version $Id: XMLSchemaValidator.java,v 1.57 2002/04/26 22:03:42 sandygao Exp $
    */
   public class XMLSchemaValidator
                implements XMLComponent, XMLDocumentFilter, FieldActivator {
  @@ -2395,11 +2395,6 @@
                       reportSchemaError("cvc-elt.3.2.2", new Object[]{element.rawname, URI_XSI+","+XSI_NIL});
                   }
               }
  -            // REVISIT: report an error for invalid boolean value?
  -            //else if (!value.equals(SchemaSymbols.ATTVAL_FALSE) &&
  -            //         !value.equals(SchemaSymbols.ATTVAL_FALSE_0)) {
  -            //    reportSchemaError("cvc-elt.3.2", new Object[]{element.rawname, URI_XSI+","+XSI_NIL, xsiNil});
  -            //}
           }
       }
   
  
  
  
  1.20      +81 -81    xml-xerces/java/src/org/apache/xerces/impl/xs/XSConstraints.java
  
  Index: XSConstraints.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XSConstraints.java,v
  retrieving revision 1.19
  retrieving revision 1.20
  diff -u -r1.19 -r1.20
  --- XSConstraints.java	22 Apr 2002 13:26:35 -0000	1.19
  +++ XSConstraints.java	26 Apr 2002 22:03:42 -0000	1.20
  @@ -74,7 +74,7 @@
    *
    * @author Sandy Gao, IBM
    *
  - * @version $Id: XSConstraints.java,v 1.19 2002/04/22 13:26:35 sandygao Exp $
  + * @version $Id: XSConstraints.java,v 1.20 2002/04/26 22:03:42 sandygao Exp $
    */
   public class XSConstraints {
   
  @@ -338,6 +338,10 @@
               SGHandler.addSubstitutionGroup(grammars[i].getSubstitutionGroups());
           }
   
  +        XSParticleDecl fakeDerived = new XSParticleDecl();
  +        XSParticleDecl fakeBase = new XSParticleDecl();
  +        fakeDerived.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +        fakeBase.fType = XSParticleDecl.PARTICLE_MODELGROUP;
           // before worrying about complexTypes, let's get
           // groups redefined by restriction out of the way.
           for (int g = grammars.length-1; g >= 0; g--) {
  @@ -345,19 +349,20 @@
               SimpleLocator [] rgLocators = grammars[g].getRGLocators();
               for(int i=0; i<redefinedGroups.length; ) {
                   XSGroupDecl derivedGrp = redefinedGroups[i++];
  -                XSParticleDecl derivedParticle = derivedGrp.fParticle;
  +                XSModelGroup derivedMG = derivedGrp.fModelGroup;
                   XSGroupDecl baseGrp = redefinedGroups[i++];
  -                XSParticleDecl baseParticle = baseGrp.fParticle;
  -                if(baseParticle == null) {
  -                    if(derivedParticle != null) { // can't be a restriction!
  +                XSModelGroup baseMG = baseGrp.fModelGroup;
  +                if(baseMG == null) {
  +                    if(derivedMG != null) { // can't be a restriction!
                           reportSchemaError(errorReporter, rgLocators[i/2-1],
                                             "src-redefine.6.2.2",
                                             new Object[]{derivedGrp.fName, "rcase-Recurse.2"});
                       } 
                   } else {
  +                    fakeDerived.fValue = derivedMG;
  +                    fakeBase.fValue = baseMG;
                       try {
  -                        particleValidRestriction(SGHandler, 
  -                            derivedParticle, baseParticle);
  +                        particleValidRestriction(fakeDerived, SGHandler, fakeBase, SGHandler);
                       } catch (XMLSchemaException e) {
                           String key = e.getKey();
                           reportSchemaError(errorReporter, rgLocators[i/2-1],
  @@ -420,8 +425,10 @@
                       (types[j].fBaseType instanceof XSComplexTypeDecl) &&
                       ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle != null) {
                     try {
  -                      particleValidRestriction(SGHandler, types[j].fParticle,
  -                         ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle);
  +                      particleValidRestriction(types[j].fParticle,
  +                                               SGHandler,
  +                                               ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle,
  +                                               SGHandler);
                     } catch (XMLSchemaException e) {
                         reportSchemaError(errorReporter, ctLocators[j],
                                           e.getKey(),
  @@ -505,14 +512,9 @@
             return;
          }
   
  -       XSParticleDecl left = (XSParticleDecl)particle.fValue;
  -       checkElementDeclsConsistent(type, left, elemDeclHash, sgHandler);
  -
  -       XSParticleDecl right = (XSParticleDecl)particle.fOtherValue;
  -       if (right != null) {
  -         checkElementDeclsConsistent(type, right, elemDeclHash, sgHandler);
  -       }
  -       
  +       XSModelGroup group = (XSModelGroup)particle.fValue;
  +       for (int i = 0; i < group.fParticleCount; i++)
  +           checkElementDeclsConsistent(type, group.fParticles[i], elemDeclHash, sgHandler);
       }
   
       public static void findElemInTable(XSComplexTypeDecl type, XSElementDecl elem, 
  @@ -541,26 +543,22 @@
           }
       }
   
  -    // Invoke particleValidRestriction with a substitution group handler for each
       /*
          Check that a given particle is a valid restriction of a base particle.
       */
  -
  -    public static void particleValidRestriction(SubstitutionGroupHandler sgHandler,
  -                                     XSParticleDecl dParticle,
  -                                     XSParticleDecl bParticle)
  +    private static void particleValidRestriction(XSParticleDecl dParticle,
  +                                     SubstitutionGroupHandler dSGHandler,
  +                                     XSParticleDecl bParticle,
  +                                     SubstitutionGroupHandler bSGHandler)
                                        throws XMLSchemaException {
  -
  -    // Invoke particleValidRestriction with a substitution group handler for each
  -    // particle.
  -
  -       particleValidRestriction(dParticle, sgHandler, bParticle, sgHandler);
  +       particleValidRestriction(dParticle, dSGHandler, bParticle, bSGHandler, true);
       }
   
       private static void particleValidRestriction(XSParticleDecl dParticle,
                                        SubstitutionGroupHandler dSGHandler,
                                        XSParticleDecl bParticle,
  -                                     SubstitutionGroupHandler bSGHandler)
  +                                     SubstitutionGroupHandler bSGHandler,
  +                                     boolean checkWCOccurrence)
                                        throws XMLSchemaException {
   
          Vector dChildren = null;
  @@ -583,13 +581,12 @@
          //   - turning top-level elements with substitution groups into CHOICE groups.
          //
   
  -       int dType = dParticle.fType;
  +       short dType = dParticle.fType;
          //
          // Handle pointless groups for the derived particle
          //
  -       if (dType == XSParticleDecl.PARTICLE_SEQUENCE ||
  -           dType == XSParticleDecl.PARTICLE_CHOICE ||
  -           dType == XSParticleDecl.PARTICLE_ALL) {
  +       if (dType == XSParticleDecl.PARTICLE_MODELGROUP) {
  +         dType = ((XSModelGroup)dParticle.fValue).fCompositor;
   
            // Find a group, starting with this particle, with more than 1 child.   There
            // may be none, and the particle of interest trivially becomes an element or
  @@ -599,6 +596,8 @@
               // Particle has been replaced.   Retrieve new type info.
               dParticle = dtmp;
               dType = dParticle.fType;
  +            if (dType == XSParticleDecl.PARTICLE_MODELGROUP)
  +               dType = ((XSModelGroup)dParticle.fValue).fCompositor;
            }
   
            // Fill in a vector with the children of the particle, removing any
  @@ -623,9 +622,7 @@
                if (subGroup.length >0 ) {
                   // Now, set the type to be CHOICE.  The "group" will have the same
                   // occurrence information as the original particle.
  -                dType = XSParticleDecl.PARTICLE_CHOICE;
  -                dMinOccurs = dParticle.fMinOccurs;
  -                dMaxOccurs = dParticle.fMaxOccurs;
  +                dType = XSModelGroup.MODELGROUP_CHOICE;
                   dMinEffectiveTotalRange = dMinOccurs;
                   dMaxEffectiveTotalRange = dMaxOccurs;
   
  @@ -643,13 +640,12 @@
              }
          }
   
  -       int bType = bParticle.fType;
  +       short bType = bParticle.fType;
          //
          // Handle pointless groups for the base particle
          //
  -       if (bType == XSParticleDecl.PARTICLE_SEQUENCE ||
  -           bType == XSParticleDecl.PARTICLE_CHOICE ||
  -           bType == XSParticleDecl.PARTICLE_ALL) {
  +       if (bType == XSParticleDecl.PARTICLE_MODELGROUP) {
  +         bType = ((XSModelGroup)bParticle.fValue).fCompositor;
   
            // Find a group, starting with this particle, with more than 1 child.   There
            // may be none, and the particle of interest trivially becomes an element or
  @@ -659,6 +655,8 @@
               // Particle has been replaced.   Retrieve new type info.
               bParticle = btmp;
               bType = bParticle.fType;
  +            if (bType == XSParticleDecl.PARTICLE_MODELGROUP)
  +               bType = ((XSModelGroup)bParticle.fValue).fCompositor;
            }
   
            // Fill in a vector with the children of the particle, removing any
  @@ -679,9 +677,7 @@
                XSElementDecl[] bsubGroup = bSGHandler.getSubstitutionGroup(bElement);
                if (bsubGroup.length >0 ) {
                   // Now, set the type to be CHOICE
  -                bType = XSParticleDecl.PARTICLE_CHOICE;
  -                bMinOccurs = bParticle.fMinOccurs;
  -                bMaxOccurs = bParticle.fMaxOccurs;
  +                bType = XSModelGroup.MODELGROUP_CHOICE;
   
                   bChildren = new Vector(bsubGroup.length+1);
                   for (int i = 0; i < bsubGroup.length; i++) {
  @@ -715,12 +711,13 @@
                 case XSParticleDecl.PARTICLE_WILDCARD:
                 {
                    checkNSCompat((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
  -                               (XSWildcardDecl)bParticle.fValue,bMinOccurs,bMaxOccurs);
  +                               (XSWildcardDecl)bParticle.fValue,bMinOccurs,bMaxOccurs,
  +                               checkWCOccurrence);
                    return;
                 }
   
                 // Elt:All RecurseAsIfGroup
  -              case XSParticleDecl.PARTICLE_CHOICE:
  +              case XSModelGroup.MODELGROUP_CHOICE:
                 {
                    // Treat the element as if it were in a group of the same type
                    // as the base Particle
  @@ -731,8 +728,8 @@
                                    bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
                    return;
                 }
  -              case XSParticleDecl.PARTICLE_SEQUENCE:
  -              case XSParticleDecl.PARTICLE_ALL:
  +              case XSModelGroup.MODELGROUP_SEQUENCE:
  +              case XSModelGroup.MODELGROUP_ALL:
                 {
                    // Treat the element as if it were in a group of the same type
                    // as the base Particle
  @@ -764,9 +761,9 @@
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_CHOICE:
  -              case XSParticleDecl.PARTICLE_SEQUENCE:
  -              case XSParticleDecl.PARTICLE_ALL:
  +              case XSModelGroup.MODELGROUP_CHOICE:
  +              case XSModelGroup.MODELGROUP_SEQUENCE:
  +              case XSModelGroup.MODELGROUP_ALL:
                 case XSParticleDecl.PARTICLE_ELEMENT:
                 {
                    throw new XMLSchemaException("cos-particle-restrict.2",
  @@ -781,7 +778,7 @@
               }
            }
   
  -         case XSParticleDecl.PARTICLE_ALL:
  +         case XSModelGroup.MODELGROUP_ALL:
            {
               switch (bType) {
   
  @@ -796,20 +793,21 @@
                    checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
                                                   dMaxEffectiveTotalRange,
                                                   dSGHandler,
  -                                                bParticle,bMinOccurs,bMaxOccurs);
  +                                                bParticle,bMinOccurs,bMaxOccurs,
  +                                                checkWCOccurrence);
   
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_ALL:
  +              case XSModelGroup.MODELGROUP_ALL:
                 {
                    checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
                                 bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_CHOICE:
  -              case XSParticleDecl.PARTICLE_SEQUENCE:
  +              case XSModelGroup.MODELGROUP_CHOICE:
  +              case XSModelGroup.MODELGROUP_SEQUENCE:
                 case XSParticleDecl.PARTICLE_ELEMENT:
                 {
                    throw new XMLSchemaException("cos-particle-restrict.2",
  @@ -824,7 +822,7 @@
               }
            }
   
  -         case XSParticleDecl.PARTICLE_CHOICE:
  +         case XSModelGroup.MODELGROUP_CHOICE:
            {
               switch (bType) {
   
  @@ -839,19 +837,20 @@
                    checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
                                                   dMaxEffectiveTotalRange,
                                                   dSGHandler,
  -                                                bParticle,bMinOccurs,bMaxOccurs);
  +                                                bParticle,bMinOccurs,bMaxOccurs,
  +                                                checkWCOccurrence);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_CHOICE:
  +              case XSModelGroup.MODELGROUP_CHOICE:
                 {
                    checkRecurseLax(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
                                    bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_ALL:
  -              case XSParticleDecl.PARTICLE_SEQUENCE:
  +              case XSModelGroup.MODELGROUP_ALL:
  +              case XSModelGroup.MODELGROUP_SEQUENCE:
                 case XSParticleDecl.PARTICLE_ELEMENT:
                 {
                    throw new XMLSchemaException("cos-particle-restrict.2",
  @@ -867,7 +866,7 @@
            }
   
   
  -         case XSParticleDecl.PARTICLE_SEQUENCE:
  +         case XSModelGroup.MODELGROUP_SEQUENCE:
            {
               switch (bType) {
   
  @@ -882,25 +881,26 @@
                    checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
                                                   dMaxEffectiveTotalRange,
                                                   dSGHandler,
  -                                                bParticle,bMinOccurs,bMaxOccurs);
  +                                                bParticle,bMinOccurs,bMaxOccurs,
  +                                                checkWCOccurrence);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_ALL:
  +              case XSModelGroup.MODELGROUP_ALL:
                 {
                    checkRecurseUnordered(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
                                          bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_SEQUENCE:
  +              case XSModelGroup.MODELGROUP_SEQUENCE:
                 {
                    checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
                                 bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
                    return;
                 }
   
  -              case XSParticleDecl.PARTICLE_CHOICE:
  +              case XSModelGroup.MODELGROUP_CHOICE:
                 {
                    int min1 = dMinOccurs * dChildren.size();
                    int max1 = (dMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)?
  @@ -943,8 +943,8 @@
            return p;
   
          if (p.fMinOccurs==1 && p.fMaxOccurs==1 &&
  -           p.fValue!=null && p.fOtherValue==null)
  -         return getNonUnaryGroup((XSParticleDecl)p.fValue);
  +           p.fValue!=null && ((XSModelGroup)p.fValue).fParticleCount == 1)
  +         return getNonUnaryGroup(((XSModelGroup)p.fValue).fParticles[0]);
          else
            return p;
       }
  @@ -959,10 +959,9 @@
   
          Vector children = new Vector();
   
  -       gatherChildren(p.fType, (XSParticleDecl)p.fValue, children);
  -       if (p.fOtherValue != null) {
  -         gatherChildren(p.fType, (XSParticleDecl)p.fOtherValue, children);
  -       }
  +       XSModelGroup group = (XSModelGroup)p.fValue;
  +       for (int i = 0; i < group.fParticleCount; i++)
  +           gatherChildren(group.fCompositor, group.fParticles[i], children);
   
          return children;
       }
  @@ -973,6 +972,8 @@
          int min = p.fMinOccurs;
          int max = p.fMaxOccurs;
          int type = p.fType;
  +       if (type == XSParticleDecl.PARTICLE_MODELGROUP)
  +          type = ((XSModelGroup)p.fValue).fCompositor;
   
          if (type == XSParticleDecl.PARTICLE_EMPTY)
             return;
  @@ -983,16 +984,13 @@
             return;
          }
   
  -       XSParticleDecl left = (XSParticleDecl)p.fValue;
  -       XSParticleDecl right = (XSParticleDecl)p.fOtherValue;
          if (! (min==1 && max==1)) {
             children.addElement(p);
          }
          else if (parentType == type) {
  -          gatherChildren(type,left,children);
  -          if (right != null) {
  -            gatherChildren(type,right,children);
  -          }
  +          XSModelGroup group = (XSModelGroup)p.fValue;
  +          for (int i = 0; i < group.fParticleCount; i++)
  +             gatherChildren(type, group.fParticles[i], children);
          }
          else if (!p.isEmpty()) {
             children.addElement(p);
  @@ -1102,11 +1100,12 @@
       }
   
       private static void checkNSCompat(XSElementDecl elem, int min1, int max1,
  -                                      XSWildcardDecl wildcard, int min2, int max2)
  +                                      XSWildcardDecl wildcard, int min2, int max2,
  +                                      boolean checkWCOccurrence)
                                 throws XMLSchemaException {
   
         // check Occurrence ranges
  -      if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  +      if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
           throw new XMLSchemaException("rcase-NSCompat.2",
                                     new Object[]{elem.fName});
         }
  @@ -1139,12 +1138,13 @@
   
       private static void checkNSRecurseCheckCardinality(Vector children, int min1, int max1,
                                             SubstitutionGroupHandler dSGHandler,
  -                                          XSParticleDecl wildcard, int min2, int max2)
  +                                          XSParticleDecl wildcard, int min2, int max2,
  +                                          boolean checkWCOccurrence)
                                             throws XMLSchemaException {
   
   
         // check Occurrence ranges
  -      if (!checkOccurrenceRange(min1,max1,min2,max2)) {
  +      if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
            throw new XMLSchemaException("rcase-NSRecurseCheckCardinality.2", null);
         }
   
  @@ -1153,7 +1153,7 @@
         try {
           for (int i = 0; i < count; i++) {
              XSParticleDecl particle1 = (XSParticleDecl)children.elementAt(i);
  -           particleValidRestriction(particle1, dSGHandler, wildcard, null);
  +           particleValidRestriction(particle1, dSGHandler, wildcard, null, false);
   
           }
         }
  
  
  
  1.5       +35 -1     xml-xerces/java/src/org/apache/xerces/impl/xs/XSDeclarationPool.java
  
  Index: XSDeclarationPool.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XSDeclarationPool.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XSDeclarationPool.java	10 Apr 2002 16:45:52 -0000	1.4
  +++ XSDeclarationPool.java	26 Apr 2002 22:03:42 -0000	1.5
  @@ -67,7 +67,7 @@
    * Note: The cashing mechanism is not implemented yet.
    * 
    * @author Elena Litani, IBM
  - * @version $Id: XSDeclarationPool.java,v 1.4 2002/04/10 16:45:52 elena Exp $
  + * @version $Id: XSDeclarationPool.java,v 1.5 2002/04/26 22:03:42 sandygao Exp $
    */
   public final class XSDeclarationPool {
       /** Chunk shift (8). */
  @@ -90,6 +90,10 @@
       private XSParticleDecl fParticleDecl[][] = new XSParticleDecl[INITIAL_CHUNK_COUNT][];
       private int fParticleDeclIndex = 0;
   
  +    /** Particle declaration pool */
  +    private XSModelGroup fModelGroup[][] = new XSModelGroup[INITIAL_CHUNK_COUNT][];
  +    private int fModelGroupIndex = 0;
  +
       /** Attribute declaration pool */
       private XSAttributeDecl fAttrDecl[][] = new XSAttributeDecl[INITIAL_CHUNK_COUNT][];
       private int fAttrDeclIndex = 0;
  @@ -188,6 +192,19 @@
           return fParticleDecl[chunk][index];
       }
   
  +    public final XSModelGroup getModelGroup(){
  +        int     chunk       = fModelGroupIndex >> CHUNK_SHIFT;
  +        int     index       = fModelGroupIndex &  CHUNK_MASK;
  +        ensureModelGroupCapacity(chunk);
  +        if (fModelGroup[chunk][index] == null) {
  +            fModelGroup[chunk][index] = new XSModelGroup();
  +        } else {
  +            fModelGroup[chunk][index].reset();
  +        }
  +        fModelGroupIndex++;
  +        return fModelGroup[chunk][index];
  +    }
  +
       // REVISIT: do we need decl pool for group declarations, attribute group,
       //          notations?
       //          it seems like each schema would use a small number of those
  @@ -222,12 +239,28 @@
           return true;
       }
   
  +    private boolean ensureModelGroupCapacity(int chunk) {
  +        if (chunk >= fModelGroup.length) {
  +            fModelGroup = resize(fModelGroup, fModelGroup.length * 2);
  +        } else if (fModelGroup[chunk] != null) {
  +            return false;
  +        }
  +
  +        fModelGroup[chunk] = new XSModelGroup[CHUNK_SIZE];
  +        return true;
  +    }
  +
       private static XSParticleDecl[][] resize(XSParticleDecl array[][], int newsize) {
           XSParticleDecl newarray[][] = new XSParticleDecl[newsize][];
           System.arraycopy(array, 0, newarray, 0, array.length);
           return newarray;
       }
   
  +    private static XSModelGroup[][] resize(XSModelGroup array[][], int newsize) {
  +        XSModelGroup newarray[][] = new XSModelGroup[newsize][];
  +        System.arraycopy(array, 0, newarray, 0, array.length);
  +        return newarray;
  +    }
   
       private boolean ensureAttrDeclCapacity(int chunk) {
           if (chunk >= fAttrDecl.length) {
  @@ -303,6 +336,7 @@
       public void reset(){
           fElementDeclIndex = 0;
           fParticleDeclIndex = 0;
  +        fModelGroupIndex = 0;
           fSTDeclIndex = 0;
           fCTDeclIndex = 0;
           fAttrDeclIndex = 0;
  
  
  
  1.4       +3 -3      xml-xerces/java/src/org/apache/xerces/impl/xs/XSGroupDecl.java
  
  Index: XSGroupDecl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XSGroupDecl.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XSGroupDecl.java	29 Jan 2002 01:15:14 -0000	1.3
  +++ XSGroupDecl.java	26 Apr 2002 22:03:42 -0000	1.4
  @@ -62,7 +62,7 @@
    * schema component is a global <group> element information item
    *
    * @author Sandy Gao, IBM
  - * @version $Id: XSGroupDecl.java,v 1.3 2002/01/29 01:15:14 lehors Exp $
  + * @version $Id: XSGroupDecl.java,v 1.4 2002/04/26 22:03:42 sandygao Exp $
    */
   public class XSGroupDecl {
   
  @@ -70,7 +70,7 @@
       public String fName = null;
       // target namespace of the group
       public String fTargetNamespace = null;
  -    // particle of the group
  -    public XSParticleDecl fParticle = null;
  +    // model group of the group
  +    public XSModelGroup fModelGroup = null;
   
   } // class XSGroupDecl
  
  
  
  1.7       +33 -136   xml-xerces/java/src/org/apache/xerces/impl/xs/XSParticleDecl.java
  
  Index: XSParticleDecl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/XSParticleDecl.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XSParticleDecl.java	22 Apr 2002 22:43:24 -0000	1.6
  +++ XSParticleDecl.java	26 Apr 2002 22:03:42 -0000	1.7
  @@ -62,7 +62,7 @@
    *
    * @author Sandy Gao, IBM
    *
  - * @version $Id: XSParticleDecl.java,v 1.6 2002/04/22 22:43:24 sandygao Exp $
  + * @version $Id: XSParticleDecl.java,v 1.7 2002/04/26 22:03:42 sandygao Exp $
    */
   public class XSParticleDecl {
   
  @@ -70,59 +70,33 @@
       public static final short PARTICLE_EMPTY        = 0;
       public static final short PARTICLE_ELEMENT      = 1;
       public static final short PARTICLE_WILDCARD     = 2;
  -    public static final short PARTICLE_CHOICE       = 3;
  -    public static final short PARTICLE_SEQUENCE     = 4;
  -    public static final short PARTICLE_ALL          = 5;
  -    public static final short PARTICLE_ZERO_OR_ONE  = 6;
  -    public static final short PARTICLE_ZERO_OR_MORE = 7;
  -    public static final short PARTICLE_ONE_OR_MORE  = 8;
  +    public static final short PARTICLE_MODELGROUP   = 3;
  +    public static final short PARTICLE_ZERO_OR_MORE = 4;
  +    public static final short PARTICLE_ZERO_OR_ONE  = 5;
  +    public static final short PARTICLE_ONE_OR_MORE  = 6;
   
       // type of the particle
       public short fType = PARTICLE_EMPTY;
  -    // left-hand value of the particle
  +    
  +    // term of the particle
       // for PARTICLE_ELEMENT : the element decl
       // for PARTICLE_WILDCARD: the wildcard decl
  -    // for PARTICLE_CHOICE/SEQUENCE/ALL: the particle of the first child
  -    // for PARTICLE_?*+: the child particle
  +    // for PARTICLE_MODELGROUP: the model group
       public Object fValue = null;
  -    // for PARTICLE_CHOICE/SEQUENCE/ALL: the particle of the other child
  -    public Object fOtherValue = null;
  +
       // minimum occurrence of this particle
       public int fMinOccurs = 1;
       // maximum occurrence of this particle
       public int fMaxOccurs = 1;
   
       // clone this decl
  -    public XSParticleDecl clone(boolean deep) {
  +    public XSParticleDecl makeClone() {
           XSParticleDecl particle = new XSParticleDecl();
           particle.fType = fType;
           particle.fMinOccurs = fMinOccurs;
           particle.fMaxOccurs = fMaxOccurs;
           particle.fDescription = fDescription;
  -        // if it's not a deep clone, or it's a leaf particle
  -        // just copy value and other value
  -        if (!deep ||
  -            fType == PARTICLE_EMPTY ||
  -            fType == PARTICLE_ELEMENT ||
  -            fType == PARTICLE_WILDCARD) {
  -            particle.fValue = fValue;
  -            particle.fOtherValue = fOtherValue;
  -        }
  -        // otherwise, we have to make clones of value and other value
  -        else {
  -            if (fValue != null) {
  -                particle.fValue = ((XSParticleDecl)fValue).clone(deep);
  -            }
  -            else {
  -                particle.fValue = null;
  -            }
  -            if (fOtherValue != null) {
  -                particle.fOtherValue = ((XSParticleDecl)fOtherValue).clone(deep);
  -            }
  -            else {
  -                particle.fOtherValue = null;
  -            }
  -        }
  +        particle.fValue = fValue;
           return particle;
       }
       
  @@ -134,16 +108,14 @@
           return minEffectiveTotalRange() == 0;
       }
   
  +    // whether this particle contains nothing
       public boolean isEmpty() {
  -        if (fType==PARTICLE_ELEMENT || fType==PARTICLE_WILDCARD) return false; 
  +        if (fType == PARTICLE_EMPTY)
  +             return true;
  +        if (fType == PARTICLE_ELEMENT || fType == PARTICLE_WILDCARD)
  +            return false; 
   
  -        if (fType==PARTICLE_EMPTY) return true; 
  -        
  -        boolean leftIsEmpty  = (fValue==null || ((XSParticleDecl)fValue).isEmpty());
  -        boolean rightIsEmpty  = (fOtherValue==null || 
  -                                 ((XSParticleDecl)fOtherValue).isEmpty());
  -
  -        return (leftIsEmpty && rightIsEmpty) ;
  +        return ((XSModelGroup)fValue).isEmpty();
       }
   
       /**
  @@ -154,79 +126,22 @@
        * values from the spec are retrievable by these methods.
        */
       public int minEffectiveTotalRange() {
  -        switch (fType) {
  -        case PARTICLE_ALL:
  -        case PARTICLE_SEQUENCE:
  -            return minEffectiveTotalRangeAllSeq();
  -        case PARTICLE_CHOICE:
  -            return minEffectiveTotalRangeChoice();
  -        default:
  -            return fMinOccurs;
  -        }
  -    }
  -
  -    private int minEffectiveTotalRangeAllSeq() {
  -        int fromLeft = ((XSParticleDecl)fValue).minEffectiveTotalRange();
  -        if (fOtherValue != null)
  -            fromLeft += ((XSParticleDecl)fOtherValue).minEffectiveTotalRange();
  -        return fMinOccurs * fromLeft;
  -    }
  -
  -    private int minEffectiveTotalRangeChoice() {
  -        int fromLeft = ((XSParticleDecl)fValue).minEffectiveTotalRange();
  -        if (fOtherValue != null) {
  -            int fromRight = ((XSParticleDecl)fOtherValue).minEffectiveTotalRange();
  -            if (fromRight < fromLeft)
  -                fromLeft = fromRight;
  +        if (fType == PARTICLE_MODELGROUP) {
  +            return ((XSModelGroup)fValue).minEffectiveTotalRange() * fMinOccurs;
           }
  -        return fMinOccurs * fromLeft;
  +        return fMinOccurs;
       }
   
       public int maxEffectiveTotalRange() {
  -        switch (fType) {
  -        case PARTICLE_ALL:
  -        case PARTICLE_SEQUENCE:
  -            return maxEffectiveTotalRangeAllSeq();
  -        case PARTICLE_CHOICE:
  -            return maxEffectiveTotalRangeChoice();
  -        default:
  -            return fMaxOccurs;
  -        }
  -    }
  -
  -    private int maxEffectiveTotalRangeAllSeq() {
  -        int fromLeft = ((XSParticleDecl)fValue).maxEffectiveTotalRange();
  -        if (fromLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  -            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -        if (fOtherValue != null) {
  -            int fromRight = ((XSParticleDecl)fOtherValue).maxEffectiveTotalRange();
  -            if (fromRight == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  +        if (fType == PARTICLE_MODELGROUP) {
  +            int max = ((XSModelGroup)fValue).maxEffectiveTotalRange();
  +            if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
                   return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -            fromLeft += fromRight;
  -        }
  -
  -        if (fromLeft != 0 && fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  -            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -
  -        return fMaxOccurs * fromLeft;
  -    }
  -
  -    private int maxEffectiveTotalRangeChoice() {
  -        int fromLeft = ((XSParticleDecl)fValue).maxEffectiveTotalRange();
  -        if (fromLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  -            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -        if (fOtherValue != null) {
  -            int fromRight = ((XSParticleDecl)fOtherValue).maxEffectiveTotalRange();
  -            if (fromRight == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  +            if (max != 0 && fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)
                   return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -            if (fromRight < fromLeft)
  -                fromLeft = fromRight;
  +            return max * fMaxOccurs;
           }
  -
  -        if (fromLeft != 0 && fMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)
  -            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -
  -        return fMaxOccurs * fromLeft;
  +        return fMaxOccurs;
       }
   
       /**
  @@ -255,46 +170,28 @@
        * append the string description of this particle to the string buffer
        * this is for error message.
        */
  -    void appendParticle(StringBuffer fBuffer) {
  +    void appendParticle(StringBuffer buffer) {
           switch (fType) {
           case PARTICLE_EMPTY:
  -            fBuffer.append("EMPTY");
  +            buffer.append("EMPTY");
               break;
           case PARTICLE_ELEMENT:
           case PARTICLE_WILDCARD:
  -            fBuffer.append('(');
  -            fBuffer.append(fValue.toString());
  -            fBuffer.append(')');
  +            buffer.append('(');
  +            buffer.append(fValue.toString());
  +            buffer.append(')');
               break;
  -        case PARTICLE_CHOICE:
  -        case PARTICLE_SEQUENCE:
  -        case PARTICLE_ALL:
  -            if (fOtherValue == null) {
  -                fBuffer.append(fValue.toString());
  -            } else {
  -                if (fType == PARTICLE_ALL)
  -                    fBuffer.append("all(");
  -                else
  -                    fBuffer.append('(');
  -                fBuffer.append(fValue.toString());
  -                if (fType == PARTICLE_CHOICE)
  -                    fBuffer.append('|');
  -                else
  -                    fBuffer.append(',');
  -                fBuffer.append(fOtherValue.toString());
  -                fBuffer.append(')');
  -            }
  +        case PARTICLE_MODELGROUP:
  +            buffer.append(fValue.toString());
               break;
           }
       }
   
  -
       public void reset(){
           fType = PARTICLE_EMPTY;
           fValue = null;
  -        fOtherValue = null;
           fMinOccurs = 1;
           fMaxOccurs = 1;
  -
  +        fDescription = null;
       }
   } // class XSParticle
  
  
  
  1.1                  xml-xerces/java/src/org/apache/xerces/impl/xs/XSModelGroup.java
  
  Index: XSModelGroup.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001, 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation and was
   * originally based on software copyright (c) 2001, International
   * Business Machines, Inc., http://www.apache.org.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.xerces.impl.xs;
  
  /**
   * Store schema model group declaration.
   *
   * @author Sandy Gao, IBM
   *
   * @version $Id: XSModelGroup.java,v 1.1 2002/04/26 22:03:42 sandygao Exp $
   */
  public class XSModelGroup {
  
      // types of model groups
      // REVISIT: can't use same constants as those in XSParticleDecl, because
      // there are place where the constants are used together. For example,
      // to check whether the content is an element or a sequence.
      public static final short MODELGROUP_CHOICE       = 11;
      public static final short MODELGROUP_SEQUENCE     = 12;
      public static final short MODELGROUP_ALL          = 13;
  
      // compositor of the model group
      public short fCompositor;
      
      // particles
      public XSParticleDecl[] fParticles = null;
      public int fParticleCount = 0;
  
      // whether this model group contains nothing
      public boolean isEmpty() {
          for (int i = 0; i < fParticleCount; i++) {
              if (!fParticles[i].isEmpty())
                  return false;
          }
          return true;
      }
  
      /**
       * 3.8.6 Effective Total Range (all and sequence) and
       *       Effective Total Range (choice)
       * The following methods are used to return min/max range for a particle.
       * They are not exactly the same as it's described in the spec, but all the
       * values from the spec are retrievable by these methods.
       */
      public int minEffectiveTotalRange() {
          if (fCompositor == MODELGROUP_CHOICE)
              return minEffectiveTotalRangeChoice();
          else
              return minEffectiveTotalRangeAllSeq();
      }
  
      // return the sum of all min values of the particles
      private int minEffectiveTotalRangeAllSeq() {
          int total = 0;
          for (int i = 0; i < fParticleCount; i++)
              total += fParticles[i].minEffectiveTotalRange();
          return total;
      }
  
      // return the min of all min values of the particles
      private int minEffectiveTotalRangeChoice() {
          int min = 0, one;
          if (fParticles.length > 0)
              min = fParticles[0].minEffectiveTotalRange();
          
          for (int i = 1; i < fParticleCount; i++) {
              one = fParticles[i].minEffectiveTotalRange();
              if (one < min)
                  min = one;
          }
  
          return min;
      }
  
      public int maxEffectiveTotalRange() {
          if (fCompositor == MODELGROUP_CHOICE)
              return maxEffectiveTotalRangeChoice();
          else
              return maxEffectiveTotalRangeAllSeq();
      }
  
      // if one of the max value of the particles is unbounded, return unbounded;
      // otherwise return the sum of all max values
      private int maxEffectiveTotalRangeAllSeq() {
          int total = 0, one;
          for (int i = 0; i < fParticleCount; i++) {
              one = fParticles[i].maxEffectiveTotalRange();
              if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
                  return SchemaSymbols.OCCURRENCE_UNBOUNDED;
              total += one;
          }
          return total;
      }
  
      // if one of the max value of the particles is unbounded, return unbounded;
      // otherwise return the max of all max values
      private int maxEffectiveTotalRangeChoice() {
          int max = 0, one;
          if (fParticles.length > 0) {
              max = fParticles[0].minEffectiveTotalRange();
              if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
                  return SchemaSymbols.OCCURRENCE_UNBOUNDED;
          }
  
          for (int i = 1; i < fParticleCount; i++) {
              one = fParticles[i].maxEffectiveTotalRange();
              if (one == SchemaSymbols.OCCURRENCE_UNBOUNDED)
                  return SchemaSymbols.OCCURRENCE_UNBOUNDED;
              if (one > max)
                  max = one;
          }
          return max;
      }
  
      /**
       * get the string description of this particle
       */
      private String fDescription = null;
      public String toString() {
          if (fDescription == null) {
              StringBuffer buffer = new StringBuffer();
              if (fCompositor == MODELGROUP_ALL)
                  buffer.append("all(");
              else
                  buffer.append('(');
              if (fParticles.length > 0)
                  buffer.append(fParticles[0].toString());
              for (int i = 1; i < fParticleCount; i++) {
                  if (fCompositor == MODELGROUP_CHOICE)
                      buffer.append('|');
                  else
                      buffer.append(',');
                  buffer.append(fParticles[i].toString());
              }
              buffer.append(')');
              fDescription = buffer.toString();
          }
          return fDescription;
      }
  
      public void reset(){
          fCompositor = MODELGROUP_SEQUENCE;
          fParticles = null;
          fParticleCount = 0;
          fDescription = null;
      }
      
  } // class XSParticle
  
  
  
  1.8       +167 -375  xml-xerces/java/src/org/apache/xerces/impl/xs/models/CMBuilder.java
  
  Index: CMBuilder.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/models/CMBuilder.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- CMBuilder.java	3 Apr 2002 23:48:27 -0000	1.7
  +++ CMBuilder.java	26 Apr 2002 22:03:42 -0000	1.8
  @@ -63,6 +63,7 @@
   import org.apache.xerces.impl.xs.XSDeclarationPool;
   import org.apache.xerces.impl.xs.XSComplexTypeDecl;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   import org.apache.xerces.impl.xs.XSElementDecl;
   import org.apache.xerces.impl.xs.models.*;
   
  @@ -70,456 +71,247 @@
    * This class constructs content models for a given grammar.
    *
    * @author Elena Litani, IBM
  - * @version $Id: CMBuilder.java,v 1.7 2002/04/03 23:48:27 elena Exp $
  + * @author Sandy Gao, IBM
  + * 
  + * @version $Id: CMBuilder.java,v 1.8 2002/04/26 22:03:42 sandygao Exp $
    */
   public class CMBuilder {
   
  -    private final QName fQName1 = new QName();
  -    private final QName fQName2 = new QName();
  -
  +    // REVISIT: should update the decl pool to cache XSCM objects too
       private XSDeclarationPool fDeclPool = null;
  +    
  +    // It never changes, so a static member is good enough
  +    private static XSEmptyCM fEmptyCM = new XSEmptyCM();
   
       // needed for DFA construction
       private int fLeafCount;
  -                           
  -    public CMBuilder (XSDeclarationPool pool){
  +    // needed for UPA
  +    private int fParticleCount;
  +
  +    public CMBuilder(XSDeclarationPool pool) {
           fDeclPool = pool;
       }
   
  -    public void setDeclPool (XSDeclarationPool declPool){
  +    public void setDeclPool(XSDeclarationPool declPool) {
           fDeclPool = declPool;
       }
   
       /**
        * Get content model for the a given type
        *
  -     * @param elementDeclIndex
  -     * @param comparator
  -     * @return a content model validator
  -     * @exception RuntimeException
  +     * @param typeDecl  get content model for which complex type 
  +     * @return          a content model validator
        */
       public XSCMValidator getContentModel(XSComplexTypeDecl typeDecl) {
   
  +        // for complex type with empty or simple content,
  +        // there is no content model validator
           short contentType = typeDecl.fContentType;
           if (contentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE ||
               contentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY) {
               return null;
           }
   
  -        XSCMValidator cmValidator = null;
  -
           XSParticleDecl particle = typeDecl.fParticle;
  -
  -        // This check is performed in XSComplexTypeDecl.
  -        //if (cmValidator != null)
  -        //    return cmValidator;
  -
  -
  -        if (particle != null)
  -            particle = expandParticleTree( (XSParticleDecl)particle);
  -
  -        // And create the content model according to the spec type
  -
  -        if (particle == null) {
  -            // create special content model for no element content
  -            cmValidator = new XSEmptyCM();
  -        }
  -        else if (contentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
  -               //
  -              // Create a child model as
  -              // per the element-only case
  -            cmValidator = createChildModel(particle, true);
  -        }
  -        else if (contentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
  -            //  This method will create an optimal model for the complexity
  -            //  of the element's defined model. If its simple, it will create
  -            //  a SimpleContentModel object. If its a simple list, it will
  -            //  create a SimpleListContentModel object. If its complex, it
  -            //  will create a DFAContentModel object.
  -            //
  -            cmValidator = createChildModel(particle, false);
  +        
  +        // if the content is element only or mixed, but no particle
  +        // is defined, return the empty content model
  +        if (particle == null)
  +            return fEmptyCM;
  +        
  +        // if the content model contains "all" model group,
  +        // we create an "all" content model, otherwise a DFA content model
  +        XSCMValidator cmValidator = null;
  +        if (particle.fType == XSParticleDecl.PARTICLE_MODELGROUP &&
  +            ((XSModelGroup)particle.fValue).fCompositor == XSModelGroup.MODELGROUP_ALL) {
  +            cmValidator = createAllCM(particle);
           }
           else {
  -            throw new RuntimeException("Unknown content type for a element decl "
  -                                       + "in getElementContentModelValidator() in Grammar class");
  +            cmValidator = createDFACM(particle);
           }
   
  +        // if the validator returned is null, it means there is nothing in
  +        // the content model, so we return the empty content model.
  +        if (cmValidator == null)
  +            cmValidator = fEmptyCM;
  +            
           return cmValidator;
       }
   
  +    XSCMValidator createAllCM(XSParticleDecl particle) {
  +        if (particle.fMaxOccurs == 0)
  +            return null;
   
  -    private XSParticleDecl expandParticleTree( XSParticleDecl particle) {
  +        // create an all content model. the parameter indicates whether
  +        // the <all> itself is optional        
  +        XSAllCM allContent = new XSAllCM(particle.fMinOccurs == 0);
  +        
  +        // get the model group, and add all children of it to the content model
  +        XSModelGroup group = (XSModelGroup)particle.fValue;
  +        for (int i = 0; i < group.fParticleCount; i++) {
  +            // for all non-empty particles
  +            if (group.fParticles[i].fType != XSParticleDecl.PARTICLE_EMPTY &&
  +                group.fParticles[i].fMaxOccurs != 0)
  +                // add the element decl to the all content model
  +                allContent.addElement((XSElementDecl)group.fParticles[i].fValue,
  +                                      group.fParticles[i].fMinOccurs == 0);
  +        }
  +        return allContent;
  +    }
  +    
  +    XSCMValidator createDFACM(XSParticleDecl particle) {
  +        fLeafCount = 0;
  +        fParticleCount = 0;
  +        // convert particle tree to CM tree
  +        CMNode node = buildSyntaxTree(particle);
  +        if (node == null)
  +            return null;
  +        // build DFA content model from the CM tree
  +        return new XSDFACM(node, fLeafCount);
  +    }
   
  -        // We may want to consider trying to combine this with buildSyntaxTree at some
  -        // point (if possible)
  +    // 1. convert particle tree to CM tree:
  +    // 2. expand all occurrence values: a{n, unbounded} -> a, a, ..., a+
  +    //                                  a{n, m} -> a, a, ..., a?, a?, ...
  +    // 3. convert model groups (a, b, c, ...) or (a | b | c | ...) to
  +    //    binary tree: (((a,b),c),...) or (((a|b)|c)|...)
  +    // 4. make sure each leaf node (XSCMLeaf) has a distinct position
  +    private CMNode buildSyntaxTree(XSParticleDecl particle) {
   
           int maxOccurs = particle.fMaxOccurs;
           int minOccurs = particle.fMinOccurs;
           short type = particle.fType;
  +        CMNode nodeRet = null;
  +        
           if ((type == XSParticleDecl.PARTICLE_WILDCARD) ||
               (type == XSParticleDecl.PARTICLE_ELEMENT)) {
  -            // Make a clone of the leaf particle, so that if there are two
  -            // references to the same group, we have two different leaf
  -            // particles for the same element or wildcard decl.
  +            // (task 1) element and wildcard particles should be converted to
  +            // leaf nodes
  +            // REVISIT: Make a clone of the leaf particle, so that if there
  +            // are two references to the same group, we have two different
  +            // leaf particles for the same element or wildcard decl.
               // This is useful for checking UPA.
  -            //return expandContentModel(particle.clone(false), minOccurs, maxOccurs);
  -            return expandContentModel(particle, minOccurs, maxOccurs);
  -        }
  -        else if (type == XSParticleDecl.PARTICLE_CHOICE ||
  -                 type == XSParticleDecl.PARTICLE_ALL ||
  -                 type == XSParticleDecl.PARTICLE_SEQUENCE) {
  -
  -            Object left = particle.fValue;
  -            Object right = particle.fOtherValue;
  -
  -            left =  expandParticleTree( (XSParticleDecl)left);
  -            if (right != null)
  -                right =  expandParticleTree( (XSParticleDecl)right);
  -
  -            // At this point, by expanding the particle tree, we may have a null left or right
  -            if (left==null && right==null)
  -                return null;
  -
  -            if (left == null)
  -                return expandContentModel((XSParticleDecl)right, minOccurs, maxOccurs);
  -
  -            if (right == null)
  -                return expandContentModel((XSParticleDecl)left, minOccurs, maxOccurs);
  -
  -            XSParticleDecl newParticle;
  -            if (fDeclPool !=null) {
  -                newParticle = fDeclPool.getParticleDecl();
  -            } else {            
  -                newParticle = new XSParticleDecl();
  -            }
  -            newParticle.fType = particle.fType;
  -            newParticle.fValue = left;
  -            newParticle.fOtherValue = right;
  -            return expandContentModel((XSParticleDecl)newParticle, minOccurs, maxOccurs);
  -        }
  -        else if (type == XSParticleDecl.PARTICLE_EMPTY) {
  -            return null;
  -        }
  -
  -        return particle;
  -    }
  -
  -
  -
  -    /**
  -     * When the element has a 'CONTENTTYPE_ELEMENT' model, this method is called to
  -     * create the content model object. It looks for some special case simple
  -     * models and creates SimpleContentModel objects for those. For the rest
  -     * it creates the standard DFA style model.
  -     *
  -     * @param grammar
  -     * @param fParticleIndex
  -     * @return
  -     */
  -    private XSCMValidator createChildModel(XSParticleDecl particle, boolean isMixed) {
  -
  -        //
  -        //  Get the content spec node for the element we are working on.
  -        //  This will tell us what kind of node it is, which tells us what
  -        //  kind of model we will try to create.
  -        //
  -        //XMLContentSpec fParticle = new XMLContentSpec();
  -        short type = particle.fType;
  -        if (type == XSParticleDecl.PARTICLE_WILDCARD) {
  -            // let fall through to build a DFAContentModel
  -        }
  -        else if (isMixed) {
  -            if (type ==XSParticleDecl.PARTICLE_ALL) {
  -                // All the nodes under an ALL must be additional ALL nodes and
  -                // ELEMENTs (or ELEMENTs under ZERO_OR_ONE nodes.)
  -                // We collapse the ELEMENTs into a single vector.
  -                XSAllCM allContent = new XSAllCM(false);
  -                gatherAllLeaves ((XSParticleDecl)(particle.fValue), allContent);
  -                gatherAllLeaves ((XSParticleDecl)(particle.fOtherValue), allContent);
  -                return allContent;
  -
  -            }
  -            else if (type == XSParticleDecl.PARTICLE_ZERO_OR_ONE) {
  -                 XSParticleDecl left = (XSParticleDecl)particle.fValue;
  -
  -
  -                // An ALL node can appear under a ZERO_OR_ONE node.
  -                if (type ==XSParticleDecl.PARTICLE_ALL) {
  -                    XSAllCM allContent = new XSAllCM(true);
  -                    gatherAllLeaves (left, allContent);
  -                    return allContent;
  -
  +            nodeRet = new XSCMLeaf(particle.fType, particle.fValue, fParticleCount++, fLeafCount++);
  +            // (task 2) expand occurrence values
  +            nodeRet = expandContentModel(nodeRet, minOccurs, maxOccurs);
  +        }
  +        else if (type == XSParticleDecl.PARTICLE_MODELGROUP) {
  +            // (task 1,3) convert model groups to binary trees
  +            XSModelGroup group = (XSModelGroup)particle.fValue;
  +            CMNode temp = null;
  +            for (int i = 0; i < group.fParticleCount; i++) {
  +                // first convert each child to a CM tree
  +                temp = buildSyntaxTree(group.fParticles[i]);
  +                // then combine them using binary operation
  +                if (temp != null) {
  +                    if (nodeRet == null) {
  +                        nodeRet = temp;
  +                    }
  +                    else {
  +                        nodeRet = new XSCMBinOp(group.fCompositor, nodeRet, temp);
  +                    }
                   }
               }
  -            // otherwise, let fall through to build a DFAContentModel
  +            // (task 2) expand occurrence values
  +            if (nodeRet != null)
  +                nodeRet = expandContentModel(nodeRet, minOccurs, maxOccurs);
           }
  -        else if (type == XSParticleDecl.PARTICLE_ELEMENT) {
  -            //
  -            //  Check that the left value is not null, since any content model
  -            //  with PCDATA should be MIXED, so we should not have gotten here.
  -            //
  -            if (particle.fValue == null &&
  -                particle.fOtherValue == null)
  -                throw new RuntimeException("ImplementationMessages.VAL_NPCD");
  -
  -            //
  -            //  Its a single leaf, so its an 'a' type of content model, i.e.
  -            //  just one instance of one element. That one is definitely a
  -            //  simple content model.
  -            //
  -            // pass element declaration
  -
  -            return new XSSimpleCM(type, (XSElementDecl)particle.fValue);
  -        }
  -        else if ((type == XSParticleDecl.PARTICLE_CHOICE)
  -                 ||  (type == XSParticleDecl.PARTICLE_SEQUENCE)) {
  -            //
  -            //  Lets see if both of the children are leafs. If so, then it
  -            //  it has to be a simple content model
  -            //
  -            XSParticleDecl left = (XSParticleDecl)particle.fValue;
  -            XSParticleDecl right = (XSParticleDecl)particle.fOtherValue;
  -
  -            if ((right.fType == XSParticleDecl.PARTICLE_ELEMENT)
  -                &&  (left.fType == XSParticleDecl.PARTICLE_ELEMENT)) {
  -                //
  -                //  Its a simple choice or sequence, so we can do a simple
  -                //  content model for it.
  -                //
  -                // pass both element decls
  -                return new XSSimpleCM(type, (XSElementDecl)left.fValue, (XSElementDecl)right.fValue);
  -            }
  -
  -        }
  -    else if (type == XSParticleDecl.PARTICLE_ALL) {
   
  -            XSParticleDecl left = (XSParticleDecl)particle.fValue;
  -            XSParticleDecl right = (XSParticleDecl)particle.fOtherValue;
  -
  -            XSAllCM allContent = new XSAllCM(false);
  -
  -            gatherAllLeaves (left, allContent);
  -            gatherAllLeaves (right, allContent);
  -            return allContent;
  -        }
  -        else if ((type == XSParticleDecl.PARTICLE_ZERO_OR_ONE)
  -                 ||  (type == XSParticleDecl.PARTICLE_ZERO_OR_MORE)
  -                 ||  (type == XSParticleDecl.PARTICLE_ONE_OR_MORE)) {
  -            //
  -            //  Its a repetition, so see if its one child is a leaf. If so
  -            //  its a repetition of a single element, so we can do a simple
  -            //  content model for that.
  -            XSParticleDecl left = (XSParticleDecl) particle.fValue;
  -
  -            if (left.fType == XSParticleDecl.PARTICLE_ELEMENT) {
  -                //
  -                //  It is, so we can create a simple content model here that
  -                //  will check for this repetition. We pass -1 for the unused
  -                //  right node.
  -                //
  -                return new XSSimpleCM(type, (XSElementDecl)left.fValue);
  -            }
  -            else if (left.fType==XSParticleDecl.PARTICLE_ALL) {
  -                 XSAllCM allContent = new XSAllCM(true);
  -                gatherAllLeaves (left, allContent);
  -                return allContent;
  -            }
  -
  -
  -        }
  -        else {
  -            throw new RuntimeException("ImplementationMessages.VAL_CST");
  -        }
  -
  -        //
  -        //  Its not a simple content model, so here we have to create a DFA
  -        //  for this element. So we create a DFAContentModel object. He
  -        //  encapsulates all of the work to create the DFA.
  -        //
  -
  -        fLeafCount = 0;
  -        CMNode node = buildSyntaxTree(particle);
  -        return new XSDFACM(node, fLeafCount, isMixed);
  +        return nodeRet;
       }
   
  +    // 2. expand all occurrence values: a{n, unbounded} -> a, a, ..., a+
  +    //                                  a{n, m} -> a, a, ..., a?, a?, ...
  +    // 4. make sure each leaf node (XSCMLeaf) has a distinct position
  +    private CMNode expandContentModel(CMNode node,
  +                                      int minOccurs, int maxOccurs) {
   
  +        CMNode nodeRet = null;
   
  -    private XSParticleDecl expandContentModel(XSParticleDecl particle,
  -                                              int minOccurs, int maxOccurs) {
  -
  -        XSParticleDecl leafParticle = particle;
  -        XSParticleDecl optional = null;
           if (minOccurs==1 && maxOccurs==1) {
  -            return particle;
  +            nodeRet = node;
           }
           else if (minOccurs==0 && maxOccurs==1) {
               //zero or one
  -            return createParticle ( XSParticleDecl.PARTICLE_ZERO_OR_ONE,particle,null);
  +            nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node);
           }
           else if (minOccurs == 0 && maxOccurs==SchemaSymbols.OCCURRENCE_UNBOUNDED) {
               //zero or more
  -            return createParticle (XSParticleDecl.PARTICLE_ZERO_OR_MORE, particle, null);
  +            nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_MORE, node);
           }
           else if (minOccurs == 1 && maxOccurs==SchemaSymbols.OCCURRENCE_UNBOUNDED) {
               //one or more
  -            return createParticle (XSParticleDecl.PARTICLE_ONE_OR_MORE, particle, null);
  +            nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ONE_OR_MORE, node);
           }
           else if (maxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED) {
               // => a,a,..,a+
  -            particle = createParticle (XSParticleDecl.PARTICLE_ONE_OR_MORE,
  -                                       particle, null);
  -
  -            for (int i=0; i < (minOccurs-1); i++) {
  -                particle = createParticle (XSParticleDecl.PARTICLE_SEQUENCE, leafParticle, particle);
  +            // create a+ node first, then put minOccurs-1 a's in front of it
  +            // for the first time "node" is used, we don't need to make a copy
  +            // and for other references to node, we make copies
  +            nodeRet = new XSCMUniOp(XSParticleDecl.PARTICLE_ONE_OR_MORE, node);
  +            for (int i=0; i < minOccurs-1; i++) {
  +                // (task 4) we need to call copyNode here, so that we append
  +                // an entire new copy of the node (a subtree). this is to ensure
  +                // all leaf nodes have distinct position
  +                nodeRet = new XSCMBinOp(XSModelGroup.MODELGROUP_SEQUENCE,
  +                                        copyNode(node), nodeRet);
               }
  -            return particle;
  -
           }
           else {
               // {n,m} => a,a,a,...(a),(a),...
  -
  -
  -            if (minOccurs==0) {
  -                optional = createParticle (XSParticleDecl.PARTICLE_ZERO_OR_ONE,
  -                                           leafParticle,
  -                                           null);
  -                particle = optional;
  -                for (int i=0; i < (maxOccurs-minOccurs-1); i++) {
  -                    particle = createParticle (XSParticleDecl.PARTICLE_SEQUENCE,
  -                                               particle,
  -                                               optional);
  +            // first n a's, then m-n a?'s.
  +            // copyNode is called, for the same reason as above
  +            if (minOccurs > 0) {
  +                nodeRet = node;
  +                for (int i=0; i<minOccurs-1; i++) {
  +                    nodeRet = new XSCMBinOp(XSModelGroup.MODELGROUP_SEQUENCE,
  +                                            nodeRet, copyNode(node));
                   }
               }
  -            else {
  -                for (int i=0; i<(minOccurs-1); i++) {
  -                    particle = createParticle (XSParticleDecl.PARTICLE_SEQUENCE,
  -                                               particle,
  -                                               leafParticle);
  +            if (maxOccurs > minOccurs) {
  +                node = new XSCMUniOp(XSParticleDecl.PARTICLE_ZERO_OR_ONE, node);
  +                if (nodeRet == null) {
  +                    nodeRet = node;
                   }
  -
  -                optional = createParticle(XSParticleDecl.PARTICLE_ZERO_OR_ONE,
  -                                          leafParticle,
  -                                          null);
  -
  -                for (int i=0; i < (maxOccurs-minOccurs); i++) {
  -                    particle = createParticle(XSParticleDecl.PARTICLE_SEQUENCE,
  -                                              particle,
  -                                              optional);
  +                else {
  +                    nodeRet = new XSCMBinOp(XSModelGroup.MODELGROUP_SEQUENCE,
  +                                            nodeRet, copyNode(node));
  +                }
  +                for (int i=minOccurs; i<maxOccurs-1; i++) {
  +                    nodeRet = new XSCMBinOp(XSModelGroup.MODELGROUP_SEQUENCE,
  +                                            nodeRet, node);
                   }
               }
           }
   
  -        return particle;
  -    }
  -
  -    /**
  -     *  Recursively builds an AllContentModel based on a particle tree
  -     *  rooted at an ALL node.
  -     */
  -     private void gatherAllLeaves(XSParticleDecl particle,
  -                                        XSAllCM allContent) {
  -        Object left = particle.fValue;
  -        Object right = particle.fOtherValue;
  -        int type = particle.fType;
  -
  -        if (type == XSParticleDecl.PARTICLE_ALL) {
  -
  -            // At an all node, visit left and right subtrees
  -            gatherAllLeaves ((XSParticleDecl)left, allContent);
  -            gatherAllLeaves ((XSParticleDecl) particle.fOtherValue, allContent);
  -        }
  -        else if (type == XSParticleDecl.PARTICLE_ELEMENT) {
  -
  -            // At leaf, add the element to list of elements permitted in the all
  -            allContent.addElement ((XSElementDecl)left, false);
  -        }
  -        else if (type == XSParticleDecl.PARTICLE_ZERO_OR_ONE) {
  -
  -            // At ZERO_OR_ONE node, subtree must be an element
  -            // that was specified with minOccurs=0, maxOccurs=1
  -            // Add the optional element to list of elements permitted in the all
  -
  -            if (((XSParticleDecl)left).fType == XSParticleDecl.PARTICLE_ELEMENT) {
  -                allContent.addElement ((XSElementDecl)(((XSParticleDecl)left).fValue), true);
  -            }
  -            else {
  -            // report error
  -        throw new RuntimeException("ImplementationMessages.VAL_CST");
  -            }
  -        }
  -        else {
  -            // report error
  -            throw new RuntimeException("ImplementationMessages.VAL_CSTA");
  -        }
  -    }
  -
  -    private XSParticleDecl createParticle (short type,
  -                                           XSParticleDecl left,
  -                                           XSParticleDecl right) {
  -
  -        XSParticleDecl newParticle;
  -        if (fDeclPool !=null) {
  -            newParticle = fDeclPool.getParticleDecl();
  -        } else {            
  -            newParticle = new XSParticleDecl();
  -        }
  -        newParticle.fType = type;
  -        newParticle.fValue = (Object) left;
  -        newParticle.fOtherValue = (Object)right;
  -        return newParticle;
  +        return nodeRet;
       }
  -
  -    // this method is needed to convert a tree of ParticleDecl
  -    // nodes into a tree of content models that XSDFACM methods can then use as input.
  -    private final CMNode buildSyntaxTree(XSParticleDecl startNode) {
  -
  -        // We will build a node at this level for the new tree
  -        CMNode nodeRet = null;
  -        if (startNode.fType == XSParticleDecl.PARTICLE_WILDCARD) {
  -            nodeRet = new XSCMLeaf(startNode, fLeafCount++);
  -        }
  -        //
  -        //  If this node is a leaf, then its an easy one. We just add it
  -        //  to the tree.
  -        //
  -        else if (startNode.fType == XSParticleDecl.PARTICLE_ELEMENT) {
  -            //
  -            //  Create a new leaf node, and pass it the current leaf count,
  -            //  which is its DFA state position. Bump the leaf count after
  -            //  storing it. This makes the positions zero based since we
  -            //  store first and then increment.
  -            //
  -            nodeRet = new XSCMLeaf(startNode, fLeafCount++);
  +    
  +    // 4. make sure each leaf node (XSCMLeaf) has a distinct position
  +    private CMNode copyNode(CMNode node) {
  +        int type = node.type();
  +        // for choice or sequence, copy the two subtrees, and combine them
  +        if (type == XSModelGroup.MODELGROUP_CHOICE ||
  +            type == XSModelGroup.MODELGROUP_SEQUENCE) {
  +            XSCMBinOp bin = (XSCMBinOp)node;
  +            node = new XSCMBinOp(type, copyNode(bin.getLeft()),
  +                                 copyNode(bin.getRight()));
  +        }
  +        // for ?+*, copy the subtree, and put it in a new ?+* node
  +        else if (type == XSParticleDecl.PARTICLE_ZERO_OR_MORE ||
  +                 type == XSParticleDecl.PARTICLE_ONE_OR_MORE ||
  +                 type == XSParticleDecl.PARTICLE_ZERO_OR_ONE) {
  +            XSCMUniOp uni = (XSCMUniOp)node;
  +            node = new XSCMUniOp(type, copyNode(uni.getChild()));
  +        }
  +        // for element/wildcard (leaf), make a new leaf node,
  +        // with a distinct position
  +        else if (type == XSParticleDecl.PARTICLE_ELEMENT ||
  +                 type == XSParticleDecl.PARTICLE_WILDCARD) {
  +            XSCMLeaf leaf = (XSCMLeaf)node;
  +            node = new XSCMLeaf(leaf.type(), leaf.getLeaf(), leaf.getParticleId(), fLeafCount++);
           }
  -        else {
  -            //
  -            //  Its not a leaf, so we have to recurse its left and maybe right
  -            //  nodes. Save both values before we recurse and trash the node.
  -            final XSParticleDecl leftNode = ((XSParticleDecl)startNode.fValue);
  -            final XSParticleDecl rightNode = ((XSParticleDecl)startNode.fOtherValue);
  -
  -            if ((startNode.fType == XSParticleDecl.PARTICLE_CHOICE)
  -                ||  (startNode.fType == XSParticleDecl.PARTICLE_SEQUENCE)) {
  -                //
  -                //  Recurse on both children, and return a binary op node
  -                //  with the two created sub nodes as its children. The node
  -                //  type is the same type as the source.
  -                //
  -
  -                nodeRet = new XSCMBinOp( startNode.fType, buildSyntaxTree(leftNode)
  -                                       , buildSyntaxTree(rightNode));
  -            }
  -            else if (startNode.fType == XSParticleDecl.PARTICLE_ZERO_OR_MORE
  -               || startNode.fType == XSParticleDecl.PARTICLE_ZERO_OR_ONE
  -               || startNode.fType == XSParticleDecl.PARTICLE_ONE_OR_MORE) {
  -                nodeRet = new XSCMUniOp(startNode.fType, buildSyntaxTree(leftNode));
  -            }
  -            else {
  -                throw new RuntimeException("ImplementationMessages.VAL_CST");
  -            }
  -        }
  -        // And return our new node for this level
  -        return nodeRet;
  +        
  +        return node;
       }
  -
   }
  
  
  
  1.3       +9 -8      xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSCMBinOp.java
  
  Index: XSCMBinOp.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSCMBinOp.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- XSCMBinOp.java	29 Jan 2002 01:15:16 -0000	1.2
  +++ XSCMBinOp.java	26 Apr 2002 22:03:42 -0000	1.3
  @@ -60,6 +60,7 @@
   import org.apache.xerces.impl.dtd.models.CMNode;
   import org.apache.xerces.impl.dtd.models.CMStateSet;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   
   /**
    *
  @@ -77,8 +78,8 @@
           super(type);
   
           // Insure that its one of the types we require
  -        if ((type() != XSParticleDecl.PARTICLE_CHOICE)
  -        &&  (type() != XSParticleDecl.PARTICLE_SEQUENCE)) {
  +        if ((type() != XSModelGroup.MODELGROUP_CHOICE)
  +        &&  (type() != XSModelGroup.MODELGROUP_SEQUENCE)) {
               throw new RuntimeException("ImplementationMessages.VAL_BST");
           }
   
  @@ -109,9 +110,9 @@
           //  this node is nullable. If its a concatenation, then both of
           //  them have to be nullable.
           //
  -        if (type() == XSParticleDecl.PARTICLE_CHOICE)
  +        if (type() == XSModelGroup.MODELGROUP_CHOICE)
               return (fLeftChild.isNullable() || fRightChild.isNullable());
  -        else if (type() == XSParticleDecl.PARTICLE_SEQUENCE)
  +        else if (type() == XSModelGroup.MODELGROUP_SEQUENCE)
               return (fLeftChild.isNullable() && fRightChild.isNullable());
           else
               throw new RuntimeException("ImplementationMessages.VAL_BST");
  @@ -122,12 +123,12 @@
       //  Protected, inherited methods
       // -------------------------------------------------------------------
       protected void calcFirstPos(CMStateSet toSet) {
  -        if (type() == XSParticleDecl.PARTICLE_CHOICE) {
  +        if (type() == XSModelGroup.MODELGROUP_CHOICE) {
               // Its the the union of the first positions of our children.
               toSet.setTo(fLeftChild.firstPos());
               toSet.union(fRightChild.firstPos());
           }
  -         else if (type() == XSParticleDecl.PARTICLE_SEQUENCE) {
  +         else if (type() == XSModelGroup.MODELGROUP_SEQUENCE) {
               //
               //  If our left child is nullable, then its the union of our
               //  children's first positions. Else is our left child's first
  @@ -143,12 +144,12 @@
       }
   
       protected void calcLastPos(CMStateSet toSet) {
  -        if (type() == XSParticleDecl.PARTICLE_CHOICE) {
  +        if (type() == XSModelGroup.MODELGROUP_CHOICE) {
               // Its the the union of the first positions of our children.
               toSet.setTo(fLeftChild.lastPos());
               toSet.union(fRightChild.lastPos());
           }
  -        else if (type() == XSParticleDecl.PARTICLE_SEQUENCE) {
  +        else if (type() == XSModelGroup.MODELGROUP_SEQUENCE) {
               //
               //  If our right child is nullable, then its the union of our
               //  children's last positions. Else is our right child's last
  
  
  
  1.4       +16 -11    xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSCMLeaf.java
  
  Index: XSCMLeaf.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSCMLeaf.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XSCMLeaf.java	29 Jan 2002 01:15:16 -0000	1.3
  +++ XSCMLeaf.java	26 Apr 2002 22:03:42 -0000	1.4
  @@ -76,8 +76,13 @@
       // Data
       //
   
  -    /** This is the leaf particle. */
  -    private XSParticleDecl fLeaf = null;
  +    /** This is the leaf: element decl or wildcard decl. */
  +    private Object fLeaf = null;
  +    
  +    /**
  +     * Identify the particle: for UPA checking
  +     */
  +    private int fParticleId = -1;
   
       /**
        * Part of the algorithm to convert a regex directly to a DFA
  @@ -91,26 +96,26 @@
       //
   
       /** Constructs a content model leaf. */
  -    public XSCMLeaf(XSParticleDecl leaf, int position)  {
  -        super(leaf.fType);
  +    public XSCMLeaf(int type, Object leaf, int id, int position)  {
  +        super(type);
   
           // Store the element index and position
           fLeaf = leaf;
  +        fParticleId = id;
           fPosition = position;
       }
   
  -    /** Constructs a content model leaf. */
  -    public XSCMLeaf(XSParticleDecl leaf)  {
  -        this(leaf, -1);
  -    }
  -
       //
       // Package methods
       //
   
  -    final XSParticleDecl getLeaf() {
  +    final Object getLeaf() {
           return fLeaf;
       }
  +    
  +    final int getParticleId() {
  +        return fParticleId;
  +    }
   
       final int getPosition() {
           return fPosition;
  @@ -132,7 +137,7 @@
       }
   
       public String toString() {
  -        StringBuffer strRet = new StringBuffer(fLeaf.fValue.toString());
  +        StringBuffer strRet = new StringBuffer(fLeaf.toString());
           if (fPosition >= 0) {
               strRet.append
               (
  
  
  
  1.5       +65 -92    xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSDFACM.java
  
  Index: XSDFACM.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/models/XSDFACM.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XSDFACM.java	15 Mar 2002 23:01:57 -0000	1.4
  +++ XSDFACM.java	26 Apr 2002 22:03:42 -0000	1.5
  @@ -64,6 +64,7 @@
   import org.apache.xerces.impl.xs.SubstitutionGroupHandler;
   import org.apache.xerces.impl.xs.XSElementDecl;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   import org.apache.xerces.impl.xs.XSWildcardDecl;
   import org.apache.xerces.impl.xs.XMLSchemaException;
   import org.apache.xerces.impl.xs.XSConstraints;
  @@ -75,7 +76,7 @@
    * it then uses in its validation algorithm.
    *
    * @author Neil Graham, IBM
  - * @version $Id: XSDFACM.java,v 1.4 2002/03/15 23:01:57 sandygao Exp $
  + * @version $Id: XSDFACM.java,v 1.5 2002/04/26 22:03:42 sandygao Exp $
    */
   public class XSDFACM
       implements XSCMValidator {
  @@ -103,7 +104,7 @@
        * actual validation.  Note tat since either XSElementDecl or XSParticleDecl object
        * can live here, we've got to use an Object.
        */
  -    private XSParticleDecl fElemMap[] = null;
  +    private Object fElemMap[] = null;
   
       /**
        * This is a map of whether the element map contains information
  @@ -111,21 +112,13 @@
        */
       private int fElemMapType[] = null;
   
  -    /** The element map size. */
  -    private int fElemMapSize = 0;
  -
  -    /* Used to indicate a mixed model */
  -    private boolean fMixed;
  -
       /**
  -     * The string index for the 'end of content' string that we add to
  -     * the string pool. This is used as the special name of an element
  -     * that represents the end of the syntax tree.
  +     * id of the unique input symbol
        */
  -    private static final XSParticleDecl fEOCParticle = new XSParticleDecl();
  -    static {
  -        fEOCParticle.fType = XSParticleDecl.PARTICLE_ELEMENT;
  -    }
  +    private int fElemMapId[] = null;
  +    
  +    /** The element map size. */
  +    private int fElemMapSize = 0;
   
       /**
        * The NFA position of the special EOC (end of content) node. This
  @@ -216,24 +209,8 @@
        * @exception RuntimeException Thrown if DFA can't be built.
        */
   
  -   public XSDFACM(CMNode syntaxTree,
  -                          int leafCount) {
  -       this(syntaxTree, leafCount, false);
  -   }
  -
  -    /**
  -     * Constructs a DFA content model.
  -     *
  -     * @param symbolTable    The symbol table.
  -     * @param syntaxTree    The syntax tree of the content model.
  -     * @param leafCount     The number of leaves.
  -     *
  -     * @exception RuntimeException Thrown if DFA can't be built.
  -     */
  -
  -   public XSDFACM(CMNode syntaxTree,
  -                          int leafCount, boolean mixed) {
  -
  +   public XSDFACM(CMNode syntaxTree, int leafCount) {
  +   
           // Store away our index and pools in members
           fLeafCount = leafCount;
   
  @@ -243,8 +220,6 @@
           //  (already done in static initialization...
           //
   
  -        fMixed = mixed;
  -
           //
           //  Ok, so lets grind through the building of the DFA. This method
           //  handles the high level logic of the algorithm, but it uses a
  @@ -321,14 +296,14 @@
                   continue;
               int type = fElemMapType[elemIndex] ;
               if (type == XSParticleDecl.PARTICLE_ELEMENT) {
  -                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex].fValue);
  +                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]);
                   if (matchingDecl != null) {
                       break;
                   }
               }
               else if (type == XSParticleDecl.PARTICLE_WILDCARD) {
  -                if(((XSWildcardDecl)fElemMap[elemIndex].fValue).allowNamespace(curElem.uri)) {
  -                    matchingDecl = fElemMap[elemIndex].fValue;
  +                if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri)) {
  +                    matchingDecl = fElemMap[elemIndex];
                       break;
                   }
               }
  @@ -351,14 +326,14 @@
           for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
               int type = fElemMapType[elemIndex] ;
               if (type == XSParticleDecl.PARTICLE_ELEMENT) {
  -                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex].fValue);
  +                matchingDecl = subGroupHandler.getMatchingElemDecl(curElem, (XSElementDecl)fElemMap[elemIndex]);
                   if (matchingDecl != null) {
                       return matchingDecl;
                   }
               }
               else if (type == XSParticleDecl.PARTICLE_WILDCARD) {
  -                if(((XSWildcardDecl)fElemMap[elemIndex].fValue).allowNamespace(curElem.uri))
  -                    return fElemMap[elemIndex].fValue;
  +                if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri))
  +                    return fElemMap[elemIndex];
               }
           }
   
  @@ -433,13 +408,6 @@
            * "(a, (b, a+, (c, (b, a+)+, a+, (d,  (c, (b, a+)+, a+)+, (b, a+)+, a+)+)+)+)+"
            */
   
  -        XSCMLeaf nodeEOC = new XSCMLeaf(fEOCParticle);
  -        fHeadNode = new XSCMBinOp(
  -        XSParticleDecl.PARTICLE_SEQUENCE
  -            , syntaxTree
  -            , nodeEOC
  -        );
  -
           //
           //  And handle specially the EOC node, which also must be numbered
           //  and counted as a non-epsilon leaf node. It could not be handled
  @@ -448,7 +416,12 @@
           //  building loop.
           //
           fEOCPos = fLeafCount;
  -        nodeEOC.setPosition(fLeafCount++);
  +        XSCMLeaf nodeEOC = new XSCMLeaf(XSParticleDecl.PARTICLE_ELEMENT, null, -1, fLeafCount++);
  +        fHeadNode = new XSCMBinOp(
  +            XSModelGroup.MODELGROUP_SEQUENCE,
  +            syntaxTree,
  +            nodeEOC
  +        );
   
           //
           //  Ok, so now we have to iterate the new tree and do a little more
  @@ -466,7 +439,7 @@
           //
           fLeafList = new XSCMLeaf[fLeafCount];
           fLeafListType = new int[fLeafCount];
  -        postTreeBuildInit(fHeadNode, 0);
  +        postTreeBuildInit(fHeadNode);
   
           //
           //  And, moving onward... We now need to build the follow position
  @@ -488,8 +461,9 @@
           //  input element. So we need to a zero based range of indexes that
           //  map to element types. This element map provides that mapping.
           //
  -        fElemMap = new XSParticleDecl[fLeafCount];
  +        fElemMap = new Object[fLeafCount];
           fElemMapType = new int[fLeafCount];
  +        fElemMapId = new int[fLeafCount];
           fElemMapSize = 0;
           for (int outIndex = 0; outIndex < fLeafCount; outIndex++) {
               // optimization from Henry Zongaro:
  @@ -497,16 +471,17 @@
               fElemMap[outIndex] = null;
   
               int inIndex = 0;
  -            final XSParticleDecl decl = fLeafList[outIndex].getLeaf();
  +            final int id = fLeafList[outIndex].getParticleId();
               for (; inIndex < fElemMapSize; inIndex++) {
  -                if (decl == fElemMap[inIndex])
  +                if (id == fElemMapId[inIndex])
                       break;
               }
   
               // If it was not in the list, then add it, if not the EOC node
               if (inIndex == fElemMapSize) {
  -                fElemMap[fElemMapSize] = decl;
  +                fElemMap[fElemMapSize] = fLeafList[outIndex].getLeaf();
                   fElemMapType[fElemMapSize] = fLeafListType[outIndex];
  +                fElemMapId[fElemMapSize] = id;
                   fElemMapSize++;
               }
           }
  @@ -514,7 +489,7 @@
           // the last entry in the element map must be the EOC element.
           // remove it from the map.
           if (DEBUG) {
  -            if (fElemMap[fElemMapSize-1] != fEOCParticle)
  +            if (fElemMapId[fElemMapSize-1] != -1)
                   System.err.println("interal error in DFA: last element is not EOC.");
           }
           fElemMapSize--;
  @@ -529,9 +504,9 @@
           int fSortCount = 0;
   
           for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
  -            final XSParticleDecl decl = fElemMap[elemIndex];
  +            final int id = fElemMapId[elemIndex];
               for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) {
  -                if (decl == fLeafList[leafIndex].getLeaf())
  +                if (id == fLeafList[leafIndex].getParticleId())
                       fLeafSorter[fSortCount++] = leafIndex;
               }
               fLeafSorter[fSortCount++] = -1;
  @@ -734,7 +709,8 @@
           fHeadNode = null;
           fLeafList = null;
           fFollowList = null;
  -
  +        fLeafListType = null;
  +        fElemMapId = null;
       }
   
       /**
  @@ -746,12 +722,12 @@
        */
       private void calcFollowList(CMNode nodeCur) {
           // Recurse as required
  -        if (nodeCur.type() == XSParticleDecl.PARTICLE_CHOICE) {
  +        if (nodeCur.type() == XSModelGroup.MODELGROUP_CHOICE) {
               // Recurse only
               calcFollowList(((XSCMBinOp)nodeCur).getLeft());
               calcFollowList(((XSCMBinOp)nodeCur).getRight());
           }
  -         else if (nodeCur.type() == XSParticleDecl.PARTICLE_SEQUENCE) {
  +         else if (nodeCur.type() == XSModelGroup.MODELGROUP_SEQUENCE) {
               // Recurse first
               calcFollowList(((XSCMBinOp)nodeCur).getLeft());
               calcFollowList(((XSCMBinOp)nodeCur).getRight());
  @@ -820,9 +796,9 @@
   
           switch(type ) {
   
  -        case XSParticleDecl.PARTICLE_CHOICE:
  -        case XSParticleDecl.PARTICLE_SEQUENCE: {
  -            if (type == XSParticleDecl.PARTICLE_CHOICE)
  +        case XSModelGroup.MODELGROUP_CHOICE:
  +        case XSModelGroup.MODELGROUP_SEQUENCE: {
  +            if (type == XSModelGroup.MODELGROUP_CHOICE)
                   System.out.print("Choice Node ");
               else
                   System.out.print("Seq Node ");
  @@ -861,9 +837,8 @@
                   "Leaf: (pos="
                   + ((XSCMLeaf)nodeCur).getPosition()
                   + "), "
  -                + ((XSCMLeaf)nodeCur).getLeaf().fValue
                   + "(elemIndex="
  -                + ((XSCMLeaf)nodeCur).getLeaf().fValue
  +                + ((XSCMLeaf)nodeCur).getLeaf()
                   + ") "
               );
   
  @@ -906,42 +881,40 @@
       }
   
       /** Post tree build initialization. */
  -    private int postTreeBuildInit(CMNode nodeCur, int curIndex) throws RuntimeException {
  +    private void postTreeBuildInit(CMNode nodeCur) throws RuntimeException {
           // Set the maximum states on this node
           nodeCur.setMaxStates(fLeafCount);
   
  +        XSCMLeaf leaf = null;
  +        int pos = 0;
           // Recurse as required
           if (nodeCur.type() == XSParticleDecl.PARTICLE_WILDCARD) {
  -            fLeafList[curIndex] = (XSCMLeaf)nodeCur;
  -            fLeafListType[curIndex] = XSParticleDecl.PARTICLE_WILDCARD;
  -            curIndex++;
  -        }
  -        else if ((nodeCur.type() == XSParticleDecl.PARTICLE_CHOICE)
  -        ||  (nodeCur.type() == XSParticleDecl.PARTICLE_SEQUENCE))
  -        {
  -            curIndex = postTreeBuildInit(((XSCMBinOp)nodeCur).getLeft(), curIndex);
  -            curIndex = postTreeBuildInit(((XSCMBinOp)nodeCur).getRight(), curIndex);
  +            leaf = (XSCMLeaf)nodeCur;
  +            pos = leaf.getPosition();
  +            fLeafList[pos] = leaf;
  +            fLeafListType[pos] = XSParticleDecl.PARTICLE_WILDCARD;
  +        }
  +        else if ((nodeCur.type() == XSModelGroup.MODELGROUP_CHOICE) ||
  +                 (nodeCur.type() == XSModelGroup.MODELGROUP_SEQUENCE)) {
  +            postTreeBuildInit(((XSCMBinOp)nodeCur).getLeft());
  +            postTreeBuildInit(((XSCMBinOp)nodeCur).getRight());
  +        }
  +        else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE ||
  +                 nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE ||
  +                 nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE) {
  +            postTreeBuildInit(((XSCMUniOp)nodeCur).getChild());
           }
  -         else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE
  -         || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE
  -         || nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE)
  -        {
  -            curIndex = postTreeBuildInit(((XSCMUniOp)nodeCur).getChild(), curIndex);
  -        }
  -         else if (nodeCur.type() == XSParticleDecl.PARTICLE_ELEMENT) {
  -            //
  +        else if (nodeCur.type() == XSParticleDecl.PARTICLE_ELEMENT) {
               //  Put this node in the leaf list at the current index if its
               //  a non-epsilon leaf.
  -            //
  -            fLeafList[curIndex] = (XSCMLeaf)nodeCur;
  -            fLeafListType[curIndex] = XSParticleDecl.PARTICLE_ELEMENT;
  -            curIndex++;
  +            leaf = (XSCMLeaf)nodeCur;
  +            pos = leaf.getPosition();
  +            fLeafList[pos] = leaf;
  +            fLeafListType[pos] = XSParticleDecl.PARTICLE_ELEMENT;
           }
  -         else
  -        {
  +        else {
               throw new RuntimeException("ImplementationMessages.VAL_NIICM");
           }
  -        return curIndex;
       }
   
       /**
  @@ -965,7 +938,7 @@
                           fTransTable[i][k] != -1) {
                           if (conflictTable[j][k] == 0) {
                               conflictTable[j][k] = XSConstraints.overlapUPA
  -                                                   (fElemMap[j].fValue,fElemMap[k].fValue,
  +                                                   (fElemMap[j],fElemMap[k],
                                                      subGroupHandler) ?
                                                      (byte)1 : (byte)-1;
                           }
  @@ -991,7 +964,7 @@
           // again, if this grammar is cached.
           for (int i = 0; i < fElemMapSize; i++) {
               if (fElemMapType[i] == XSParticleDecl.PARTICLE_WILDCARD) {
  -                XSWildcardDecl wildcard = (XSWildcardDecl)fElemMap[i].fValue;
  +                XSWildcardDecl wildcard = (XSWildcardDecl)fElemMap[i];
                   if (wildcard.fType == XSWildcardDecl.WILDCARD_LIST ||
                       wildcard.fType == XSWildcardDecl.WILDCARD_OTHER) {
                       return true;
  
  
  
  1.8       +136 -104  xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser.java
  
  Index: XSDAbstractParticleTraverser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDAbstractParticleTraverser.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XSDAbstractParticleTraverser.java	4 Apr 2002 18:36:26 -0000	1.7
  +++ XSDAbstractParticleTraverser.java	26 Apr 2002 22:03:43 -0000	1.8
  @@ -60,6 +60,7 @@
   import org.apache.xerces.impl.xs.SchemaGrammar;
   import org.apache.xerces.impl.xs.SchemaSymbols;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   import org.apache.xerces.util.DOMUtil;
   import org.apache.xerces.impl.xs.util.XInt;
   import org.w3c.dom.Element;
  @@ -67,13 +68,12 @@
   /**
    * @author Elena Litani, IBM
    * @author Sandy Gao, IBM
  - * @version $Id: XSDAbstractParticleTraverser.java,v 1.7 2002/04/04 18:36:26 sandygao Exp $
  + * @version $Id: XSDAbstractParticleTraverser.java,v 1.8 2002/04/26 22:03:43 sandygao Exp $
    */
   abstract class XSDAbstractParticleTraverser extends XSDAbstractTraverser {
   
       XSDAbstractParticleTraverser (XSDHandler handler,
                                     XSAttributeChecker gAttrCheck) {
  -
           super(handler, gAttrCheck);
       }
   
  @@ -106,10 +106,10 @@
                   child = DOMUtil.getNextSiblingElement(child);
               }
           }
  -        XSParticleDecl left = null;
  -        XSParticleDecl right = null;
           String childName = null;
  -        XSParticleDecl particle, temp;
  +        XSParticleDecl particle;
  +        fPArray.pushContext();
  +
           for (; child != null; child = DOMUtil.getNextSiblingElement(child)) {
   
               particle = null;
  @@ -124,58 +124,42 @@
                   reportSchemaError("s4s-elt-must-match", args, child);
               }
   
  -            if (left == null) {
  -                left = particle;
  -            }
  -            else if (right == null) {
  -                right = particle;
  -            }
  -            else {
  -                if (fSchemaHandler.fDeclPool !=null) {
  -                    temp = fSchemaHandler.fDeclPool.getParticleDecl();
  -                } else {        
  -                    temp = new XSParticleDecl();
  -                }
  -                temp.fType = XSParticleDecl.PARTICLE_ALL;
  -                temp.fValue = left;
  -                temp.fOtherValue = right;
  -                left = temp;
  -                right = particle;
  -            }
  -        }
  -
  -        if (left != null) {
  -            if (fSchemaHandler.fDeclPool !=null) {
  -                temp = fSchemaHandler.fDeclPool.getParticleDecl();
  -            } else {        
  -                temp = new XSParticleDecl();
  -            }
  -            temp.fType = XSParticleDecl.PARTICLE_ALL;
  -            temp.fValue = left;
  -            temp.fOtherValue = right;
  -            left = temp;
  +            if (particle != null)
  +                fPArray.addParticle(particle);
           }
   
  +        particle = null;
           // REVISIT: model group
           // Quick fix for the case that particle <all> does not have any children.
           // For now we return null. In the future we might want to return model group decl.
  -        if (left != null) {
  +        if (fPArray.getParticleCount() != 0) {
   
               XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
               XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
               Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
  -            left.fMinOccurs = minAtt.intValue();
  -            left.fMaxOccurs = maxAtt.intValue();
  -
  -            left = checkOccurrences(left,
  -                                    SchemaSymbols.ELT_ALL,
  -                                    (Element)allDecl.getParentNode(),
  -                                    allContextFlags,
  -                                    defaultVals.longValue());
  +            
  +            XSModelGroup group = new XSModelGroup();
  +            group.fCompositor = XSModelGroup.MODELGROUP_ALL;
  +            group.fParticleCount = fPArray.getParticleCount();
  +            group.fParticles = fPArray.popContext();
  +            particle = new XSParticleDecl();
  +            particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +            particle.fMinOccurs = minAtt.intValue();
  +            particle.fMaxOccurs = maxAtt.intValue();
  +            particle.fValue = group;
  +
  +            particle = checkOccurrences(particle,
  +                                        SchemaSymbols.ELT_ALL,
  +                                        (Element)allDecl.getParentNode(),
  +                                        allContextFlags,
  +                                        defaultVals.longValue());
  +        }
  +        else {
  +            fPArray.discardContext();
           }
           fAttrChecker.returnAttrArray(attrValues, schemaDoc);
   
  -        return left;
  +        return particle;
       }
   
       /**
  @@ -250,11 +234,11 @@
                   child = DOMUtil.getNextSiblingElement(child);
               }
           }
  -        XSParticleDecl left = null;
  -        XSParticleDecl right = null;
           boolean hadContent = false;
           String childName = null;
  -        XSParticleDecl particle, temp;
  +        XSParticleDecl particle;
  +        fPArray.pushContext();
  +
           for (;child != null;child = DOMUtil.getNextSiblingElement(child)) {
   
               particle = null;
  @@ -277,10 +261,10 @@
   
               }
               else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
  -                particle = traverseChoice( child,schemaDoc, grammar, NOT_ALL_CONTEXT);
  +                particle = traverseChoice(child, schemaDoc, grammar, NOT_ALL_CONTEXT);
               }
               else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
  -                particle = traverseSequence(child,schemaDoc, grammar, NOT_ALL_CONTEXT);
  +                particle = traverseSequence(child, schemaDoc, grammar, NOT_ALL_CONTEXT);
               }
               else if (childName.equals(SchemaSymbols.ELT_ANY)) {
                   particle = fSchemaHandler.fWildCardTraverser.traverseAny(child, schemaDoc, grammar);
  @@ -296,80 +280,128 @@
                   reportSchemaError("s4s-elt-must-match", args, child);
               }
   
  -
  -            if (left == null) {
  -                left = particle;
  -            }
  -            else if (right == null) {
  -                right = particle;
  -            }
  -            else {
  -                if (fSchemaHandler.fDeclPool !=null) {
  -                    temp = fSchemaHandler.fDeclPool.getParticleDecl();
  -                } else {        
  -                    temp = new XSParticleDecl();
  -                }
  -                if (choice)
  -                    temp.fType = XSParticleDecl.PARTICLE_CHOICE;
  -                else
  -                    temp.fType = XSParticleDecl.PARTICLE_SEQUENCE;
  -                temp.fValue = left;
  -                temp.fOtherValue = right;
  -                left = temp;
  -                right = particle;
  -            }
  +            if (particle != null)
  +                fPArray.addParticle(particle);
           }
   
  +        particle = null;
  +        
           // REVISIT: model group
           // Quick fix for the case that particles <choice> | <sequence> do not have any children.
           // For now we return null. In the future we might want to return model group decl.
  -
  -        if (left != null) {
  -            if (fSchemaHandler.fDeclPool !=null) {
  -                temp = fSchemaHandler.fDeclPool.getParticleDecl();
  -            } else {        
  -                temp = new XSParticleDecl();
  -            }
  -            if (choice)
  -                temp.fType = XSParticleDecl.PARTICLE_CHOICE;
  -            else
  -                temp.fType = XSParticleDecl.PARTICLE_SEQUENCE;
  -            temp.fValue = left;
  -            temp.fOtherValue = right;
  -            left = temp;
  +        if (fPArray.getParticleCount() != 0) {
   
               XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
               XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
               Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
  -            left.fMinOccurs = minAtt.intValue();
  -            left.fMaxOccurs = maxAtt.intValue();
  -            left = checkOccurrences(left,
  -                                    choice ? SchemaSymbols.ELT_CHOICE : SchemaSymbols.ELT_SEQUENCE,
  -                                    (Element)decl.getParentNode(),
  -                                    allContextFlags,
  -                                    defaultVals.longValue());
  +
  +            XSModelGroup group = new XSModelGroup();
  +            group.fCompositor = choice ? XSModelGroup.MODELGROUP_CHOICE : XSModelGroup.MODELGROUP_SEQUENCE;
  +            group.fParticleCount = fPArray.getParticleCount();
  +            group.fParticles = fPArray.popContext();
  +            particle = new XSParticleDecl();
  +            particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +            particle.fMinOccurs = minAtt.intValue();
  +            particle.fMaxOccurs = maxAtt.intValue();
  +            particle.fValue = group;
  +
  +            particle = checkOccurrences(particle,
  +                                        choice ? SchemaSymbols.ELT_CHOICE : SchemaSymbols.ELT_SEQUENCE,
  +                                        (Element)decl.getParentNode(),
  +                                        allContextFlags,
  +                                        defaultVals.longValue());
  +        }
  +        else {
  +            fPArray.discardContext();
           }
           fAttrChecker.returnAttrArray(attrValues, schemaDoc);
   
  -        return left;
  +        return particle;
       }
   
       // Determines whether a content spec tree represents an "all" content model
       protected boolean hasAllContent(XSParticleDecl particle) {
           // If the content is not empty, is the top node ALL?
  -        if (particle != null) {
  -
  -            // REVISIT: defered?
  -            // An ALL node could be optional, so we have to be prepared
  -            // to look one level below a ZERO_OR_ONE node for an ALL.
  -            //if (fParticle.type == XSParticleDecl.CONTENTSPECNODE_ZERO_OR_ONE) {
  -            //    fSchemaGrammar.getContentSpec(content.value, content);
  -            //}
  -
  -            return(particle.fType == XSParticleDecl.PARTICLE_ALL);
  +        if (particle != null && particle.fType == XSParticleDecl.PARTICLE_MODELGROUP) {
  +            return ((XSModelGroup)particle.fValue).fCompositor == XSModelGroup.MODELGROUP_ALL;
           }
   
           return false;
       }
   
  +    // the inner class: used to store particles for model groups
  +    // to avoid creating a new Vector in each model group, or when traversing
  +    // each model group, we use this one big array to store all particles
  +    // for model groups. when the traversal finishes, this class returns an
  +    // XSParticleDecl[] containing all particles for the current model group.
  +    // it's possible that we need to traverse another model group while
  +    // traversing one (one inside another one; referring to a global group,
  +    // etc.), so we have push/pos context methods to save the same of the
  +    // current traversal before starting the traversal of another model group.
  +    protected static class ParticleArray {
  +        // big array to contain all particles
  +        XSParticleDecl[] fParticles = new XSParticleDecl[10];
  +        // the ending position of particles in the array for each context
  +        // index 0 is reserved, with value 0. index 1 is used for the fist
  +        // context. so that the number of particles for context 'i' can be
  +        // computed simply by fPos[i] - fPos[i-1].
  +        int[] fPos = new int[5];
  +        // number of contexts
  +        int fContextCount = 0;
  +        
  +        // start a new context (start traversing a new model group)
  +        void pushContext() {
  +            fContextCount++;
  +            // resize position array if necessary
  +            if (fContextCount == fPos.length) {
  +                int newSize = fContextCount * 2;
  +                int[] newArray = new int[newSize];
  +                System.arraycopy(fPos, 0, newArray, 0, fContextCount);
  +                fPos = newArray;
  +            }
  +            // the initial ending position of the current context is the
  +            // ending position of the previsous context. which means there is
  +            // no particle for the current context yet.
  +            fPos[fContextCount] = fPos[fContextCount-1];
  +        }
  +        
  +        // get the number of particles of this context (model group)
  +        int getParticleCount() {
  +            return fPos[fContextCount] - fPos[fContextCount-1];
  +        }
  +        
  +        // add a particle to the current context
  +        void addParticle(XSParticleDecl particle) {
  +            // resize the particle array if necessary
  +            if (fPos[fContextCount] == fParticles.length) {
  +                int newSize = fPos[fContextCount] * 2;
  +                XSParticleDecl[] newArray = new XSParticleDecl[newSize];
  +                System.arraycopy(fParticles, 0, newArray, 0, fPos[fContextCount]);
  +                fParticles = newArray;
  +            }
  +            fParticles[fPos[fContextCount]++] = particle;
  +        }
  +        
  +        // end the current context, and return an array of particles
  +        XSParticleDecl[] popContext() {
  +            int count = fPos[fContextCount] - fPos[fContextCount-1];
  +            XSParticleDecl[] array = new XSParticleDecl[count];
  +            System.arraycopy(fParticles, fPos[fContextCount-1], array, 0, count);
  +            // clear the particle array, to release memory
  +            for (int i = fPos[fContextCount-1]; i < fPos[fContextCount]; i++)
  +                fParticles[i] = null;
  +            fContextCount--;
  +            return array;
  +        }
  +        
  +        void discardContext() {
  +            // clear the particle array, to release memory
  +            for (int i = fPos[fContextCount-1]; i < fPos[fContextCount]; i++)
  +                fParticles[i] = null;
  +            fContextCount--;
  +        }
  +    }
  +
  +    // the big particle array to hold all particles in model groups
  +    ParticleArray fPArray = new ParticleArray();
   }
  
  
  
  1.18      +29 -13    xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser.java
  
  Index: XSDComplexTypeTraverser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDComplexTypeTraverser.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- XSDComplexTypeTraverser.java	4 Apr 2002 18:36:26 -0000	1.17
  +++ XSDComplexTypeTraverser.java	26 Apr 2002 22:03:43 -0000	1.18
  @@ -69,6 +69,7 @@
   import org.apache.xerces.impl.xs.XSAttributeUse;
   import org.apache.xerces.impl.xs.XSWildcardDecl;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   import org.apache.xerces.util.DOMUtil;
   import org.apache.xerces.impl.xs.util.XInt;
   import org.apache.xerces.impl.xs.util.XIntPool;
  @@ -91,7 +92,7 @@
    *            ((group | all | choice | sequence)?,
    *            ((attribute | attributeGroup)*, anyAttribute?))))
    * </complexType>
  - * @version $Id: XSDComplexTypeTraverser.java,v 1.17 2002/04/04 18:36:26 sandygao Exp $
  + * @version $Id: XSDComplexTypeTraverser.java,v 1.18 2002/04/26 22:03:43 sandygao Exp $
    */
   
   class  XSDComplexTypeTraverser extends XSDAbstractParticleTraverser {
  @@ -721,16 +722,27 @@
               else if (baseContent==null) {
               }
               else {
  -                if (typeInfo.fParticle.fType == XSParticleDecl.PARTICLE_ALL ||
  -                    baseType.fParticle.fType == XSParticleDecl.PARTICLE_ALL) {
  +                // if the content of either type is an "all" model group, error.
  +                if (typeInfo.fParticle.fType == XSParticleDecl.PARTICLE_MODELGROUP &&
  +                    ((XSModelGroup)typeInfo.fParticle.fValue).fCompositor == XSModelGroup.MODELGROUP_ALL ||
  +                    baseType.fParticle.fType == XSParticleDecl.PARTICLE_MODELGROUP &&
  +                    ((XSModelGroup)baseType.fParticle.fValue).fCompositor == XSModelGroup.MODELGROUP_ALL) {
                       throw new ComplexTypeRecoverableError("cos-all-limited.1.2",
                             null, complexContent);
                   }
  -                XSParticleDecl temp = new XSParticleDecl();
  -                temp.fType = XSParticleDecl.PARTICLE_SEQUENCE;
  -                temp.fValue = baseContent;
  -                temp.fOtherValue = typeInfo.fParticle;
  -                typeInfo.fParticle = temp;
  +                // the "sequence" model group to contain both particles
  +                XSModelGroup group = new XSModelGroup();
  +                group.fCompositor = XSModelGroup.MODELGROUP_SEQUENCE;
  +                group.fParticleCount = 2;
  +                group.fParticles = new XSParticleDecl[2];
  +                group.fParticles[0] = baseType.fParticle;
  +                group.fParticles[1] = typeInfo.fParticle;
  +                // the particle to contain the above sequence
  +                XSParticleDecl particle = new XSParticleDecl();
  +                particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +                particle.fValue = group;
  +                
  +                typeInfo.fParticle = particle;
               }
   
               // Set the contentType
  @@ -949,17 +961,21 @@
   
       private static synchronized XSParticleDecl getErrorContent() {
           if (fErrorContent==null) {
  -            fErrorContent = new XSParticleDecl();
  -            fErrorContent.fType = XSParticleDecl.PARTICLE_SEQUENCE;
  -            XSParticleDecl particle = new XSParticleDecl();
               fErrorWildcard = new XSWildcardDecl();
               fErrorWildcard.fProcessContents = XSWildcardDecl.WILDCARD_SKIP;
  +            XSParticleDecl particle = new XSParticleDecl();
               particle.fType = XSParticleDecl.PARTICLE_WILDCARD;
               particle.fValue = fErrorWildcard;
               particle.fMinOccurs = 0;
               particle.fMaxOccurs = SchemaSymbols.OCCURRENCE_UNBOUNDED;
  -            fErrorContent.fValue = particle;
  -            fErrorContent.fOtherValue = null;
  +            XSModelGroup group = new XSModelGroup();
  +            group.fCompositor = XSModelGroup.MODELGROUP_SEQUENCE;
  +            group.fParticleCount = 1;
  +            group.fParticles = new XSParticleDecl[1];
  +            group.fParticles[0] = particle;
  +            fErrorContent = new XSParticleDecl();
  +            fErrorContent.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +            fErrorContent.fValue = group;
           }
   
           return fErrorContent;
  
  
  
  1.11      +16 -20    xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDGroupTraverser.java
  
  Index: XSDGroupTraverser.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/traversers/XSDGroupTraverser.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- XSDGroupTraverser.java	4 Apr 2002 18:36:26 -0000	1.10
  +++ XSDGroupTraverser.java	26 Apr 2002 22:03:43 -0000	1.11
  @@ -59,6 +59,7 @@
   import org.apache.xerces.impl.xs.SchemaGrammar;
   import org.apache.xerces.impl.xs.SchemaSymbols;
   import org.apache.xerces.impl.xs.XSParticleDecl;
  +import org.apache.xerces.impl.xs.XSModelGroup;
   import org.apache.xerces.impl.xs.XSGroupDecl;
   import org.apache.xerces.impl.xs.XSMessageFormatter;
   import org.apache.xerces.util.DOMUtil;
  @@ -77,7 +78,7 @@
    * @author Rahul Srivastava, Sun Microsystems Inc.
    * @author Elena Litani, IBM
    * @author Lisa Martin,  IBM
  - * @version $Id: XSDGroupTraverser.java,v 1.10 2002/04/04 18:36:26 sandygao Exp $
  + * @version $Id: XSDGroupTraverser.java,v 1.11 2002/04/26 22:03:43 sandygao Exp $
    */
   class  XSDGroupTraverser extends XSDAbstractParticleTraverser {
   
  @@ -119,25 +120,19 @@
   
           XSParticleDecl particle = null;
   
  -        if (group != null) {
  -            // empty particle
  -            if (minOccurs == 0 && maxOccurs == 0) {
  -            } else if (minOccurs == 1 && maxOccurs == 1) {
  -                particle = group.fParticle;
  -            }
  -            else if (!( minOccurs == 1 && maxOccurs == 1)) {
  -                // if minOccurs==maxOccurs==1 we don't need to create new particle
  -                // create new particle in the grammar if minOccurs<maxOccurs
  -                if (fSchemaHandler.fDeclPool !=null) {
  -                    particle = fSchemaHandler.fDeclPool.getParticleDecl();
  -                } else {        
  -                    particle = new XSParticleDecl();
  -                }
  -                particle.fType = group.fParticle.fType;
  -                particle.fValue = group.fParticle;
  -                particle.fMinOccurs = minOccurs;
  -                particle.fMaxOccurs = maxOccurs;
  +        // not empty group, not empty particle
  +        if (group != null && group.fModelGroup != null &&
  +            !(minOccurs == 0 && maxOccurs == 0)) {
  +            // create a particle to contain this model group
  +            if (fSchemaHandler.fDeclPool != null) {
  +                particle = fSchemaHandler.fDeclPool.getParticleDecl();
  +            } else {        
  +                particle = new XSParticleDecl();
               }
  +            particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
  +            particle.fValue = group.fModelGroup;
  +            particle.fMinOccurs = minOccurs;
  +            particle.fMaxOccurs = maxOccurs;
           }
   
           fAttrChecker.returnAttrArray(attrValues, schemaDoc);
  @@ -206,7 +201,8 @@
                   group = new XSGroupDecl();
                   group.fName = strNameAttr;
                   group.fTargetNamespace = schemaDoc.fTargetNamespace;
  -                group.fParticle = particle;
  +                if (particle != null)
  +                    group.fModelGroup = (XSModelGroup)particle.fValue;
                   grammar.addGlobalGroupDecl(group);
               }
           }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org