blob: 84a6a64c0bb96f0cec7c6a64f372f4f19ce0f1a7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xerces.impl.xs;
import org.apache.xerces.impl.XMLErrorReporter;
import org.apache.xerces.impl.xs.models.CMBuilder;
import org.apache.xerces.util.SymbolHash;
/**
* XML Schema 1.0 constraints
*
* @xerces.internal
*
* @author Sandy Gao, IBM
* @author Khaled Noaman, IBM
*
* @version $Id$
*
*/
class XS10Constraints extends XSConstraints {
// accomodate 1.0 extended
private short fSchemaVersion;
public XS10Constraints(short schemaVersion) {
super(SchemaGrammar.getXSAnyType(schemaVersion));
fSchemaVersion = schemaVersion;
}
public boolean overlapUPA(XSElementDecl element,
XSWildcardDecl wildcard,
SubstitutionGroupHandler sgHandler) {
// if the wildcard allows the element
if (wildcard.allowNamespace(element.fTargetNamespace))
return true;
// or if the wildcard allows any element in the substitution group
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element, fSchemaVersion);
for (int i = subGroup.length-1; i >= 0; i--) {
if (wildcard.allowNamespace(subGroup[i].fTargetNamespace))
return true;
}
return false;
}
public boolean overlapUPA(XSWildcardDecl wildcard1,
XSWildcardDecl wildcard2) {
// if the intersection of the two wildcard is not empty list
XSWildcardDecl intersect = performIntersectionWith(wildcard1, wildcard2, wildcard1.fProcessContents);
if (intersect == null ||
intersect.fType != XSWildcardDecl.NSCONSTRAINT_LIST ||
intersect.fNamespaceList.length != 0) {
return true;
}
return false;
}
public boolean overlapUPA(XSElementDecl element1,
XSElementDecl element2,
SubstitutionGroupHandler sgHandler) {
return overlapUPA(element1, element2, sgHandler, fSchemaVersion);
}
public void checkElementDeclsConsistent(XSComplexTypeDecl type,
XSParticleDecl particle,
SymbolHash elemDeclHash,
SubstitutionGroupHandler sgHandler) throws XMLSchemaException {
checkElementDeclsConsistent(type, particle, elemDeclHash, sgHandler, fSchemaVersion);
}
public void fullSchemaChecking(XSGrammarBucket grammarBucket,
SubstitutionGroupHandler SGHandler,
CMBuilder cmBuilder,
XMLErrorReporter errorReporter) {
fullSchemaChecking(grammarBucket, SGHandler, cmBuilder, errorReporter, fSchemaVersion);
}
/**
* Schema Component Constraint: Wildcard Subset
*
* wildcard.isSubsetOf(superWildcard)
*/
public boolean isSubsetOf(XSWildcardDecl wildcard, XSWildcardDecl superWildcard) {
// if the super is null (not expressible), return false
if (superWildcard == null) {
return false;
}
// For a namespace constraint (call it sub) to be an intensional subset of another
// namespace constraint (call it super) one of the following must be true:
// 1 super must be any.
if (superWildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY) {
return true;
}
// 2 All of the following must be true:
// 2.1 sub must be a pair of not and a namespace name or absent.
// 2.2 super must be a pair of not and the same value.
// * we can't just compare whether the namespace are the same value
// since we store other as not(list)
if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
if (superWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT &&
wildcard.fNamespaceList[0] == superWildcard.fNamespaceList[0]) {
return true;
}
}
// 3 All of the following must be true:
// 3.1 sub must be a set whose members are either namespace names or absent.
// 3.2 One of the following must be true:
// 3.2.1 super must be the same set or a superset thereof.
// -3.2.2 super must be a pair of not and a namespace name or absent and
// that value must not be in sub's set.
// +3.2.2 super must be a pair of not and a namespace name or absent and
// either that value or absent must not be in sub's set.
// * since we store ##other as not(list), we acturally need to make sure
// that none of the namespaces in super.list is in sub.list.
if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) {
if (superWildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST &&
subset2sets(wildcard.fNamespaceList, superWildcard.fNamespaceList)) {
return true;
}
if (superWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT &&
!elementInSet(superWildcard.fNamespaceList[0], wildcard.fNamespaceList) &&
!elementInSet(XSWildcardDecl.ABSENT, wildcard.fNamespaceList)) {
return true;
}
}
// none of the above conditions applied, so return false.
return false;
} // isSubsetOf
/**
* Schema Component Constraint: Attribute Wildcard Union
*/
public XSWildcardDecl performUnionWith(XSWildcardDecl wildcard,
XSWildcardDecl otherWildcard,
short processContents) {
// if the other wildcard is not expressible, the result is still not expressible
if (otherWildcard == null)
return null;
// For a wildcard's {namespace constraint} value to be the intensional union of two
// other such values (call them O1 and O2): the appropriate case among the following
// must be true:
XSWildcardDecl unionWildcard = new XSWildcardDecl();
unionWildcard.fProcessContents = processContents;
// 1 If O1 and O2 are the same value, then that value must be the value.
if (areSame(wildcard, otherWildcard)) {
unionWildcard.fType = wildcard.fType;
unionWildcard.fNamespaceList = wildcard.fNamespaceList;
}
// 2 If either O1 or O2 is any, then any must be the value.
else if ( (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY) || (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY) ) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_ANY;
}
// 3 If both O1 and O2 are sets of (namespace names or absent), then the union of
// those sets must be the value.
else if ( (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) ) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_LIST;
unionWildcard.fNamespaceList = union2sets(wildcard.fNamespaceList, otherWildcard.fNamespaceList);
}
// -4 If the two are negations of different namespace names, then the intersection
// is not expressible.
// +4 If the two are negations of different namespace names or absent, then
// a pair of not and absent must be the value.
// * now we store ##other as not(list), the result should be
// not(intersection of two lists).
else if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT && otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = new String[2];
unionWildcard.fNamespaceList[0] = XSWildcardDecl.ABSENT;
unionWildcard.fNamespaceList[1] = XSWildcardDecl.ABSENT;
}
// 5 If either O1 or O2 is a pair of not and a namespace name and the other is a set of
// (namespace names or absent), then The appropriate case among the following must be true:
// -5.1 If the set includes the negated namespace name, then any must be the value.
// -5.2 If the set does not include the negated namespace name, then whichever of O1 or O2
// is a pair of not and a namespace name must be the value.
// +5.1 If the negated value is a namespace name, then The appropriate case
// among the following must be true:
// +5.1.1 If the set includes both the namespace name and absent, then any
// must be the value.
// +5.1.2 If the set includes the namespace name but does not include
// absent, then a pair of not and absent must be the value.
// +5.1.3 If the set does not include the namespace name but includes
// absent, then the union is not expressible.
// +5.1.4 If the set does not include either the namespace name or absent,
// then whichever of O1 or O2 is a pair of not and a namespace name must be
// the value.
// +5.2 If the negated value is absent, then The appropriate case among the
// following must be true:
// +5.2.1 If the set includes absent, then any must be the value.
// +5.2.2 If the set does not include absent, then whichever of O1 or O2 is
// a pair of not and a namespace name must be the value.
// * when we have not(list), the operation is just not(otherlist-list)
else if ( ((wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST)) ||
((wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT)) ) {
String[] local = null;
String[] list = null;
if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
local = wildcard.fNamespaceList;
list = otherWildcard.fNamespaceList;
}
else {
local = otherWildcard.fNamespaceList;
list = wildcard.fNamespaceList;
}
boolean foundAbsent = elementInSet(XSWildcardDecl.ABSENT, list);
if (local[0] != XSWildcardDecl.ABSENT) {
boolean foundNS = elementInSet(local[0], list);
if (foundNS && foundAbsent) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_ANY;
} else if (foundNS && !foundAbsent) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = new String[2];
unionWildcard.fNamespaceList[0] = XSWildcardDecl.ABSENT;
unionWildcard.fNamespaceList[1] = XSWildcardDecl.ABSENT;
} else if (!foundNS && foundAbsent) {
return null;
} else { // !foundNS && !foundAbsent
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = local;
}
} else { // other[0] == ABSENT
if (foundAbsent) {
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_ANY;
} else { // !foundAbsent
unionWildcard.fType = XSWildcardDecl.NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = local;
}
}
}
return unionWildcard;
} // performUnionWith
/**
* Schema Component Constraint: Attribute Wildcard Intersection
*/
public XSWildcardDecl performIntersectionWith(XSWildcardDecl wildcard,
XSWildcardDecl otherWildcard,
short processContents) {
// if the other wildcard is not expressible, the result is still not expressible
if (otherWildcard == null)
return null;
// For a wildcard's {namespace constraint} value to be the intensional intersection of
// two other such values (call them O1 and O2): the appropriate case among the following
// must be true:
XSWildcardDecl intersectWildcard = new XSWildcardDecl();
intersectWildcard.fProcessContents = processContents;
// 1 If O1 and O2 are the same value, then that value must be the value.
if (areSame(wildcard, otherWildcard)) {
intersectWildcard.fType = wildcard.fType;
intersectWildcard.fNamespaceList = wildcard.fNamespaceList;
}
// 2 If either O1 or O2 is any, then the other must be the value.
else if ( (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY) || (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY) ) {
// both cannot be ANY, if we have reached here.
XSWildcardDecl other = wildcard;
if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_ANY)
other = otherWildcard;
intersectWildcard.fType = other.fType;
intersectWildcard.fNamespaceList = other.fNamespaceList;
}
// -3 If either O1 or O2 is a pair of not and a namespace name and the other is a set of
// (namespace names or absent), then that set, minus the negated namespace name if
// it was in the set, must be the value.
// +3 If either O1 or O2 is a pair of not and a namespace name and the other
// is a set of (namespace names or absent), then that set, minus the negated
// namespace name if it was in the set, then minus absent if it was in the
// set, must be the value.
// * when we have not(list), the operation is just list-otherlist
else if ( ((wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST)) ||
((wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT)) ) {
String[] list = null;
String[] other = null;
if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
other = wildcard.fNamespaceList;
list = otherWildcard.fNamespaceList;
}
else {
other = otherWildcard.fNamespaceList;
list = wildcard.fNamespaceList;
}
int listSize = list.length;
String[] intersect = new String[listSize];
int newSize = 0;
for (int i = 0; i < listSize; i++) {
if (list[i] != other[0] && list[i] != XSWildcardDecl.ABSENT)
intersect[newSize++] = list[i];
}
intersectWildcard.fType = XSWildcardDecl.NSCONSTRAINT_LIST;
intersectWildcard.fNamespaceList = new String[newSize];
System.arraycopy(intersect, 0, intersectWildcard.fNamespaceList, 0, newSize);
}
// 4 If both O1 and O2 are sets of (namespace names or absent), then the intersection of those
// sets must be the value.
else if ( (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) && (otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_LIST) ) {
intersectWildcard.fType = XSWildcardDecl.NSCONSTRAINT_LIST;
intersectWildcard.fNamespaceList = intersect2sets(wildcard.fNamespaceList, otherWildcard.fNamespaceList);
}
// -5 If the two are negations of different namespace names, then the intersection is not expressible.
// +5 If the two are negations of namespace names or absent, then The
// appropriate case among the following must be true:
// +5.1 If the two are negations of different namespace names, then the
// intersection is not expressible.
// +5.2 If one of the two is a pair of not and absent, the other must be
// the value.
// * when we have not(list), the operation is just not(onelist+otherlist)
else if (wildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT && otherWildcard.fType == XSWildcardDecl.NSCONSTRAINT_NOT) {
if (wildcard.fNamespaceList[0] != XSWildcardDecl.ABSENT && otherWildcard.fNamespaceList[0] != XSWildcardDecl.ABSENT)
return null;
XSWildcardDecl local = wildcard;
if (wildcard.fNamespaceList[0] == XSWildcardDecl.ABSENT)
local = otherWildcard;
intersectWildcard.fType = local.fType;
intersectWildcard.fNamespaceList = local.fNamespaceList;
}
return intersectWildcard;
} // performIntersectionWith
}