in xmlschema-walker/src/main/java/org/apache/ws/commons/schema/docpath/XmlSchemaPathFinder.java [931:1097]
private static <U, V> Fulfillment isPositionFulfilled(XmlSchemaPathNode<U, V> currentPath,
List<Integer> possiblePaths) {
boolean completelyFulfilled = true;
boolean partiallyFulfilled = true;
final XmlSchemaStateMachineNode state = currentPath.getStateMachineNode();
if (currentPath.getDocumentNode() == null) {
// This is the root node. It is not fulfilled.
partiallyFulfilled = false;
} else if (currentPath.getDocIteration() >= state.getMinOccurs()) {
partiallyFulfilled = true;
} else {
partiallyFulfilled = false;
}
if (currentPath.getDocumentNode() == null) {
completelyFulfilled = false;
} else if (currentPath.getDocIteration() == state.getMaxOccurs()) {
completelyFulfilled = true;
} else if (currentPath.getDocIteration() > state.getMaxOccurs()) {
throw new IllegalStateException("Current path's document iteration of "
+ currentPath.getDocIteration()
+ " is greater than the maximum number of occurrences ("
+ state.getMaxOccurs() + ").");
} else {
completelyFulfilled = false;
}
final List<XmlSchemaStateMachineNode> nextStates = state.getPossibleNextStates();
Map<Integer, XmlSchemaDocumentNode<U>> children = null;
if (currentPath.getDocumentNode() != null) {
children = currentPath.getDocumentNode().getChildren();
}
switch (state.getNodeType()) {
case ELEMENT:
case ANY:
// We only needed to perform the occurrence check.
break;
case CHOICE:
case SUBSTITUTION_GROUP: {
/*
* If any child meets the minimum number, we are partially
* fulfilled. If all elements meet the maximum, we are completely
* fulfilled.
*/
boolean groupPartiallyFulfilled = false;
boolean groupCompletelyFulfilled = false;
for (int stateIndex = 0; stateIndex < nextStates.size(); ++stateIndex) {
XmlSchemaStateMachineNode nextState = nextStates.get(stateIndex);
if ((children != null) && children.containsKey(stateIndex)) {
final XmlSchemaDocumentNode<U> child = children.get(stateIndex);
final int iteration = child.getIteration();
if (iteration >= nextState.getMinOccurs()) {
groupPartiallyFulfilled = true;
if (possiblePaths != null) {
possiblePaths.clear();
if (iteration < nextState.getMaxOccurs()) {
possiblePaths.add(stateIndex);
} else {
groupCompletelyFulfilled = true;
}
}
break;
} else if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
} else {
if (nextState.getMinOccurs() == 0) {
groupPartiallyFulfilled = true;
}
if (nextState.getMaxOccurs() == 0) {
groupCompletelyFulfilled = true;
} else if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
}
}
partiallyFulfilled &= groupPartiallyFulfilled;
completelyFulfilled &= groupCompletelyFulfilled;
break;
}
case ALL: {
// If all children meet the minimum number, we succeeded.
for (int stateIndex = 0; stateIndex < nextStates.size(); ++stateIndex) {
final XmlSchemaStateMachineNode nextState = nextStates.get(stateIndex);
if ((children != null) && children.containsKey(stateIndex)) {
final XmlSchemaDocumentNode<U> child = children.get(stateIndex);
final int iteration = child.getIteration();
if (iteration < nextState.getMinOccurs()) {
partiallyFulfilled = false;
}
if (iteration < nextState.getMaxOccurs()) {
completelyFulfilled = false;
if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
}
} else {
if (nextState.getMinOccurs() > 0) {
partiallyFulfilled = false;
}
if (nextState.getMaxOccurs() > 0) {
completelyFulfilled = false;
if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
}
}
}
break;
}
case SEQUENCE: {
// If the sequence is complete, we succeeded.
int stateIndex = currentPath.getDocSequencePosition();
if (stateIndex < 0) {
stateIndex = 0;
}
for (; stateIndex < nextStates.size(); ++stateIndex) {
final XmlSchemaStateMachineNode nextState = nextStates.get(stateIndex);
if ((children != null) && children.containsKey(stateIndex)) {
final XmlSchemaDocumentNode<U> child = children.get(stateIndex);
if (child.getIteration() < nextState.getMinOccurs()) {
partiallyFulfilled = false;
}
if (child.getIteration() < nextState.getMaxOccurs()) {
completelyFulfilled = false;
if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
}
} else {
if (nextState.getMinOccurs() > 0) {
partiallyFulfilled = false;
}
if (nextState.getMaxOccurs() > 0) {
completelyFulfilled = false;
if (possiblePaths != null) {
possiblePaths.add(stateIndex);
}
}
}
}
break;
}
default:
throw new IllegalStateException("Current position has a node of unrecognized type \""
+ currentPath.getStateMachineNode().getNodeType() + '\"');
}
Fulfillment fulfillment = Fulfillment.NOT;
if (completelyFulfilled) {
fulfillment = Fulfillment.COMPLETE;
} else if (partiallyFulfilled) {
fulfillment = Fulfillment.PARTIAL;
}
return fulfillment;
}