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]