SubstitutionGroupHandlerpublic class SubstitutionGroupHandler extends Object To store and validate information about substitutionGroup |
Fields Summary |
---|
private static final XSElementDecl[] | EMPTY_GROUP | XSGrammarBucket | fGrammarBucket | Hashtable | fSubGroupsB | private static final OneSubGroup[] | EMPTY_VECTOR | Hashtable | fSubGroups |
Constructors Summary |
---|
public SubstitutionGroupHandler(XSGrammarBucket grammarBucket)Default constructor
fGrammarBucket = grammarBucket;
|
Methods Summary |
---|
public void | addSubstitutionGroup(XSElementDecl[] elements)add a list of substitution group information.
XSElementDecl subHead, element;
Vector subGroup;
// for all elements with substitution group affiliation
for (int i = elements.length-1; i >= 0; i--) {
element = elements[i];
subHead = element.fSubGroup;
// check whether this an entry for this element
subGroup = (Vector)fSubGroupsB.get(subHead);
if (subGroup == null) {
// if not, create a new one
subGroup = new Vector();
fSubGroupsB.put(subHead, subGroup);
}
// add to the vactor
subGroup.addElement(element);
}
| private boolean | getDBMethods(org.apache.xerces.xs.XSTypeDefinition typed, org.apache.xerces.xs.XSTypeDefinition typeb, org.apache.xerces.impl.xs.SubstitutionGroupHandler$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;
| public XSElementDecl | getMatchingElemDecl(org.apache.xerces.xni.QName element, XSElementDecl exemplar)
if (element.localpart == exemplar.fName &&
element.uri == exemplar.fTargetNamespace) {
return exemplar;
}
// if the exemplar is not a global element decl, then it's not possible
// to be substituted by another element.
if (exemplar.fScope != XSConstants.SCOPE_GLOBAL) {
return null;
}
// if the decl blocks substitution, return false
if ((exemplar.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) {
return null;
}
// get grammar of the element
SchemaGrammar sGrammar = fGrammarBucket.getGrammar(element.uri);
if (sGrammar == null) {
return null;
}
// get the decl for the element
XSElementDecl eDecl = sGrammar.getGlobalElementDecl(element.localpart);
if (eDecl == null) {
return null;
}
// and check by using substitutionGroup information
if (substitutionGroupOK(eDecl, exemplar, exemplar.fBlock)) {
return eDecl;
}
return null;
| private org.apache.xerces.impl.xs.SubstitutionGroupHandler$OneSubGroup[] | getSubGroupB(XSElementDecl element, org.apache.xerces.impl.xs.SubstitutionGroupHandler$OneSubGroup methods)
Object subGroup = fSubGroupsB.get(element);
// substitution group for this one is empty
if (subGroup == null) {
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;
newGroup.addElement(new OneSubGroup(group1[j].sub, dSubMethod, bSubMethod));
}
}
// 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;
| public XSElementDecl[] | getSubstitutionGroup(XSElementDecl element)get all elements that can substitute the given element,
according to the spec, we shouldn't consider the {block} constraints.
from the spec, substitution group of a given element decl also contains
the element itself. but the array returned from this method doesn't
containt this element.
// If we already have sub group for this element, just return it.
Object subGroup = fSubGroups.get(element);
if (subGroup != null)
return (XSElementDecl[])subGroup;
if ((element.fBlock & XSConstants.DERIVATION_SUBSTITUTION) != 0) {
fSubGroups.put(element, EMPTY_GROUP);
return EMPTY_GROUP;
}
// 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;
| public boolean | inSubstitutionGroup(XSElementDecl element, XSElementDecl exemplar)
// [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).
return substitutionGroupOK(element, exemplar, exemplar.fBlock);
| public void | reset()clear the internal registry of substitutionGroup information
fSubGroupsB.clear();
fSubGroups.clear();
| protected boolean | substitutionGroupOK(XSElementDecl element, XSElementDecl exemplar, short blockingConstraint)
// 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.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;
}
if (subGroup == null) {
return false;
}
// 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}
return typeDerivationOK(element.fType, exemplar.fType, blockingConstraint);
| private boolean | typeDerivationOK(org.apache.xerces.xs.XSTypeDefinition derived, org.apache.xerces.xs.XSTypeDefinition base, short blockingConstraint)
short devMethod = 0, blockConstraint = blockingConstraint;
// "derived" should be derived from "base"
// add derivation methods of derived types to devMethod;
// add block of base types to blockConstraint.
XSTypeDefinition type = derived;
while (type != base && type != SchemaGrammar.fAnyType) {
if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
devMethod |= ((XSComplexTypeDecl)type).fDerivedBy;
}
else {
devMethod |= XSConstants.DERIVATION_RESTRICTION;
}
type = type.getBaseType();
// type == null means the current type is anySimpleType,
// whose base type should be anyType
if (type == null) {
type = SchemaGrammar.fAnyType;
}
if (type.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
blockConstraint |= ((XSComplexTypeDecl)type).fBlock;
}
}
if (type != base) {
// If the base is a union, check if "derived" is allowed through any of the member types.
if (base.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
XSSimpleTypeDefinition st = (XSSimpleTypeDefinition) base;
if (st.getVariety() == XSSimpleTypeDefinition.VARIETY_UNION) {
XSObjectList memberTypes = st.getMemberTypes();
final int length = memberTypes.getLength();
for (int i = 0; i < length; ++i) {
if (typeDerivationOK(derived, (XSTypeDefinition) memberTypes.item(i), blockingConstraint)) {
return true;
}
}
}
}
return false;
}
if ((devMethod & blockConstraint) != 0) {
return false;
}
return true;
|
|