/*
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
/*
* 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 com.sun.org.apache.xerces.internal.impl.xs;
import com.sun.org.apache.xerces.internal.impl.xs.util.StringListImpl;
import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
import com.sun.org.apache.xerces.internal.xs.StringList;
import com.sun.org.apache.xerces.internal.xs.XSAnnotation;
import com.sun.org.apache.xerces.internal.xs.XSConstants;
import com.sun.org.apache.xerces.internal.xs.XSNamespaceItem;
import com.sun.org.apache.xerces.internal.xs.XSWildcard;
import com.sun.org.apache.xerces.internal.xs.XSObjectList;
The XML representation for a wildcard declaration
schema component is an or element information item
Author: Sandy Gao, IBM, Rahul Srivastava, Sun Microsystems Inc. @xerces.internal
/**
* The XML representation for a wildcard declaration
* schema component is an <any> or <anyAttribute> element information item
*
* @xerces.internal
*
* @author Sandy Gao, IBM
* @author Rahul Srivastava, Sun Microsystems Inc.
*
*/
public class XSWildcardDecl implements XSWildcard {
public static final String ABSENT = null;
// the type of wildcard: any, other, or list
public short fType = NSCONSTRAINT_ANY;
// the type of process contents: strict, lax, or skip
public short fProcessContents = PC_STRICT;
// the namespace list:
// for NSCONSTRAINT_LIST, it means one of the namespaces in the list
// for NSCONSTRAINT_NOT, it means not any of the namespaces in the list
public String[] fNamespaceList;
// optional annotation
public XSObjectList fAnnotations = null;
// I'm trying to implement the following constraint exactly as what the
// spec describes. Sometimes it seems redundant, and sometimes there seems
// to be much easier solutions. But it makes it easy to understand,
// easy to maintain, and easy to find a bug (either in the code, or in the
// spec). -SG
//
// NOTE: Schema spec only requires that ##other not(tNS,absent).
// The way we store ##other is not(NS1,NS2,...,NSN), which covers
// what's required by Schema, and allows future enhanced features.
//
// In the following in-line comments:
// - Bullet removed from w3c specification.
// + Bullet added as proposed by Sandy Gao, IBM.
// / Since we store ##other as not(NS1,NS2,...,NSN), we need to put some
// comments on where we didn't follow the spec exactly.
// * When we really support not(NS1,NS2,...,NSN), we need to revisit these items.
Validation Rule: Wildcard allows Namespace Name
/**
* Validation Rule: Wildcard allows Namespace Name
*/
public boolean allowNamespace(String namespace) {
// For a value which is either a namespace name or absent to be valid with respect to a wildcard constraint (the value of a {namespace constraint}) one of the following must be true:
// 1 The constraint must be any.
if (fType == NSCONSTRAINT_ANY)
return true;
// 2 All of the following must be true:
// 2.1 The constraint is a pair of not and a namespace name or absent ([Definition:] call this the namespace test).
// 2.2 The value must not be identical to the namespace test.
// 2.3 The value must not be absent.
// / we store ##other as not(list), so our actual rule is
// / 2 The constraint is a pair of not and a set, and the value is not in such set.
if (fType == NSCONSTRAINT_NOT) {
boolean found = false;
int listNum = fNamespaceList.length;
for (int i = 0; i < listNum && !found; i++) {
if (namespace == fNamespaceList[i])
found = true;
}
if (!found)
return true;
}
// 3 The constraint is a set, and the value is identical to one of the members of the set.
if (fType == NSCONSTRAINT_LIST) {
int listNum = fNamespaceList.length;
for (int i = 0; i < listNum; i++) {
if (namespace == fNamespaceList[i])
return true;
}
}
// none of the above conditions applied, so return false.
return false;
}
Schema Component Constraint: Wildcard Subset
/**
* Schema Component Constraint: Wildcard Subset
*/
public boolean isSubsetOf(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 == 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 (fType == NSCONSTRAINT_NOT) {
if (superWildcard.fType == NSCONSTRAINT_NOT &&
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 (fType == NSCONSTRAINT_LIST) {
if (superWildcard.fType == NSCONSTRAINT_LIST &&
subset2sets(fNamespaceList, superWildcard.fNamespaceList)) {
return true;
}
if (superWildcard.fType == NSCONSTRAINT_NOT &&
!elementInSet(superWildcard.fNamespaceList[0], fNamespaceList) &&
!elementInSet(ABSENT, fNamespaceList)) {
return true;
}
}
// none of the above conditions applied, so return false.
return false;
} // isSubsetOf
Check whether this wildcard has a weaker process contents than the super.
/**
* Check whether this wildcard has a weaker process contents than the super.
*/
public boolean weakerProcessContents(XSWildcardDecl superWildcard) {
return fProcessContents == XSWildcardDecl.PC_LAX &&
superWildcard.fProcessContents == XSWildcardDecl.PC_STRICT ||
fProcessContents == XSWildcardDecl.PC_SKIP &&
superWildcard.fProcessContents != XSWildcardDecl.PC_SKIP;
}
Schema Component Constraint: Attribute Wildcard Union
/**
* Schema Component Constraint: Attribute Wildcard Union
*/
public XSWildcardDecl performUnionWith(XSWildcardDecl wildcard,
short processContents) {
// if the other wildcard is not expressible, the result is still not expressible
if (wildcard == 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)) {
unionWildcard.fType = fType;
unionWildcard.fNamespaceList = fNamespaceList;
}
// 2 If either O1 or O2 is any, then any must be the value.
else if ( (fType == NSCONSTRAINT_ANY) || (wildcard.fType == NSCONSTRAINT_ANY) ) {
unionWildcard.fType = 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 ( (fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_LIST) ) {
unionWildcard.fType = NSCONSTRAINT_LIST;
unionWildcard.fNamespaceList = union2sets(fNamespaceList, wildcard.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 (fType == NSCONSTRAINT_NOT && wildcard.fType == NSCONSTRAINT_NOT) {
unionWildcard.fType = NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = new String[2];
unionWildcard.fNamespaceList[0] = ABSENT;
unionWildcard.fNamespaceList[1] = 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 ( ((fType == NSCONSTRAINT_NOT) && (wildcard.fType == NSCONSTRAINT_LIST)) ||
((fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_NOT)) ) {
String[] other = null;
String[] list = null;
if (fType == NSCONSTRAINT_NOT) {
other = fNamespaceList;
list = wildcard.fNamespaceList;
}
else {
other = wildcard.fNamespaceList;
list = fNamespaceList;
}
boolean foundAbsent = elementInSet(ABSENT, list);
if (other[0] != ABSENT) {
boolean foundNS = elementInSet(other[0], list);
if (foundNS && foundAbsent) {
unionWildcard.fType = NSCONSTRAINT_ANY;
} else if (foundNS && !foundAbsent) {
unionWildcard.fType = NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = new String[2];
unionWildcard.fNamespaceList[0] = ABSENT;
unionWildcard.fNamespaceList[1] = ABSENT;
} else if (!foundNS && foundAbsent) {
return null;
} else { // !foundNS && !foundAbsent
unionWildcard.fType = NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = other;
}
} else { // other[0] == ABSENT
if (foundAbsent) {
unionWildcard.fType = NSCONSTRAINT_ANY;
} else { // !foundAbsent
unionWildcard.fType = NSCONSTRAINT_NOT;
unionWildcard.fNamespaceList = other;
}
}
}
return unionWildcard;
} // performUnionWith
Schema Component Constraint: Attribute Wildcard Intersection
/**
* Schema Component Constraint: Attribute Wildcard Intersection
*/
public XSWildcardDecl performIntersectionWith(XSWildcardDecl wildcard,
short processContents) {
// if the other wildcard is not expressible, the result is still not expressible
if (wildcard == 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)) {
intersectWildcard.fType = fType;
intersectWildcard.fNamespaceList = fNamespaceList;
}
// 2 If either O1 or O2 is any, then the other must be the value.
else if ( (fType == NSCONSTRAINT_ANY) || (wildcard.fType == NSCONSTRAINT_ANY) ) {
// both cannot be ANY, if we have reached here.
XSWildcardDecl other = this;
if (fType == NSCONSTRAINT_ANY)
other = wildcard;
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 ( ((fType == NSCONSTRAINT_NOT) && (wildcard.fType == NSCONSTRAINT_LIST)) ||
((fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_NOT)) ) {
String[] list = null;
String[] other = null;
if (fType == NSCONSTRAINT_NOT) {
other = fNamespaceList;
list = wildcard.fNamespaceList;
}
else {
other = wildcard.fNamespaceList;
list = 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] != ABSENT)
intersect[newSize++] = list[i];
}
intersectWildcard.fType = 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 ( (fType == NSCONSTRAINT_LIST) && (wildcard.fType == NSCONSTRAINT_LIST) ) {
intersectWildcard.fType = NSCONSTRAINT_LIST;
intersectWildcard.fNamespaceList = intersect2sets(fNamespaceList, wildcard.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 (fType == NSCONSTRAINT_NOT && wildcard.fType == NSCONSTRAINT_NOT) {
if (fNamespaceList[0] != ABSENT && wildcard.fNamespaceList[0] != ABSENT)
return null;
XSWildcardDecl other = this;
if (fNamespaceList[0] == ABSENT)
other = wildcard;
intersectWildcard.fType = other.fType;
intersectWildcard.fNamespaceList = other.fNamespaceList;
}
return intersectWildcard;
} // performIntersectionWith
private boolean areSame(XSWildcardDecl wildcard) {
if (fType == wildcard.fType) {
// ##any, true
if (fType == NSCONSTRAINT_ANY)
return true;
// ##other, only check the negated value
// * when we support not(list), we need to check in the same way
// as for NSCONSTRAINT_LIST.
if (fType == NSCONSTRAINT_NOT)
return fNamespaceList[0] == wildcard.fNamespaceList[0];
// ## list, must have the same length,
// and each item in one list must appear in the other one
// (we are assuming that there are no duplicate items in a list)
if (fNamespaceList.length == wildcard.fNamespaceList.length) {
for (int i=0; i<fNamespaceList.length; i++) {
if (!elementInSet(fNamespaceList[i], wildcard.fNamespaceList))
return false;
}
return true;
}
}
return false;
} // areSame
String[] intersect2sets(String[] one, String[] theOther){
String[] result = new String[Math.min(one.length,theOther.length)];
// simple implemention,
int count = 0;
for (int i=0; i<one.length; i++) {
if (elementInSet(one[i], theOther))
result[count++] = one[i];
}
String[] result2 = new String[count];
System.arraycopy(result, 0, result2, 0, count);
return result2;
}
String[] union2sets(String[] one, String[] theOther){
String[] result1 = new String[one.length];
// simple implemention,
int count = 0;
for (int i=0; i<one.length; i++) {
if (!elementInSet(one[i], theOther))
result1[count++] = one[i];
}
String[] result2 = new String[count+theOther.length];
System.arraycopy(result1, 0, result2, 0, count);
System.arraycopy(theOther, 0, result2, count, theOther.length);
return result2;
}
boolean subset2sets(String[] subSet, String[] superSet){
for (int i=0; i<subSet.length; i++) {
if (!elementInSet(subSet[i], superSet))
return false;
}
return true;
}
boolean elementInSet(String ele, String[] set){
boolean found = false;
for (int i=0; i<set.length && !found; i++) {
if (ele==set[i])
found = true;
}
return found;
}
get the string description of this wildcard
/**
* get the string description of this wildcard
*/
private String fDescription = null;
public String toString() {
if (fDescription == null) {
StringBuffer buffer = new StringBuffer();
buffer.append("WC[");
switch (fType) {
case NSCONSTRAINT_ANY:
buffer.append(SchemaSymbols.ATTVAL_TWOPOUNDANY);
break;
case NSCONSTRAINT_NOT:
buffer.append(SchemaSymbols.ATTVAL_TWOPOUNDOTHER);
buffer.append(":\"");
if (fNamespaceList[0] != null)
buffer.append(fNamespaceList[0]);
buffer.append("\"");
break;
case NSCONSTRAINT_LIST:
if (fNamespaceList.length == 0)
break;
buffer.append("\"");
if (fNamespaceList[0] != null)
buffer.append(fNamespaceList[0]);
buffer.append("\"");
for (int i = 1; i < fNamespaceList.length; i++) {
buffer.append(",\"");
if (fNamespaceList[i] != null)
buffer.append(fNamespaceList[i]);
buffer.append("\"");
}
break;
}
buffer.append(']');
fDescription = buffer.toString();
}
return fDescription;
}
Get the type of the object, i.e ELEMENT_DECLARATION.
/**
* Get the type of the object, i.e ELEMENT_DECLARATION.
*/
public short getType() {
return XSConstants.WILDCARD;
}
The name
of this XSObject
depending on the
XSObject
type.
/**
* The <code>name</code> of this <code>XSObject</code> depending on the
* <code>XSObject</code> type.
*/
public String getName() {
return null;
}
The namespace URI of this node, or null
if it is
unspecified. defines how a namespace URI is attached to schema
components.
/**
* The namespace URI of this node, or <code>null</code> if it is
* unspecified. defines how a namespace URI is attached to schema
* components.
*/
public String getNamespace() {
return null;
}
Namespace constraint: A constraint type: any, not, list.
/**
* Namespace constraint: A constraint type: any, not, list.
*/
public short getConstraintType() {
return fType;
}
Namespace constraint. For constraintType
LIST_NSCONSTRAINT, the list contains allowed namespaces. For
constraintType
NOT_NSCONSTRAINT, the list contains
disallowed namespaces.
/**
* Namespace constraint. For <code>constraintType</code>
* LIST_NSCONSTRAINT, the list contains allowed namespaces. For
* <code>constraintType</code> NOT_NSCONSTRAINT, the list contains
* disallowed namespaces.
*/
public StringList getNsConstraintList() {
return new StringListImpl(fNamespaceList, fNamespaceList == null ? 0 : fNamespaceList.length);
}
{process contents} One of skip, lax or strict. Valid constants values
are: PC_SKIP, PC_LAX, PC_STRICT.
/**
* {process contents} One of skip, lax or strict. Valid constants values
* are: PC_SKIP, PC_LAX, PC_STRICT.
*/
public short getProcessContents() {
return fProcessContents;
}
String valid of {process contents}. One of "skip", "lax" or "strict".
/**
* String valid of {process contents}. One of "skip", "lax" or "strict".
*/
public String getProcessContentsAsString() {
switch (fProcessContents) {
case XSWildcardDecl.PC_SKIP: return "skip";
case XSWildcardDecl.PC_LAX: return "lax";
case XSWildcardDecl.PC_STRICT: return "strict";
default: return "invalid value";
}
}
Optional. Annotation.
/**
* Optional. Annotation.
*/
public XSAnnotation getAnnotation() {
return (fAnnotations != null) ? (XSAnnotation) fAnnotations.item(0) : null;
}
Optional. Annotations.
/**
* Optional. Annotations.
*/
public XSObjectList getAnnotations() {
return (fAnnotations != null) ? fAnnotations : XSObjectListImpl.EMPTY_LIST;
}
See Also: - getNamespaceItem.getNamespaceItem()
/**
* @see org.apache.xerces.xs.XSObject#getNamespaceItem()
*/
public XSNamespaceItem getNamespaceItem() {
return null;
}
} // class XSWildcardDecl