sandygao    2003/02/12 06:44:19

  Modified:    java/src/org/apache/xerces/impl/xs
                        SubstitutionGroupHandler.java
  Log:
  Erratum E1-23: the definition of "substitution group" was changed so that
  some element declarations (those blocked by either the head or one of the
  type definitions) aren't in the substitution group anymore.
  
  Revision  Changes    Path
  1.12      +144 -39   
xml-xerces/java/src/org/apache/xerces/impl/xs/SubstitutionGroupHandler.java
  
  Index: SubstitutionGroupHandler.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xerces/java/src/org/apache/xerces/impl/xs/SubstitutionGroupHandler.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- SubstitutionGroupHandler.java     10 Feb 2003 14:40:59 -0000      1.11
  +++ SubstitutionGroupHandler.java     12 Feb 2003 14:44:19 -0000      1.12
  @@ -119,12 +119,17 @@
       // 3.3.6 Substitution Group OK (Transitive)
       // check whether element can substitute exemplar
       protected 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.
  +        // For an element declaration (call it D) to be validly substitutable for 
another element declaration (call it C) subject to a blocking constraint (a subset of 
{substitution, extension, restriction}, the value of a {disallowed substitutions}) one 
of the following must be true:
  +        // 1. D and C are the same element declaration.
  +        if (element == exemplar)
  +            return true;
  +        
  +        // 2 All of the following must be true:
  +        // 2.1 The blocking constraint does not contain substitution.
           if ((blockingConstraint & XSConstants.DERIVATION_SUBSTITUTION) != 0)
               return false;
   
  -        // 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 . . .
  +        // 2.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) {
               subGroup = subGroup.fSubGroup;
  @@ -133,7 +138,7 @@
           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}.
  +        // 2.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}.
           // prepare the combination of {derivation method} and
           // {disallowed substitution}
           short devMethod = 0, blockConstraint = blockingConstraint;
  @@ -166,27 +171,33 @@
   
       // check whether element is in exemplar's substitution group
       public boolean inSubstitutionGroup(XSElementDecl element, XSElementDecl 
exemplar) {
  -        // [Definition:]  Every element declaration in the {element declarations} 
of a schema defines a substitution group, a subset of those {element declarations}, as 
follows:
  -        // 1 The element declaration itself is in the group;
  -        // 2 The group is closed with respect to {substitution group affiliation}, 
that is, if any element declaration in the {element declarations} has a {substitution 
group affiliation} in the group, then it is also in the group itself.
  -        while (element != null && element != exemplar) {
  -            element = element.fSubGroup;
  -        }
  -        return (element != null);
  +        // [Definition:]  Every element declaration (call this HEAD) in the 
{element declarations} of a schema defines a substitution group, a subset of those 
{element declarations}, as follows:
  +        // Define PSG, the potential substitution group for HEAD, as follows:
  +        // 1 The element declaration itself is in PSG;
  +        // 2 PSG is closed with respect to {substitution group affiliation}, that 
is, if any element declaration in the {element declarations} has a {substitution group 
affiliation} in PSG, then it is also in PSG itself.
  +        // HEAD's actual substitution group is then the set consisting of each 
member of PSG such that all of the following must be true:
  +        // 1 Its {abstract} is false.
  +        // 2 It is validly substitutable for HEAD subject to an empty blocking 
constraint, as defined in Substitution Group OK (Transitive) (3.3.6).
  +        // REVISIT: should use exemplar.fBlock
  +        return substitutionGroupOK(element, exemplar, (short)0);
  +        //return substitutionGroupOK(element, exemplar, exemplar.fBlock);
       }
   
       // to store substitution group information
       // the key to the hashtable is an element decl, and the value is
       // - a Vector, which contains all elements that has this element as their
       //   substitution group affilication
  -    // - an array, which contains its substitution group.
  +    // - an array of OneSubGroup, which contains its substitution group before 
block.
  +    Hashtable fSubGroupsB = new Hashtable();
  +    private static final OneSubGroup[] EMPTY_VECTOR = new OneSubGroup[0];
  +    // The real substitution groups (after "block")
       Hashtable fSubGroups = new Hashtable();
  -    private static final XSElementDecl[] EMPTY_VECTOR = new XSElementDecl[0];
   
       /**
        * clear the internal registry of substitutionGroup information
        */
       public void reset() {
  +        fSubGroupsB.clear();
           fSubGroups.clear();
       }
   
  @@ -201,11 +212,11 @@
               element = elements[i];
               subHead = element.fSubGroup;
               // check whether this an entry for this element
  -            subGroup = (Vector)fSubGroups.get(subHead);
  +            subGroup = (Vector)fSubGroupsB.get(subHead);
               if (subGroup == null) {
                   // if not, create a new one
                   subGroup = new Vector();
  -                fSubGroups.put(subHead, subGroup);
  +                fSubGroupsB.put(subHead, subGroup);
               }
               // add to the vactor
               subGroup.addElement(element);
  @@ -221,34 +232,128 @@
        * containt this element.
        */
       public XSElementDecl[] getSubstitutionGroup(XSElementDecl element) {
  -        XSElementDecl[] ret;
  +        // If we already have sub group for this element, just return it.
           Object subGroup = fSubGroups.get(element);
  +        if (subGroup != null)
  +            return (XSElementDecl[])subGroup;
  +        
  +        // Otherwise, get all potential sub group elements
  +        // (without considering "block" on this element
  +        OneSubGroup[] groupB = getSubGroupB(element, new OneSubGroup());
  +        int len = groupB.length, rlen = 0;
  +        XSElementDecl[] ret = new XSElementDecl[len];
  +        // For each of such elements, check whether the derivation methods
  +        // overlap with "block". If not, add it to the sub group
  +        for (int i = 0 ; i < len; i++) {
  +            if ((element.fBlock & groupB[i].dMethod) == 0)
  +                ret[rlen++] = groupB[i].sub;
  +        }
  +        // Resize the array if necessary
  +        if (rlen < len) {
  +            XSElementDecl[] ret1 = new XSElementDecl[rlen];
  +            System.arraycopy(ret, 0, ret1, 0, rlen);
  +            ret = ret1;
  +        }
  +        // Store the subgroup
  +        fSubGroups.put(element, ret);
  +
  +        return ret;
  +    }
  +
  +    // Get potential sub group element (without considering "block")
  +    private OneSubGroup[] getSubGroupB(XSElementDecl element, OneSubGroup methods) {
  +        Object subGroup = fSubGroupsB.get(element);
  +
  +        // substitution group for this one is empty
           if (subGroup == null) {
  -            // substitution group for this one is empty
  -            ret = EMPTY_VECTOR;
  -            fSubGroups.put(element, ret);
  -        } else if (subGroup instanceof XSElementDecl[]) {
  -            // we've already calculated the element, just return.
  -            ret = (XSElementDecl[])subGroup;
  -        } else {
  -            // we only have the *direct* substitutions
  -            Vector group = (Vector)subGroup;
  -            XSElementDecl[] group1;
  -            // then for each of the direct substitutions, get its substitution
  -            // group, and combine the groups together.
  -            for (int i = group.size()-1, j; i >= 0; i--) {
  -                group1 = getSubstitutionGroup((XSElementDecl)group.elementAt(i));
  -                for (j = group1.length-1; j >= 0; j--)
  -                    group.addElement(group1[j]);
  -            }
  -            ret = new XSElementDecl[group.size()];
  -            for (int i = group.size()-1; i >= 0; i--) {
  -                ret[i] = (XSElementDecl)group.elementAt(i);
  +            fSubGroupsB.put(element, EMPTY_VECTOR);
  +            return EMPTY_VECTOR;
  +        }
  +        
  +        // we've already calculated the element, just return.
  +        if (subGroup instanceof OneSubGroup[])
  +            return (OneSubGroup[])subGroup;
  +        
  +        // we only have the *direct* substitutions
  +        Vector group = (Vector)subGroup, newGroup = new Vector();
  +        OneSubGroup[] group1;
  +        // then for each of the direct substitutions, get its substitution
  +        // group, and combine the groups together.
  +        short dMethod, bMethod, dSubMethod, bSubMethod;
  +        for (int i = group.size()-1, j; i >= 0; i--) {
  +            // Check whether this element is blocked. If so, ignore it.
  +            XSElementDecl sub = (XSElementDecl)group.elementAt(i);
  +            if (!getDBMethods(sub.fType, element.fType, methods))
  +                continue;
  +            // Remember derivation methods and blocks from the types
  +            dMethod = methods.dMethod;
  +            bMethod = methods.bMethod;
  +            // Add this one to potential group
  +            newGroup.addElement(new OneSubGroup(sub, methods.dMethod, 
methods.bMethod));
  +            // Get potential group for this element
  +            group1 = getSubGroupB(sub, methods);
  +            for (j = group1.length-1; j >= 0; j--) {
  +                // For each of them, check whether it's blocked (by type)
  +                dSubMethod = (short)(dMethod | group1[j].dMethod);
  +                bSubMethod = (short)(bMethod | group1[j].bMethod);
  +                // Ignore it if it's blocked
  +                if ((dSubMethod & bSubMethod) != 0)
  +                    continue;
  +                group.addElement(new OneSubGroup(group1[j].sub, dSubMethod, 
bSubMethod));
               }
  -            fSubGroups.put(element, ret);
           }
  -
  +        // Convert to an array
  +        OneSubGroup[] ret = new OneSubGroup[newGroup.size()];
  +        for (int i = newGroup.size()-1; i >= 0; i--) {
  +            ret[i] = (OneSubGroup)newGroup.elementAt(i);
  +        }
  +        // Store the potential sub group
  +        fSubGroupsB.put(element, ret);
  +        
           return ret;
       }
   
  +    private boolean getDBMethods(XSTypeDefinition typed, XSTypeDefinition typeb,
  +                                 OneSubGroup methods) {
  +        short dMethod = 0, bMethod = 0;
  +        while (typed != typeb && typed != SchemaGrammar.fAnyType) {
  +            if (typed.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
  +                dMethod |= ((XSComplexTypeDecl)typed).fDerivedBy;
  +            else
  +                dMethod |= XSConstants.DERIVATION_RESTRICTION;
  +            typed = typed.getBaseType();
  +            // type == null means the current type is anySimpleType,
  +            // whose base type should be anyType
  +            if (typed == null)
  +                typed = SchemaGrammar.fAnyType;
  +            if (typed.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
  +                bMethod |= ((XSComplexTypeDecl)typed).fBlock;
  +        }
  +        // No derivation relation, or blocked, return false
  +        if (typed != typeb || (dMethod & bMethod) != 0)
  +            return false;
  +        
  +        // Remember the derivation methods and blocks, return true.
  +        methods.dMethod = dMethod;
  +        methods.bMethod = bMethod;
  +        return true;
  +    }
  +
  +    // Record the information about how one element substitute another one
  +    private static final class OneSubGroup {
  +        OneSubGroup() {}
  +        OneSubGroup(XSElementDecl sub, short dMethod, short bMethod) {
  +            this.sub = sub;
  +            this.dMethod = dMethod;
  +            this.bMethod = bMethod;
  +        }
  +        // The element that substitutes another one
  +        XSElementDecl sub;
  +        // The combination of all derivation methods from sub's type to
  +        // the head's type
  +        short dMethod;
  +        // The combination of {block} of the types in the derivation chain
  +        // excluding sub's type
  +        short bMethod;
  +    }
   } // class SubstitutionGroupHandler
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to