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 2001/10/16 00:55:17 UTC

cvs commit: xml-xerces/java/src/org/apache/xerces/impl/v2 SchemaValidator.java SubstitutionGroupHandler.java XSAllCM.java XSCMValidator.java XSDFACM.java XSDHandler.java XSMixedCM.java XSSimpleCM.java

sandygao    01/10/15 15:55:17

  Modified:    java/src/org/apache/xerces/impl/v2 SchemaValidator.java
                        SubstitutionGroupHandler.java XSAllCM.java
                        XSCMValidator.java XSDFACM.java XSDHandler.java
                        XSMixedCM.java XSSimpleCM.java
  Log:
  SubstitutionGroup support in content model validators.
  
  Revision  Changes    Path
  1.28      +34 -37    xml-xerces/java/src/org/apache/xerces/impl/v2/SchemaValidator.java
  
  Index: SchemaValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/SchemaValidator.java,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- SchemaValidator.java	2001/10/12 17:54:30	1.27
  +++ SchemaValidator.java	2001/10/15 22:55:16	1.28
  @@ -112,7 +112,7 @@
    * @author Andy Clark, IBM
    * @author Jeffrey Rodriguez IBM
    *
  - * @version $Id: SchemaValidator.java,v 1.27 2001/10/12 17:54:30 neilg Exp $
  + * @version $Id: SchemaValidator.java,v 1.28 2001/10/15 22:55:16 sandygao Exp $
    */
   public class SchemaValidator
       implements XMLComponent, XMLDocumentFilter,
  @@ -440,8 +440,8 @@
                       break;
                   }
           }
  -        
  -        fBuffer.append(text.toString()); 
  +
  +        fBuffer.append(text.toString());
           if (!allWhiteSpace) {
               fSawCharacters = true;
           }
  @@ -716,6 +716,7 @@
   
       /** Schema grammar resolver. */
       final XSGrammarResolver fGrammarResolver;
  +    final SubstitutionGroupHandler fSubGroupHandler;
   
       /** Schema handler */
       final XSDHandler fSchemaHandler;
  @@ -833,7 +834,8 @@
       public SchemaValidator() {
   
           fGrammarResolver = new XSGrammarResolver();
  -        fSchemaHandler = new XSDHandler(fGrammarResolver);
  +        fSubGroupHandler = new SubstitutionGroupHandler(fGrammarResolver);
  +        fSchemaHandler = new XSDHandler(fGrammarResolver, fSubGroupHandler);
   
       } // <init>()
   
  @@ -857,7 +859,7 @@
           fSymbolTable = symbolTable;
   
           // get entity resolver. if there is no one, create a default
  -        // REVISIT: use default entity resolution from ENTITY MANAGER - temporary solution        
  +        // REVISIT: use default entity resolution from ENTITY MANAGER - temporary solution
           fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_MANAGER);
   
           // initialize namespace support
  @@ -868,6 +870,9 @@
           fGrammarResolver.reset();
           fGrammarResolver.putGrammar(URI_SCHEMAFORSCHEMA, SchemaGrammar.SG_SchemaNS);
   
  +        // clear thing in substitution group handler
  +        fSubGroupHandler.reset();
  +
           // reset schema handler and all traversal objects
           fSchemaHandler.reset(fErrorReporter, fEntityResolver, fSymbolTable);
   
  @@ -900,19 +905,19 @@
               int[] newArrayI = new int[newSize];
               System.arraycopy(fChildCountStack, 0, newArrayI, 0, newSize);
               fChildCountStack = newArrayI;
  -            
  +
               XSElementDecl[] newArrayE = new XSElementDecl[newSize];
               System.arraycopy(fElemDeclStack, 0, newArrayE, 0, newSize);
               fElemDeclStack = newArrayE;
  -            
  +
               XSTypeDecl[] newArrayT = new XSTypeDecl[newSize];
               System.arraycopy(fTypeStack, 0, newArrayT, 0, newSize);
               fTypeStack = newArrayT;
  -            
  +
               XSCMValidator[] newArrayC = new XSCMValidator[newSize];
               System.arraycopy(fCMStack, 0, newArrayC, 0, newSize);
               fCMStack = newArrayC;
  -            
  +
               boolean[] newArrayD = new boolean[newSize];
               System.arraycopy(fStringContent, 0, newArrayD, 0, newSize);
               fStringContent = newArrayD;
  @@ -1063,32 +1068,24 @@
           XSWildcardDecl wildcard = null;
           // if there is a content model, then get the decl from that
           if (fCurrentCM != null) {
  -            Object decl = fCurrentCM.oneTransition(element, fCurrCMState);
  +            Object decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
               // it could be an element decl or a wildcard decl
               // REVISIT: is there a more efficient way than 'instanceof'
  -            if (decl instanceof XSElementDecl) {
  -                fCurrentElemDecl = (XSElementDecl)decl;
  -            } else if (decl instanceof XSWildcardDecl) {
  -                wildcard = (XSWildcardDecl)decl;
  -            } else if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR &&
  -                       fDoValidation) {
  -                XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  -                //REVISIT: is it the only case we will have particle = null?
  -                // 
  -                if (ctype.fParticle != null) {
  -                    reportSchemaError("cvc-complex-type.2.4.a", new Object[]{element.rawname, ctype.fParticle.toString()});
  -                } else {
  -                    reportSchemaError("cvc-complex-type.2.4.a", new Object[]{element.rawname,"mixed with no element content"});
  +            if (decl == null) {
  +                if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR && fDoValidation) {
  +                    XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
  +                    //REVISIT: is it the only case we will have particle = null?
  +                    if (ctype.fParticle != null) {
  +                        reportSchemaError("cvc-complex-type.2.4.a", new Object[]{element.rawname, ctype.fParticle.toString()});
  +                    } else {
  +                        reportSchemaError("cvc-complex-type.2.4.a", new Object[]{element.rawname, "mixed with no element content"});
  +                    }
                   }
  -                
  -                fCurrCMState[0] = XSCMValidator.SUBSEQUENT_ERROR;
  -               
  -           
               } else if (decl instanceof XSElementDecl) {
                   fCurrentElemDecl = (XSElementDecl)decl;
  -            } else if (decl instanceof XSWildcardDecl) {
  +            } else {
                   wildcard = (XSWildcardDecl)decl;
  -            }  
  +            }
           }
   
           // save the current content model state in the stack
  @@ -1210,7 +1207,7 @@
               int count = fMatcherStack.getMatcherCount();
               for (int i = 0; i < count; i++) {
                   XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
  -            matcher.startElement(element, attributes, fGrammarResolver.getGrammar(element.uri)); 
  +            matcher.startElement(element, attributes, fGrammarResolver.getGrammar(element.uri));
               }
           }
   
  @@ -1307,7 +1304,7 @@
               fCurrCMState = fCMStateStack[fElementDepth];
               fSawCharacters = fStringContent[fElementDepth];
           }
  -        
  +
       } // handleEndElement(QName,boolean)*/
   
   
  @@ -1585,7 +1582,7 @@
               }
               // whether this attribute is specified
               isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
  -            
  +
               // Element Locally Valid (Complex Type)
               // 4 The {attribute declaration} of each attribute use in the {attribute uses} whose {required} is true matches one of the attribute information items in the element information item's [attributes] as per clause 3.1 above.
               if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
  @@ -1598,8 +1595,8 @@
                   //REVISIT: what's the proper attrType?
                   attributes.addAttribute(attName, null, (defaultValue !=null)?defaultValue.toString():"");
               }
  +
   
  -            
           } // for
       } // addDefaultAttributes
   
  @@ -1610,7 +1607,7 @@
                   if(fBuffer.toString().trim().length() == 0) {
                       int bufLen = fCurrentElemDecl.fDefault.toString().length();
                       char [] chars = new char[bufLen];
  -                    fCurrentElemDecl.fDefault.toString().getChars(0, bufLen, chars, 0); 
  +                    fCurrentElemDecl.fDefault.toString().getChars(0, bufLen, chars, 0);
                       XMLString text = new XMLString(chars, 0, bufLen);
                       if(fDocumentHandler != null) {
                           fDocumentHandler.characters(text);
  @@ -1629,7 +1626,7 @@
           if (DEBUG) {
             System.out.println("processElementContent:" +element);
           }
  -        
  +
           if (fCurrentElemDecl != null &&
               fCurrentElemDecl.getConstraintType() == XSElementDecl.DEFAULT_VALUE) {
           }
  @@ -1773,7 +1770,7 @@
                   ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
                   // if the current state is a valid state, check whether
                   // it's one of the final states.
  -                if (DEBUG) {                
  +                if (DEBUG) {
                     System.out.println(fCurrCMState);
                   }
                   if (fCurrCMState[0] >= 0 &&
  @@ -2454,7 +2451,7 @@
                       fIdentityConstraint2ValueStoreMap.put(keyRef, keyRefValueStore);
                       break;
                   }
  -            } 
  +            }
           } // initValueStoresFor(XSElementDecl)
   
           /** Returns the value store associated to the specified field. */
  
  
  
  1.4       +73 -1     xml-xerces/java/src/org/apache/xerces/impl/v2/SubstitutionGroupHandler.java
  
  Index: SubstitutionGroupHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/SubstitutionGroupHandler.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SubstitutionGroupHandler.java	2001/09/19 16:25:35	1.3
  +++ SubstitutionGroupHandler.java	2001/10/15 22:55:16	1.4
  @@ -57,12 +57,14 @@
   
   package org.apache.xerces.impl.v2;
   
  +import org.apache.xerces.xni.QName;
  +
   /**
    * To store and validate information about substitutionGroup
    *
    * @author Sandy Gao, IBM
    *
  - * @version $Id: SubstitutionGroupHandler.java,v 1.3 2001/09/19 16:25:35 sandygao Exp $
  + * @version $Id: SubstitutionGroupHandler.java,v 1.4 2001/10/15 22:55:16 sandygao Exp $
    */
   class SubstitutionGroupHandler {
   
  @@ -105,6 +107,76 @@
        */
       static boolean checkSubstitutionGroupOK(XSElementDecl element) {
           // REVISIT: to implement
  +        return true;
  +    }
  +
  +    // 3.9.4 Element Sequence Locally Valid (Particle) 2.3.3
  +    // check whether one element decl matches an element with the given qname
  +    boolean substitutionGroupOK(QName element, XSElementDecl exemplar) {
  +        // if the decl blocks substitution, return false
  +        if ((exemplar.fBlock & SchemaSymbols.SUBSTITUTION) != 0)
  +            return false;
  +
  +        // get grammar of the element
  +        SchemaGrammar sGrammar = fGrammarResolver.getGrammar(element.uri);
  +        if (sGrammar == null)
  +            return false;
  +
  +        // get the decl for the element
  +        XSElementDecl eDecl = sGrammar.getGlobalElementDecl(element.localpart);
  +        if (eDecl == null)
  +            return false;
  +
  +        // and check by using substitutionGroup information
  +        return substitutionGroupOK(eDecl, exemplar, exemplar.fBlock);
  +    }
  +
  +    // 3.3.6 Substitution Group OK (Transitive)
  +    // check whether element can substitute exemplar
  +    boolean substitutionGroupOK(XSElementDecl element, XSElementDecl exemplar, short blockingConstraint) {
  +        // For an element declaration (call it D) together with a blocking constraint (a subset of {substitution, extension, restriction}, the value of a {disallowed substitutions}) to be validly substitutable for another element declaration (call it C) all of the following must be true:
  +        // 1 The blocking constraint does not contain substitution.
  +        if ((blockingConstraint & SchemaSymbols.SUBSTITUTION) != 0)
  +            return false;
  +
  +        // prepare the combination of {derivation method} and
  +        // {disallowed substitution}
  +        short devMethod = 0, blockConstraint = blockingConstraint;
  +
  +        // initialize the derivation method to be that of the type of D
  +        XSTypeDecl type = element.fType;
  +        if ((type.getXSType() & XSTypeDecl.COMPLEX_TYPE) != 0)
  +            devMethod = ((XSComplexTypeDecl)type).fDerivedBy;
  +        else
  +            devMethod = SchemaSymbols.RESTRICTION;
  +
  +        // initialize disallowed substitution to the passed in blocking constraint
  +        type = exemplar.fType;
  +        if ((type.getXSType() & XSTypeDecl.COMPLEX_TYPE) != 0)
  +            blockConstraint |= ((XSComplexTypeDecl)type).fBlock;
  +
  +        // 2 There is a chain of {substitution group affiliation}s from D to C, that is, either D's {substitution group affiliation} is C, or D's {substitution group affiliation}'s {substitution group affiliation} is C, or . . .
  +        XSElementDecl subGroup = element.fSubGroup;
  +        while (subGroup != null && subGroup != exemplar) {
  +            // add the derivation method and disallowed substitution info
  +            // of the current type to the corresponding variables
  +            type = subGroup.fType;
  +            if ((type.getXSType() & XSTypeDecl.COMPLEX_TYPE) != 0) {
  +                devMethod |= ((XSComplexTypeDecl)type).fDerivedBy;
  +                blockConstraint |= ((XSComplexTypeDecl)type).fBlock;
  +            } else {
  +                devMethod |= SchemaSymbols.RESTRICTION;
  +            }
  +            subGroup = subGroup.fSubGroup;
  +        }
  +
  +        if (subGroup == null)
  +            return false;
  +
  +        // 3 The set of all {derivation method}s involved in the derivation of D's {type definition} from C's {type definition} does not intersect with the union of the blocking constraint, C's {prohibited substitutions} (if C is complex, otherwise the empty set) and the {prohibited substitutions} (respectively the empty set) of any intermediate {type definition}s in the derivation of D's {type definition} from C's {type definition}.
  +        if ((devMethod & blockConstraint) != 0)
  +            return false;
  +
           return true;
       }
   
  
  
  
  1.2       +47 -46    xml-xerces/java/src/org/apache/xerces/impl/v2/XSAllCM.java
  
  Index: XSAllCM.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSAllCM.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XSAllCM.java	2001/10/04 16:06:09	1.1
  +++ XSAllCM.java	2001/10/15 22:55:16	1.2
  @@ -63,7 +63,7 @@
    * XSAllCM implements XSCMValidator and handles <all>
    *
    * @author Pavani Mukthipudi, Sun Microsystems Inc.
  - * @version $Id: XSAllCM.java,v 1.1 2001/10/04 16:06:09 neilg Exp $
  + * @version $Id: XSAllCM.java,v 1.2 2001/10/15 22:55:16 sandygao Exp $
    */
   public class XSAllCM implements XSCMValidator {
   
  @@ -95,7 +95,7 @@
       public XSAllCM (boolean hasOptionalContent) {
           fHasOptionalContent = hasOptionalContent;
       }
  - 
  +
       // REVISIT : do we need this ?
       // public XSAllCM (boolean hasOptionalContent, boolean isMixed) {
       //     this(hasOptionalContent);
  @@ -133,26 +133,26 @@
   
       // REVISIT : to implement Unique Particle Attribution
       // public void checkUniqueParticleAttribution()
  +
   
  -    
       //
       // XSCMValidator methods
       //
   
       /**
        * This methods to be called on entering a first element whose type
  -     * has this content model. It will return the initial state of the 
  +     * has this content model. It will return the initial state of the
        * content model
        *
        * @return Start state of the content model
        */
       public int[] startContentModel() {
   
  -	    int[] state = new int[fNumElements + 1];
  +        int[] state = new int[fNumElements + 1];
   
  -	    for (int i = 0; i <= fNumElements; i++) {
  -	        state[i] = STATE_START;
  -	    }
  +        for (int i = 0; i <= fNumElements; i++) {
  +            state[i] = STATE_START;
  +        }
           return state;
       }
   
  @@ -164,39 +164,40 @@
        * @param state  Current state
        * @return an element decl object
        */
  -    public Object oneTransition (QName elementName, int[] currentState) {
  +    public Object oneTransition (QName elementName, int[] currentState, SubstitutionGroupHandler subGroupHandler) {
   
  -	    for (int i = 0; i < fNumElements; i++) {
  +        for (int i = 0; i < fNumElements; i++) {
   
  -	        if (fAllElements[i].fTargetNamespace == elementName.uri &&
  -	                fAllElements[i].fName == elementName.localpart) {
  +            if (fAllElements[i].fTargetNamespace == elementName.uri &&
  +                fAllElements[i].fName == elementName.localpart ||
  +                subGroupHandler.substitutionGroupOK(elementName, fAllElements[i])) {
  +
  +                if (currentState[i+1] == STATE_START) {
  +                    currentState[i+1] = STATE_VALID;
  +                }
  +                else if (currentState[i+1] == STATE_VALID) {
  +                    // duplicate element
  +                    currentState[i+1] = XSCMValidator.FIRST_ERROR;
  +                    currentState[0] = XSCMValidator.FIRST_ERROR;
  +                }
  +                else if (currentState[i+1] == XSCMValidator.FIRST_ERROR) {
  +                    currentState[i+1] = XSCMValidator.SUBSEQUENT_ERROR;
  +                    currentState[0] = XSCMValidator.SUBSEQUENT_ERROR;
  +                }
  +
  +                if (currentState[0] == STATE_START) {
  +                    currentState[0] = STATE_VALID;
  +                }
  +                return fAllElements[i];
  +            }
  +        }
   
  -		        if (currentState[i+1] == STATE_START) {
  -		            currentState[i+1] = STATE_VALID;
  -		        }
  -		        else if (currentState[i+1] == STATE_VALID) {
  -		            // duplicate element 
  -		            currentState[i+1] = XSCMValidator.FIRST_ERROR;
  -		            currentState[0] = XSCMValidator.FIRST_ERROR;
  -		        }
  -		        else if (currentState[i+1] == XSCMValidator.FIRST_ERROR) {
  -		            currentState[i+1] = XSCMValidator.SUBSEQUENT_ERROR;
  -		            currentState[0] = XSCMValidator.SUBSEQUENT_ERROR;
  -		        }
  -
  -		        if (currentState[0] == STATE_START) {
  -		            currentState[0] = STATE_VALID;
  -		        }
  -		        return fAllElements[i];
  -	        }
  - 	    }
  -
  -	    if (currentState[0] == XSCMValidator.FIRST_ERROR) 
  -	        currentState[0] = XSCMValidator.SUBSEQUENT_ERROR; 
  -	    else if (currentState[0] == STATE_START || currentState[0] == STATE_VALID)
  -	        currentState[0] = XSCMValidator.FIRST_ERROR;
  +        if (currentState[0] == XSCMValidator.FIRST_ERROR)
  +            currentState[0] = XSCMValidator.SUBSEQUENT_ERROR;
  +        else if (currentState[0] == STATE_START || currentState[0] == STATE_VALID)
  +            currentState[0] = XSCMValidator.FIRST_ERROR;
   
  -	    return null;
  +        return null;
       }
   
   
  @@ -209,23 +210,23 @@
       public boolean endContentModel (int[] currentState) {
   
           int state = currentState[0];
  +
  +        if (state == XSCMValidator.FIRST_ERROR || state == XSCMValidator.SUBSEQUENT_ERROR) {
  +            return false;
  +        }
   
  -	    if (state == XSCMValidator.FIRST_ERROR || state == XSCMValidator.SUBSEQUENT_ERROR) {
  -	        return false;
  -	    }
  -	
  -	    // If <all> has minOccurs of zero and there are
  +        // If <all> has minOccurs of zero and there are
           // no children to validate, it is trivially valid
   
           if (fHasOptionalContent && fNumElements == 0) {
               return true;
           }
   
  -	    int numRequiredSeen = 0;
  +        int numRequiredSeen = 0;
   
  -	    for (int i = 0; i < fNumElements; i++) {
  -	        if (!fIsOptionalElement[i] && currentState[i+1] != STATE_START)
  -		        numRequiredSeen++;
  +        for (int i = 0; i < fNumElements; i++) {
  +            if (!fIsOptionalElement[i] && currentState[i+1] != STATE_START)
  +                numRequiredSeen++;
           }
   
           if (fNumRequired == numRequiredSeen ) {
  
  
  
  1.5       +5 -5      xml-xerces/java/src/org/apache/xerces/impl/v2/XSCMValidator.java
  
  Index: XSCMValidator.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSCMValidator.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XSCMValidator.java	2001/09/21 18:51:44	1.4
  +++ XSCMValidator.java	2001/10/15 22:55:16	1.5
  @@ -64,14 +64,14 @@
    *
    * @author Sandy Gao, IBM
    * @author Elena Litani, IBM
  - * @version $Id: XSCMValidator.java,v 1.4 2001/09/21 18:51:44 elena Exp $
  + * @version $Id: XSCMValidator.java,v 1.5 2001/10/15 22:55:16 sandygao Exp $
    */
   public interface XSCMValidator {
   
  -    
  +
       public static final short FIRST_ERROR = -1;
  -    
  -    // on subsequent errors the validator should not report 
  +
  +    // on subsequent errors the validator should not report
       // an error
       //
       public static final short SUBSEQUENT_ERROR = -2;
  @@ -93,7 +93,7 @@
        * @return element decl or wildcard decl that
        *         corresponds to the element from the Schema grammar
        */
  -    public Object oneTransition (QName elementName, int[] state);
  +    public Object oneTransition (QName elementName, int[] state, SubstitutionGroupHandler subGroupHandler);
   
   
       /**
  
  
  
  1.4       +71 -108   xml-xerces/java/src/org/apache/xerces/impl/v2/XSDFACM.java
  
  Index: XSDFACM.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSDFACM.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- XSDFACM.java	2001/10/03 18:30:53	1.3
  +++ XSDFACM.java	2001/10/15 22:55:16	1.4
  @@ -69,7 +69,7 @@
    * it then uses in its validation algorithm.
    *
    * @author Neil Graham, IBM
  - * @version $Id: XSDFACM.java,v 1.3 2001/10/03 18:30:53 neilg Exp $
  + * @version $Id: XSDFACM.java,v 1.4 2001/10/15 22:55:16 sandygao Exp $
    */
   public class XSDFACM
       implements XSCMValidator {
  @@ -256,7 +256,7 @@
           //  Create some string pool indexes that represent the names of some
           //  magical nodes in the syntax tree.
           //  (already done in static initialization...
  -        // 
  +        //
   
           fMixed = mixed;
   
  @@ -271,14 +271,14 @@
           //
   
           if(DEBUG_VALIDATE_CONTENT) {
  -	        XSDFACM.time -= System.currentTimeMillis();
  +            XSDFACM.time -= System.currentTimeMillis();
           }
   
           buildDFA(syntaxTree);
   
           if(DEBUG_VALIDATE_CONTENT) {
  -	        XSDFACM.time += System.currentTimeMillis();
  -	        System.out.println("DFA build: " + XSDFACM.time + "ms");
  +            XSDFACM.time += System.currentTimeMillis();
  +            System.out.println("DFA build: " + XSDFACM.time + "ms");
           }
       }
   
  @@ -308,50 +308,35 @@
        * @param curPos      the current position of the stack
        *
        * @return:  null if transition is invalid; otherwise the Object corresponding to the
  -     *      XSElementDecl or XSWildcardDecl identified.  Also, the 
  +     *      XSElementDecl or XSWildcardDecl identified.  Also, the
        *      state array will be modified to include the new state; this so that the validator can
        *      store it away.
        *
        * @exception RuntimeException thrown on error
        */
  -    public Object oneTransition(QName curElem, int[] state) {
  +    public Object oneTransition(QName curElem, int[] state, SubstitutionGroupHandler subGroupHandler) {
           int curState = state[0];
           if(curState == XSCMValidator.FIRST_ERROR || curState == XSCMValidator.SUBSEQUENT_ERROR) {
               // there was an error last time; so just go find correct Object in fElemmMap.
               // ... after resetting state[0].
               if(curState == XSCMValidator.FIRST_ERROR)
  -                state[0] = XSCMValidator.SUBSEQUENT_ERROR; 
  +                state[0] = XSCMValidator.SUBSEQUENT_ERROR;
               int elemIndex = 0;
   
               for (; elemIndex < fElemMapSize; elemIndex++) {
                   int type = fElemMapType[elemIndex] ;
                   if (type == XSParticleDecl.PARTICLE_ELEMENT) {
                       if ((curElem.uri == ((XSElementDecl)fElemMap[elemIndex]).fTargetNamespace) &&
  -                            (curElem.localpart == ((XSElementDecl)fElemMap[elemIndex]).fName) ) {
  +                        (curElem.localpart == ((XSElementDecl)fElemMap[elemIndex]).fName) ||
  +                        subGroupHandler.substitutionGroupOK(curElem, (XSElementDecl)fElemMap[elemIndex])) {
                           return fElemMap[elemIndex];
                       }
                   }
                   else if (type == XSParticleDecl.PARTICLE_WILDCARD) {
  -                    if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri)) 
  +                    if(((XSWildcardDecl)fElemMap[elemIndex]).allowNamespace(curElem.uri))
                           return fElemMap[elemIndex];
                   }
               }
  -
  -            // if we can't find a match, try substitutionGroup
  -            // REVISIT:  add substitutionGroup support!
  -            /***
  -            if (elemIndex == fElemMapSize && comparator != null) {
  -                for (elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
  -                    if (fElemMapType[elemIndex] == XSParticleDecl.PARTICLE_ELEMENT) {
  -                        if (comparator.isEquivalentTo(curElem,fElemMap[elemIndex])) {
  -                            nextState = fTransTable[curState][elemIndex];
  -                            if (nextState != -1)
  -                                break;
  -                        }
  -                    }
  -                }
  -            }
  -            /**** end of commented-out section ****/
           }
   
           int nextState = 0;
  @@ -361,7 +346,8 @@
               int type = fElemMapType[elemIndex] ;
               if (type == XSParticleDecl.PARTICLE_ELEMENT) {
                   if ((curElem.uri == ((XSElementDecl)fElemMap[elemIndex]).fTargetNamespace) &&
  -                        (curElem.localpart == ((XSElementDecl)fElemMap[elemIndex]).fName) ) {
  +                    (curElem.localpart == ((XSElementDecl)fElemMap[elemIndex]).fName) ||
  +                    subGroupHandler.substitutionGroupOK(curElem, (XSElementDecl)fElemMap[elemIndex])) {
                       nextState = fTransTable[curState][elemIndex];
                       if (nextState != -1)
                           break;
  @@ -376,24 +362,8 @@
               }
           }
   
  -        // if we can't find a match, try substitutionGroup
  -        // REVISIT:  add substitutionGroup support!
  -        /***
  -        if (elemIndex == fElemMapSize && comparator != null) {
  -            for (elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
  -                if (fElemMapType[elemIndex] == XSParticleDecl.PARTICLE_ELEMENT) {
  -                    if (comparator.isEquivalentTo(curElem,fElemMap[elemIndex])) {
  -                        nextState = fTransTable[curState][elemIndex];
  -                        if (nextState != -1)
  -                            break;
  -                    }
  -                }
  -            }
  -        }
  -        /**** end of commented-out section ****/
  -
           // if we still can't find a match, set the state to first_error
  -        // and return null 
  +        // and return null
           if (elemIndex == fElemMapSize) {
               state[0] = XSCMValidator.FIRST_ERROR;
               return null;
  @@ -401,9 +371,9 @@
   
           state[0] = nextState;
           return fElemMap[elemIndex];
  -    } // oneTransition(QName, int[]):  Object
  +    } // oneTransition(QName, int[], SubstitutionGroup):  Object
   
  -    // This method returns the start states of the content model.  
  +    // This method returns the start states of the content model.
       public int[] startContentModel() {
           int[] val = new int[1];
           val[0]=0;
  @@ -415,13 +385,6 @@
           return fFinalStateFlags[state[0]];
       } // endContentModel(int[]):  boolean
   
  -    // REVISIT:  is any method like this still needed?
  -    /***
  -    public void setSubstitutionGroupComparator(SubstitutionGroupComparator comparator) {
  -        this.comparator = comparator;
  -    }
  -    ***/
  -
       // Killed off whatCanGoHere; we may need it for DOM canInsert(...) etc.,
       // but we can put it back later.
   
  @@ -512,17 +475,17 @@
           //  for that matter.)
           //
   
  -	    /* MODIFIED (Jan, 2001)
  -	     *
  -	     * Use following rules.
  -	     *   nullable(x+) := nullable(x), first(x+) := first(x),  last(x+) := last(x)
  -	     *   nullable(x?) := true, first(x?) := first(x),  last(x?) := last(x)
  -	     *
  -	     * The same computation of follow as x* is applied to x+
  -	     *
  -	     * The modification drastically reduces computation time of
  -	     * "(a, (b, a+, (c, (b, a+)+, a+, (d,  (c, (b, a+)+, a+)+, (b, a+)+, a+)+)+)+)+"
  -	     */
  +        /* MODIFIED (Jan, 2001)
  +         *
  +         * Use following rules.
  +         *   nullable(x+) := nullable(x), first(x+) := first(x),  last(x+) := last(x)
  +         *   nullable(x?) := true, first(x?) := first(x),  last(x?) := last(x)
  +         *
  +         * The same computation of follow as x* is applied to x+
  +         *
  +         * The modification drastically reduces computation time of
  +         * "(a, (b, a+, (c, (b, a+)+, a+, (d,  (c, (b, a+)+, a+)+, (b, a+)+, a+)+)+)+)+"
  +         */
   
           fElementDecl = new XSElementDecl();
           fElementDecl.fName = fEOCString;
  @@ -598,7 +561,7 @@
               }
               ***/
   
  -            // Get the current leaf's element 
  +            // Get the current leaf's element
               final XSElementDecl element = fLeafList[outIndex].getElement();
   
               // See if the current leaf node's element index is in the list
  @@ -624,30 +587,30 @@
           }
           ******/
   
  -	    /***
  -	     * Optimization(Jan, 2001); We sort fLeafList according to
  -	     * elemIndex which is *uniquely* associated to each leaf.
  -	     * We are *assuming* that each element appears in at least one leaf.
  -	     **/
  -
  -	    int[] fLeafSorter = new int[fLeafCount + fElemMapSize];
  -	    int fSortCount = 0;
  -
  -	    for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
  -	        for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) {
  -		        final XSElementDecl leaf = fLeafList[leafIndex].getElement();
  -		        final int leafType = fLeafListType[leafIndex];
  -		        final XSElementDecl element = (XSElementDecl)fElemMap[elemIndex];
  -		        if (fElemMapType[elemIndex] == fLeafListType[leafIndex] &&
  +        /***
  +         * Optimization(Jan, 2001); We sort fLeafList according to
  +         * elemIndex which is *uniquely* associated to each leaf.
  +         * We are *assuming* that each element appears in at least one leaf.
  +         **/
  +
  +        int[] fLeafSorter = new int[fLeafCount + fElemMapSize];
  +        int fSortCount = 0;
  +
  +        for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
  +            for (int leafIndex = 0; leafIndex < fLeafCount; leafIndex++) {
  +                final XSElementDecl leaf = fLeafList[leafIndex].getElement();
  +                final int leafType = fLeafListType[leafIndex];
  +                final XSElementDecl element = (XSElementDecl)fElemMap[elemIndex];
  +                if (fElemMapType[elemIndex] == fLeafListType[leafIndex] &&
                           leaf.fTargetNamespace == element.fTargetNamespace &&
  -					    leaf.fName == element.fName ) {
  -				    fLeafSorter[fSortCount++] = leafIndex;
  -		        }
  -	        }
  -	        fLeafSorter[fSortCount++] = -1;
  -	    }
  +                        leaf.fName == element.fName ) {
  +                    fLeafSorter[fSortCount++] = leafIndex;
  +                }
  +            }
  +            fLeafSorter[fSortCount++] = -1;
  +        }
   
  -	    /* Optimization(Jan, 2001) */
  +        /* Optimization(Jan, 2001) */
   
           //
           //  Next lets create some arrays, some that hold transient
  @@ -693,13 +656,13 @@
           statesToDo[curState] = setT;
           curState++;
   
  -	    /* Optimization(Jan, 2001); This is faster for
  -	     * a large content model such as, "(t001+|t002+|.... |t500+)".
  -	     */
  +        /* Optimization(Jan, 2001); This is faster for
  +         * a large content model such as, "(t001+|t002+|.... |t500+)".
  +         */
   
  -	    java.util.Hashtable stateTable = new java.util.Hashtable();
  +        java.util.Hashtable stateTable = new java.util.Hashtable();
   
  -	    /* Optimization(Jan, 2001) */
  +        /* Optimization(Jan, 2001) */
   
           //
           //  Ok, almost done with the algorithm... We now enter the
  @@ -722,9 +685,9 @@
   
               // Loop through each possible input symbol in the element map
               CMStateSet newSet = null;
  -	        /* Optimization(Jan, 2001) */
  +            /* Optimization(Jan, 2001) */
               int sorterIndex = 0;
  -	        /* Optimization(Jan, 2001) */
  +            /* Optimization(Jan, 2001) */
               for (int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++) {
                   //
                   //  Build up a set of states which is the union of all of
  @@ -737,11 +700,11 @@
                   else
                       newSet.zeroBits();
   
  -	            /* Optimization(Jan, 2001) */
  +                /* Optimization(Jan, 2001) */
                   int leafIndex = fLeafSorter[sorterIndex++];
   
                   while (leafIndex != -1) {
  -	                // If this leaf index (DFA position) is in the current set...
  +                    // If this leaf index (DFA position) is in the current set...
                       if (setT.getBit(leafIndex)) {
                           //
                           //  If this leaf is the current input symbol, then we
  @@ -752,8 +715,8 @@
                       }
   
                      leafIndex = fLeafSorter[sorterIndex++];
  -	            }
  -	            /* Optimization(Jan, 2001) */
  +                }
  +                /* Optimization(Jan, 2001) */
   
                   //
                   //  If this new set is not empty, then see if its in the list
  @@ -765,10 +728,10 @@
                       //  state set is already in there.
                       //
   
  -	                /* Optimization(Jan, 2001) */
  -	                Integer stateObj = (Integer)stateTable.get(newSet);
  -	                int stateIndex = (stateObj == null ? curState : stateObj.intValue());
  -	                /* Optimization(Jan, 2001) */
  +                    /* Optimization(Jan, 2001) */
  +                    Integer stateObj = (Integer)stateTable.get(newSet);
  +                    int stateIndex = (stateObj == null ? curState : stateObj.intValue());
  +                    /* Optimization(Jan, 2001) */
   
                       // If we did not find it, then add it
                       if (stateIndex == curState) {
  @@ -780,9 +743,9 @@
                           statesToDo[curState] = newSet;
                           fTransTable[curState] = makeDefStateList();
   
  -	                    /* Optimization(Jan, 2001) */ 
  +                        /* Optimization(Jan, 2001) */
                           stateTable.put(newSet, new Integer(curState));
  -	                    /* Optimization(Jan, 2001) */
  +                        /* Optimization(Jan, 2001) */
   
                           // We now have a new state to do so bump the count
                           curState++;
  @@ -885,7 +848,7 @@
               }
           }
            else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE
  -	    || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE) {
  +        || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE) {
               // Recurse first
               calcFollowList(((XSCMUniOp)nodeCur).getChild());
   
  @@ -1023,7 +986,7 @@
           // Recurse as required
           if (nodeCur.type() == XSParticleDecl.PARTICLE_WILDCARD) {
               // REVISIT: Don't waste these structures.
  -			fElementDecl = ((XSCMAny)nodeCur).getURI();
  +            fElementDecl = ((XSCMAny)nodeCur).getURI();
               // REVISIT:  depends on result of XSDElement->XSDWildcard discussions...
               fLeafList[curIndex] = new XSCMLeaf(fElementDecl, ((XSCMAny)nodeCur).getPosition());
               fLeafListType[curIndex] = nodeCur.type();
  @@ -1036,8 +999,8 @@
               curIndex = postTreeBuildInit(((XSCMBinOp)nodeCur).getRight(), curIndex);
           }
            else if (nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_MORE
  -	     || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE
  -	     || nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE)
  +         || nodeCur.type() == XSParticleDecl.PARTICLE_ONE_OR_MORE
  +         || nodeCur.type() == XSParticleDecl.PARTICLE_ZERO_OR_ONE)
           {
               curIndex = postTreeBuildInit(((XSCMUniOp)nodeCur).getChild(), curIndex);
           }
  
  
  
  1.40      +29 -28    xml-xerces/java/src/org/apache/xerces/impl/v2/XSDHandler.java
  
  Index: XSDHandler.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSDHandler.java,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- XSDHandler.java	2001/10/11 19:42:19	1.39
  +++ XSDHandler.java	2001/10/15 22:55:16	1.40
  @@ -97,7 +97,7 @@
    * schema, other grammars may be constructed as a side-effect.
    *
    * @author Neil Graham, IBM
  - * @version $Id: XSDHandler.java,v 1.39 2001/10/11 19:42:19 neilg Exp $
  + * @version $Id: XSDHandler.java,v 1.40 2001/10/15 22:55:16 sandygao Exp $
    */
   
   class XSDHandler {
  @@ -156,7 +156,7 @@
       // publicId and systemId of the inputSource corresponding to a
       // schema document.  This combination is used so that the user's
       // EntityResolver can provide a consistent way of identifying a
  -    // schema document that is included in multiple other schemas.  
  +    // schema document that is included in multiple other schemas.
       private SymbolHash fTraversed = new SymbolHash();
   
       // the primary XSDocumentInfo we were called to parse
  @@ -179,7 +179,7 @@
       private Hashtable fRedefinedRestrictedAttributeGroupRegistry = new Hashtable();
       private Hashtable fRedefinedRestrictedGroupRegistry = new Hashtable();
   
  -    // a variable storing whether the last schema document 
  +    // a variable storing whether the last schema document
       // processed (by getSchema) was a duplicate.
       private boolean fLastSchemaWasDuplicate;
   
  @@ -249,8 +249,9 @@
       // it should be possible to use the same XSDHandler to parse
       // multiple schema documents; this will allow one to be
       // constructed.
  -    XSDHandler (XSGrammarResolver gResolver) {
  +    XSDHandler (XSGrammarResolver gResolver, SubstitutionGroupHandler subGroupHandler) {
           fGrammarResolver = gResolver;
  +        fSubGroupHandler = subGroupHandler;
   
           // REVISIT: do we use shadowed or synchronized symbol table of
           //          SchemaSymbols.fSymbolTable?
  @@ -276,7 +277,7 @@
                                 String schemaHint) {
   
           // first phase:  construct trees.
  -        Document schemaRoot = getSchema(schemaNamespace, schemaHint); 
  +        Document schemaRoot = getSchema(schemaNamespace, schemaHint);
           if(schemaRoot == null) {
               // something went wrong right off the hop
               fElementTraverser.reportGenericSchemaError("Could not locate a schema document corresponding to grammar " + schemaNamespace);
  @@ -286,7 +287,7 @@
           if (schemaNamespace.length() == 0) {
               schemaNamespace = null;
           }
  -        else {        
  +        else {
               schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
           }
           fRoot = constructTrees(schemaRoot, schemaNamespace);
  @@ -333,8 +334,8 @@
           if(schemaRoot == null) return null;
           XSDocumentInfo currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable);
   
  -		 // Modified by Pavani Mukthipudi, Sun Microsystems Inc.
  -		 fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
  +         // Modified by Pavani Mukthipudi, Sun Microsystems Inc.
  +         fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
   
           if(callerTNS != null) {
               // only set if we were included or redefined in.
  @@ -368,11 +369,11 @@
                   Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
                   schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
                   schemaNamespace = (String)includeAttrs[XSAttributeChecker.ATTIDX_NAMESPACE];
  -                if(schemaNamespace != null) 
  +                if(schemaNamespace != null)
                       schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
                   if(schemaNamespace == currSchemaInfo.fTargetNamespace) {
                       fElementTraverser.reportSchemaError("src-import.1.1", new Object [] {schemaNamespace});
  -                } 
  +                }
                   fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo);
                   // consciously throw away whether was a duplicate; don't care.
                   newSchemaRoot = getSchema(schemaNamespace, schemaHint);
  @@ -394,13 +395,13 @@
                   break;
               }
   
  -		     // If the schema is duplicate, we needn't call constructTrees() again.
  -		     // To handle mutual <include>s
  +             // If the schema is duplicate, we needn't call constructTrees() again.
  +             // To handle mutual <include>s
   
               XSDocumentInfo newSchemaInfo = null;
  -		     if (fLastSchemaWasDuplicate) {
  -		 		 newSchemaInfo = (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot);
  -		     } else { 
  +             if (fLastSchemaWasDuplicate) {
  +                 newSchemaInfo = (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot);
  +             } else {
                   newSchemaInfo = constructTrees(newSchemaRoot, schemaNamespace);
               }
               if (localName.equals(SchemaSymbols.ELT_REDEFINE)) {
  @@ -695,7 +696,7 @@
                   break;
               default:
                   // REVISIT: report internal error...
  -                fElementTraverser.reportGenericSchemaError("XSDHandler asked to locate component of type " + declType + "; it does not recognize this type (internal error!)"); 
  +                fElementTraverser.reportGenericSchemaError("XSDHandler asked to locate component of type " + declType + "; it does not recognize this type (internal error!)");
               }
               if (decl != null)
                   schemaWithDecl = findXSDocumentForDecl(currSchema, decl);
  @@ -814,8 +815,8 @@
       }
   
       // This method squirrels away <keyref> declarations--along with the element
  -    // decls and namespace bindings they might find handy.  
  -    protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc, 
  +    // decls and namespace bindings they might find handy.
  +    protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc,
               XSElementDecl currElemDecl) {
           String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME);
           if(keyrefName.length() != 0) {
  @@ -824,7 +825,7 @@
               checkForDuplicateNames(keyrefQName, fUnparsedIdentityConstraintRegistry, keyrefToStore, schemaDoc);
           }
           // now set up all the registries we'll need...
  -        
  +
           // check array sizes
           if(fKeyrefStackPos == fKeyrefs.length) {
               Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
  @@ -847,7 +848,7 @@
       // the given namespace and hint, it returns it.  It returns true
       // if this is the first time it's seen this document, false
       // otherwise.  schemaDoc is null if and only if no schema document
  -    // was resolved to.  
  +    // was resolved to.
       private Document getSchema(String schemaNamespace,
                                  String schemaHint) {
           // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc.
  @@ -861,7 +862,7 @@
                       schemaIdBuf.append(schemaSource.getPublicId());
                   if(schemaSource.getSystemId() != null)
                       schemaIdBuf.append(schemaSource.getSystemId());
  -                if(schemaIdBuf.equals(EMPTY_STRING)) 
  +                if(schemaIdBuf.equals(EMPTY_STRING))
                       schemaIdBuf.append(schemaSource.getBaseSystemId());
                   String schemaId =
                       fSymbolTable.addSymbol(schemaIdBuf.toString());
  @@ -895,7 +896,6 @@
       // construct schemaGrammars.
       private void createTraversers() {
           fAttributeChecker = new XSAttributeChecker(this);
  -        fSubGroupHandler = new SubstitutionGroupHandler(fGrammarResolver);
           fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker);
           fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker);
           fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker);
  @@ -975,7 +975,7 @@
        */
       void traverseLocalElements() {
           fElementTraverser.fDeferTraversingLocalElements = false;
  -        
  +
           for (int i = 0; i < fLocalElemStackPos; i++) {
               Element currElem = fLocalElementDecl[i];
               XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getDocument(currElem));
  @@ -1050,14 +1050,14 @@
                       currComp.setAttribute(SchemaSymbols.ATT_NAME, newName);
                       registry.put(qName+REDEF_IDENTIFIER, currComp);
                       // and take care of nested redefines by calling recursively:
  -                    if(currSchema.fTargetNamespace == null) 
  +                    if(currSchema.fTargetNamespace == null)
                           checkForDuplicateNames(","+newName, registry, currComp, currSchema);
  -                    else 
  +                    else
                           checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, registry, currComp, currSchema);
                   } else { // we're apparently redefining the wrong schema
                       // REVISIT:  error that redefined element in wrong schema
                       fElementTraverser.reportSchemaError("src-redefine.1", new Object [] {qName});
  -                } 
  +                }
               } else { // we've just got a flat-out collision
                   fElementTraverser.reportSchemaError("sch-props-correct.2", new Object []{qName});
               }
  @@ -1206,7 +1206,7 @@
               } else if (groupRefsCount == 1) {
   //                return true;
               }  else {
  -                if(currSchema.fTargetNamespace == null) 
  +                if(currSchema.fTargetNamespace == null)
                       fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName);
                   else
                       fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
  @@ -1327,7 +1327,8 @@
       /******* only for testing!  ******/
       public static void main (String args[]) throws Exception {
           DefaultHandler handler = new DefaultHandler();
  -        XSDHandler me = new XSDHandler(new XSGrammarResolver());
  +        XSGrammarResolver xsg = new XSGrammarResolver();
  +        XSDHandler me = new XSDHandler(xsg, new SubstitutionGroupHandler(xsg));
           XMLErrorReporter rep = new XMLErrorReporter();
           rep.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());
           me.reset(rep, new EntityResolverWrapper(new org.apache.xerces.impl.v2.XSDHandler.DummyResolver()), new SymbolTable());
  
  
  
  1.2       +13 -13    xml-xerces/java/src/org/apache/xerces/impl/v2/XSMixedCM.java
  
  Index: XSMixedCM.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSMixedCM.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- XSMixedCM.java	2001/10/01 19:42:14	1.1
  +++ XSMixedCM.java	2001/10/15 22:55:16	1.2
  @@ -61,16 +61,16 @@
   
   /**
    * XSMixedCM is a derivative of the abstract content model base class that
  - * handles a mixed content model with no chilren (elements). 
  + * handles a mixed content model with no chilren (elements).
    * In the future, this class may handle a small subset of mixed content
  - * model with limited number of children (for example, a mixed content model 
  - * with one child) 
  - * 
  + * model with limited number of children (for example, a mixed content model
  + * with one child)
  + *
    * This model validated on the way in.
  - * 
  + *
    * @author Elena Litani
    * @author IBM
  - * @version $Id: XSMixedCM.java,v 1.1 2001/10/01 19:42:14 elena Exp $
  + * @version $Id: XSMixedCM.java,v 1.2 2001/10/15 22:55:16 sandygao Exp $
    */
   public class XSMixedCM  implements XSCMValidator {
   
  @@ -85,8 +85,8 @@
       // Data
       //
       private int[] fState = {STATE_START};
  -    
   
  +
       //
       // XSCMValidator methods
       //
  @@ -109,15 +109,15 @@
        * @param state  Current state
        * @return element index corresponding to the element from the Schema grammar
        */
  -    public Object oneTransition (QName elementName, int[] currentState){
  +    public Object oneTransition (QName elementName, int[] currentState, SubstitutionGroupHandler subGroupHandler){
           // mixed content model do not have any children
   
  -        int state = currentState[0];
           // error state
  -        if (state < 0 ) {
  +        if (currentState[0] == XSCMValidator.FIRST_ERROR) {
  +            currentState[0] = XSCMValidator.SUBSEQUENT_ERROR;
               return null;
           }
  -        
  +
           currentState[0] = XSCMValidator.FIRST_ERROR;
           return null;
       }
  @@ -132,10 +132,10 @@
       public boolean endContentModel (int[] currentState){
           boolean isFinal =  false;
           int state = currentState[0];
  -        
  +
           // restore content model state:
           fState[0] = STATE_START;
  -        
  +
           // error
           if (state < 0) {
               return false;
  
  
  
  1.6       +22 -16    xml-xerces/java/src/org/apache/xerces/impl/v2/XSSimpleCM.java
  
  Index: XSSimpleCM.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/impl/v2/XSSimpleCM.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- XSSimpleCM.java	2001/10/01 19:42:14	1.5
  +++ XSSimpleCM.java	2001/10/15 22:55:16	1.6
  @@ -81,7 +81,7 @@
    * This model validated on the way in.
    *
    * @author Elena Litani, IBM
  - * @version $Id: XSSimpleCM.java,v 1.5 2001/10/01 19:42:14 elena Exp $
  + * @version $Id: XSSimpleCM.java,v 1.6 2001/10/15 22:55:16 sandygao Exp $
    */
   public class XSSimpleCM
   implements XSCMValidator {
  @@ -127,7 +127,7 @@
       public XSSimpleCM(short operator, XSElementDecl elem) {
           fFirstElement = elem;
           fOperator = operator;
  -        
  +
       }
   
       /**
  @@ -139,11 +139,11 @@
           fFirstElement = elem1;
           fSecondElement = elem2;
           fOperator = operator;
  -        
  +
       }
   
  -    
   
  +
       //
       // XSCMValidator methods
       //
  @@ -166,22 +166,23 @@
        * @param state  Current state
        * @return element index corresponding to the element from the Schema grammar
        */
  -    public Object oneTransition (QName elementName, int[] currentState){
  +    public Object oneTransition (QName elementName, int[] currentState, SubstitutionGroupHandler subGroupHandler){
   
  -        int state = currentState[0];
           // error state
  -        if (state < 0 ) {
  +        if (currentState[0] == XSCMValidator.FIRST_ERROR) {
  +            currentState[0] = XSCMValidator.SUBSEQUENT_ERROR;
               return null;
           }
   
  +        int state = currentState[0];
   
  -        
           switch (fOperator) {
           case XSParticleDecl.PARTICLE_ELEMENT :
           case XSParticleDecl.PARTICLE_ZERO_OR_ONE :
               if (state == STATE_START) {
                   if (fFirstElement.fTargetNamespace == elementName.uri &&
  -                    fFirstElement.fName == elementName.localpart) {
  +                    fFirstElement.fName == elementName.localpart ||
  +                    subGroupHandler.substitutionGroupOK(elementName, fFirstElement)) {
                       currentState[0] = STATE_VALID;
                       return fFirstElement;
                   }
  @@ -192,7 +193,8 @@
           case XSParticleDecl.PARTICLE_ZERO_OR_MORE :
           case XSParticleDecl.PARTICLE_ONE_OR_MORE :
               if (fFirstElement.fTargetNamespace == elementName.uri &&
  -                fFirstElement.fName == elementName.localpart) {
  +                fFirstElement.fName == elementName.localpart ||
  +                subGroupHandler.substitutionGroupOK(elementName, fFirstElement)) {
                   currentState[0] = STATE_VALID;
                   return fFirstElement;
               }
  @@ -201,13 +203,15 @@
           case XSParticleDecl.PARTICLE_CHOICE :
               if (state == STATE_START) {
                   if (fFirstElement.fTargetNamespace == elementName.uri &&
  -                    fFirstElement.fName == elementName.localpart) {
  +                    fFirstElement.fName == elementName.localpart ||
  +                    subGroupHandler.substitutionGroupOK(elementName, fFirstElement)) {
                       currentState[0] = STATE_VALID;
                       return fFirstElement;
   
                   }
                   else if (fSecondElement.fTargetNamespace == elementName.uri &&
  -                         fSecondElement.fName == elementName.localpart) {
  +                         fSecondElement.fName == elementName.localpart ||
  +                         subGroupHandler.substitutionGroupOK(elementName, fSecondElement)) {
                       currentState[0] = STATE_VALID;
                       return fSecondElement;
                   }
  @@ -223,7 +227,8 @@
               //
               if (state == STATE_START) {
                   if (fFirstElement.fTargetNamespace == elementName.uri &&
  -                    fFirstElement.fName == elementName.localpart) {
  +                    fFirstElement.fName == elementName.localpart ||
  +                    subGroupHandler.substitutionGroupOK(elementName, fFirstElement)) {
                       currentState[0] = STATE_FIRST;
                       return fFirstElement;
                   }
  @@ -231,7 +236,8 @@
               }
               else if (state == STATE_FIRST) {
                   if (fSecondElement.fTargetNamespace == elementName.uri &&
  -                    fSecondElement.fName == elementName.localpart) {
  +                    fSecondElement.fName == elementName.localpart ||
  +                    subGroupHandler.substitutionGroupOK(elementName, fSecondElement)) {
                       currentState[0] = STATE_VALID;
                       return fSecondElement;
                   }
  @@ -258,10 +264,10 @@
       public boolean endContentModel (int[] currentState){
           boolean isFinal =  false;
           int state = currentState[0];
  -        
  +
           // restore content model state:
           fState[0] = STATE_START;
  -        
  +
           // error
           if (state < 0) {
               return false;
  
  
  

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