final List<Predicate> preds = locationStep.getPredicates();
// will become true if optimizable expression is found
boolean canOptimize = false;
// get path of path expression before the predicates
NodePath contextPath = toNodePath(getPrecedingSteps(locationStep));
// process the remaining predicates
for (Predicate pred : preds) {
if (pred.getLength() != 1) {
// can only optimize predicates with one expression
break;
}
Expression innerExpr = pred.getExpression(0);
List<LocationStep> steps = getStepsToOptimize(innerExpr);
if (steps == null || steps.size() == 0) {
// no optimizable steps found
continue;
}
// check if inner steps are on an axis we can optimize
final int axis;
if (innerExpr instanceof InternalFunctionCall) {
InternalFunctionCall fcall = (InternalFunctionCall) innerExpr;
axis = ((Optimizable) fcall.getFunction()).getOptimizeAxis();
} else {
axis = ((Optimizable) innerExpr).getOptimizeAxis();
}
if (!(axis == Constants.CHILD_AXIS || axis == Constants.DESCENDANT_AXIS ||
axis == Constants.DESCENDANT_SELF_AXIS || axis == Constants.ATTRIBUTE_AXIS ||
axis == Constants.DESCENDANT_ATTRIBUTE_AXIS || axis == Constants.SELF_AXIS
)) {
continue;
}
// compute left hand path
NodePath innerPath = toNodePath(steps);
if (innerPath == null) {
continue;
}
NodePath path;
if (contextPath == null) {
path = innerPath;
} else {
path = new NodePath(contextPath);
path.append(innerPath);
}
if (path.length() > 0) {
// replace with call to lookup function
// collect arguments
Lookup func = rewrite(innerExpr, path);
// preserve original comparison: may need it for in-memory lookups
func.setFallback(innerExpr, axis);