in src/org/apache/xerces/impl/xs/XSConstraints.java [605:988]
private static boolean particleValidRestriction(XSParticleDecl dParticle,
SubstitutionGroupHandler dSGHandler,
XSParticleDecl bParticle,
SubstitutionGroupHandler bSGHandler,
boolean checkWCOccurrence)
throws XMLSchemaException {
Vector dChildren = null;
Vector bChildren = null;
int dMinEffectiveTotalRange=OCCURRENCE_UNKNOWN;
int dMaxEffectiveTotalRange=OCCURRENCE_UNKNOWN;
// By default there has been no expansion
boolean bExpansionHappened = false;
// Check for empty particles. If either base or derived particle is empty,
// (and the other isn't) it's an error.
if (dParticle.isEmpty() && !bParticle.emptiable()) {
throw new XMLSchemaException("cos-particle-restrict.a", null);
}
else if (!dParticle.isEmpty() && bParticle.isEmpty()) {
throw new XMLSchemaException("cos-particle-restrict.b", null);
}
//
// Do setup prior to invoking the Particle (Restriction) cases.
// This involves:
// - removing pointless occurrences for groups, and retrieving a vector of
// non-pointless children
// - turning top-level elements with substitution groups into CHOICE groups.
//
short dType = dParticle.fType;
//
// Handle pointless groups for the derived particle
//
if (dType == XSParticleDecl.PARTICLE_MODELGROUP) {
dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
// Find a group, starting with this particle, with more than 1 child. There
// may be none, and the particle of interest trivially becomes an element or
// wildcard.
XSParticleDecl dtmp = getNonUnaryGroup(dParticle);
if (dtmp != dParticle) {
// Particle has been replaced. Retrieve new type info.
dParticle = dtmp;
dType = dParticle.fType;
if (dType == XSParticleDecl.PARTICLE_MODELGROUP)
dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
}
// Fill in a vector with the children of the particle, removing any
// pointless model groups in the process.
dChildren = removePointlessChildren(dParticle);
}
int dMinOccurs = dParticle.fMinOccurs;
int dMaxOccurs = dParticle.fMaxOccurs;
//
// For elements which are the heads of substitution groups, treat as CHOICE
//
if (dSGHandler != null && dType == XSParticleDecl.PARTICLE_ELEMENT) {
XSElementDecl dElement = (XSElementDecl)dParticle.fValue;
if (dElement.fScope == XSConstants.SCOPE_GLOBAL) {
// Check for subsitution groups. Treat any element that has a
// subsitution group as a choice. Fill in the children vector with the
// members of the substitution group
XSElementDecl[] subGroup = dSGHandler.getSubstitutionGroup(dElement);
if (subGroup.length >0 ) {
// Now, set the type to be CHOICE. The "group" will have the same
// occurrence information as the original particle.
dType = XSModelGroupImpl.MODELGROUP_CHOICE;
dMinEffectiveTotalRange = dMinOccurs;
dMaxEffectiveTotalRange = dMaxOccurs;
// Fill in the vector of children
dChildren = new Vector(subGroup.length+1);
for (int i = 0; i < subGroup.length; i++) {
addElementToParticleVector(dChildren, subGroup[i]);
}
addElementToParticleVector(dChildren, dElement);
Collections.sort(dChildren, ELEMENT_PARTICLE_COMPARATOR);
// Set the handler to null, to indicate that we've finished handling
// substitution groups for this particle.
dSGHandler = null;
}
}
}
short bType = bParticle.fType;
//
// Handle pointless groups for the base particle
//
if (bType == XSParticleDecl.PARTICLE_MODELGROUP) {
bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
// Find a group, starting with this particle, with more than 1 child. There
// may be none, and the particle of interest trivially becomes an element or
// wildcard.
XSParticleDecl btmp = getNonUnaryGroup(bParticle);
if (btmp != bParticle) {
// Particle has been replaced. Retrieve new type info.
bParticle = btmp;
bType = bParticle.fType;
if (bType == XSParticleDecl.PARTICLE_MODELGROUP)
bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
}
// Fill in a vector with the children of the particle, removing any
// pointless model groups in the process.
bChildren = removePointlessChildren(bParticle);
}
int bMinOccurs = bParticle.fMinOccurs;
int bMaxOccurs = bParticle.fMaxOccurs;
if (bSGHandler != null && bType == XSParticleDecl.PARTICLE_ELEMENT) {
XSElementDecl bElement = (XSElementDecl)bParticle.fValue;
if (bElement.fScope == XSConstants.SCOPE_GLOBAL) {
// Check for subsitution groups. Treat any element that has a
// subsitution group as a choice. Fill in the children vector with the
// members of the substitution group
XSElementDecl[] bsubGroup = bSGHandler.getSubstitutionGroup(bElement);
if (bsubGroup.length >0 ) {
// Now, set the type to be CHOICE
bType = XSModelGroupImpl.MODELGROUP_CHOICE;
bChildren = new Vector(bsubGroup.length+1);
for (int i = 0; i < bsubGroup.length; i++) {
addElementToParticleVector(bChildren, bsubGroup[i]);
}
addElementToParticleVector(bChildren, bElement);
Collections.sort(bChildren, ELEMENT_PARTICLE_COMPARATOR);
// Set the handler to null, to indicate that we've finished handling
// substitution groups for this particle.
bSGHandler = null;
// if we are here expansion of bParticle happened
bExpansionHappened = true;
}
}
}
//
// O.K. - Figure out which particle derivation rule applies and call it
//
switch (dType) {
case XSParticleDecl.PARTICLE_ELEMENT:
{
switch (bType) {
// Elt:Elt NameAndTypeOK
case XSParticleDecl.PARTICLE_ELEMENT:
{
checkNameAndTypeOK((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
(XSElementDecl)bParticle.fValue,bMinOccurs,bMaxOccurs);
return bExpansionHappened;
}
// Elt:Any NSCompat
case XSParticleDecl.PARTICLE_WILDCARD:
{
checkNSCompat((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
(XSWildcardDecl)bParticle.fValue,bMinOccurs,bMaxOccurs,
checkWCOccurrence);
return bExpansionHappened;
}
// Elt:All RecurseAsIfGroup
case XSModelGroupImpl.MODELGROUP_CHOICE:
{
// Treat the element as if it were in a group of the same type
// as the base Particle
dChildren = new Vector();
dChildren.addElement(dParticle);
checkRecurseLax(dChildren, 1, 1, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
case XSModelGroupImpl.MODELGROUP_ALL:
{
// Treat the element as if it were in a group of the same type
// as the base Particle
dChildren = new Vector();
dChildren.addElement(dParticle);
checkRecurse(dChildren, 1, 1, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
default:
{
throw new XMLSchemaException("Internal-Error",
new Object[]{"in particleValidRestriction"});
}
}
}
case XSParticleDecl.PARTICLE_WILDCARD:
{
switch (bType) {
// Any:Any NSSubset
case XSParticleDecl.PARTICLE_WILDCARD:
{
checkNSSubset((XSWildcardDecl)dParticle.fValue, dMinOccurs, dMaxOccurs,
(XSWildcardDecl)bParticle.fValue, bMinOccurs, bMaxOccurs);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_CHOICE:
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
case XSModelGroupImpl.MODELGROUP_ALL:
case XSParticleDecl.PARTICLE_ELEMENT:
{
throw new XMLSchemaException("cos-particle-restrict.2",
new Object[]{"any:choice,sequence,all,elt"});
}
default:
{
throw new XMLSchemaException("Internal-Error",
new Object[]{"in particleValidRestriction"});
}
}
}
case XSModelGroupImpl.MODELGROUP_ALL:
{
switch (bType) {
// All:Any NSRecurseCheckCardinality
case XSParticleDecl.PARTICLE_WILDCARD:
{
if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
dMaxEffectiveTotalRange,
dSGHandler,
bParticle,bMinOccurs,bMaxOccurs,
checkWCOccurrence);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_ALL:
{
checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_CHOICE:
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
case XSParticleDecl.PARTICLE_ELEMENT:
{
throw new XMLSchemaException("cos-particle-restrict.2",
new Object[]{"all:choice,sequence,elt"});
}
default:
{
throw new XMLSchemaException("Internal-Error",
new Object[]{"in particleValidRestriction"});
}
}
}
case XSModelGroupImpl.MODELGROUP_CHOICE:
{
switch (bType) {
// Choice:Any NSRecurseCheckCardinality
case XSParticleDecl.PARTICLE_WILDCARD:
{
if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
dMaxEffectiveTotalRange,
dSGHandler,
bParticle,bMinOccurs,bMaxOccurs,
checkWCOccurrence);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_CHOICE:
{
checkRecurseLax(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_ALL:
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
case XSParticleDecl.PARTICLE_ELEMENT:
{
throw new XMLSchemaException("cos-particle-restrict.2",
new Object[]{"choice:all,sequence,elt"});
}
default:
{
throw new XMLSchemaException("Internal-Error",
new Object[]{"in particleValidRestriction"});
}
}
}
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
{
switch (bType) {
// Choice:Any NSRecurseCheckCardinality
case XSParticleDecl.PARTICLE_WILDCARD:
{
if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
dMaxEffectiveTotalRange,
dSGHandler,
bParticle,bMinOccurs,bMaxOccurs,
checkWCOccurrence);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_ALL:
{
checkRecurseUnordered(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_SEQUENCE:
{
checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSModelGroupImpl.MODELGROUP_CHOICE:
{
int min1 = dMinOccurs * dChildren.size();
int max1 = (dMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)?
dMaxOccurs : dMaxOccurs * dChildren.size();
checkMapAndSum(dChildren, min1, max1, dSGHandler,
bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
return bExpansionHappened;
}
case XSParticleDecl.PARTICLE_ELEMENT:
{
throw new XMLSchemaException("cos-particle-restrict.2",
new Object[]{"seq:elt"});
}
default:
{
throw new XMLSchemaException("Internal-Error",
new Object[]{"in particleValidRestriction"});
}
}
}
}
return bExpansionHappened;
}