use of org.jaxen.expr.UnionExpr in project pmd by pmd.
the class JaxenXPathRuleQuery method initializeXPathExpression.
private void initializeXPathExpression(final Navigator navigator) throws JaxenException {
/*
Attempt to use the RuleChain with this XPath query.
To do so, the queries should generally look like //TypeA or //TypeA | //TypeB. We will look at the parsed XPath
AST using the Jaxen APIs to make this determination.
If the query is not exactly what we are looking for, do not use the
RuleChain.
*/
nodeNameToXPaths = new HashMap<>();
final BaseXPath originalXPath = createXPath(xpath, navigator);
addQueryToNode(originalXPath, AST_ROOT);
boolean useRuleChain = true;
final Deque<Expr> pending = new ArrayDeque<>();
pending.push(originalXPath.getRootExpr());
while (!pending.isEmpty()) {
final Expr node = pending.pop();
// Need to prove we can handle this part of the query
boolean valid = false;
// Must be a LocationPath... that is something like //Type
if (node instanceof LocationPath) {
final LocationPath locationPath = (LocationPath) node;
if (locationPath.isAbsolute()) {
// Should be at least two steps
@SuppressWarnings("unchecked") final List<Step> steps = locationPath.getSteps();
if (steps.size() >= 2) {
final Step step1 = steps.get(0);
final Step step2 = steps.get(1);
// descendant or self axis
if (step1 instanceof AllNodeStep && step1.getAxis() == Axis.DESCENDANT_OR_SELF) {
// axis.
if (step2 instanceof NameStep && step2.getAxis() == Axis.CHILD) {
// Construct a new expression that is
// appropriate for RuleChain use
final XPathFactory xpathFactory = new DefaultXPathFactory();
// Instead of an absolute location path, we'll
// be using a relative path
final LocationPath relativeLocationPath = xpathFactory.createRelativeLocationPath();
// The first step will be along the self axis
final Step allNodeStep = xpathFactory.createAllNodeStep(Axis.SELF);
// Retain all predicates from the original name
// step
@SuppressWarnings("unchecked") final List<Predicate> predicates = step2.getPredicates();
for (Predicate predicate : predicates) {
allNodeStep.addPredicate(predicate);
}
relativeLocationPath.addStep(allNodeStep);
// location path
for (int i = 2; i < steps.size(); i++) {
relativeLocationPath.addStep(steps.get(i));
}
final BaseXPath xpath = createXPath(relativeLocationPath.getText(), navigator);
addQueryToNode(xpath, ((NameStep) step2).getLocalName());
valid = true;
}
}
}
}
} else if (node instanceof UnionExpr) {
// Or a UnionExpr, that is
// something like //TypeA |
// //TypeB
UnionExpr unionExpr = (UnionExpr) node;
pending.push(unionExpr.getLHS());
pending.push(unionExpr.getRHS());
valid = true;
}
if (!valid) {
useRuleChain = false;
break;
}
}
if (useRuleChain) {
// Use the RuleChain for all the nodes extracted from the xpath
// queries
super.ruleChainVisits.addAll(nodeNameToXPaths.keySet());
} else {
// Use original XPath if we cannot use the RuleChain
nodeNameToXPaths.clear();
addQueryToNode(originalXPath, AST_ROOT);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Unable to use RuleChain for XPath: " + xpath);
}
}
if (navigator == null) {
this.initializationStatus = InitializationStatus.PARTIAL;
// Clear the node data, because we did not have a Navigator
nodeNameToXPaths = null;
} else {
this.initializationStatus = InitializationStatus.FULL;
}
}
Aggregations