Search in sources :

Example 1 with DefaultXPathFactory

use of org.jaxen.expr.DefaultXPathFactory 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;
    }
}
Also used : UnionExpr(org.jaxen.expr.UnionExpr) AllNodeStep(org.jaxen.expr.AllNodeStep) Step(org.jaxen.expr.Step) NameStep(org.jaxen.expr.NameStep) ArrayDeque(java.util.ArrayDeque) Predicate(org.jaxen.expr.Predicate) XPathFactory(org.jaxen.expr.XPathFactory) DefaultXPathFactory(org.jaxen.expr.DefaultXPathFactory) UnionExpr(org.jaxen.expr.UnionExpr) Expr(org.jaxen.expr.Expr) LocationPath(org.jaxen.expr.LocationPath) BaseXPath(org.jaxen.BaseXPath) DefaultXPathFactory(org.jaxen.expr.DefaultXPathFactory) NameStep(org.jaxen.expr.NameStep) AllNodeStep(org.jaxen.expr.AllNodeStep)

Aggregations

ArrayDeque (java.util.ArrayDeque)1 BaseXPath (org.jaxen.BaseXPath)1 AllNodeStep (org.jaxen.expr.AllNodeStep)1 DefaultXPathFactory (org.jaxen.expr.DefaultXPathFactory)1 Expr (org.jaxen.expr.Expr)1 LocationPath (org.jaxen.expr.LocationPath)1 NameStep (org.jaxen.expr.NameStep)1 Predicate (org.jaxen.expr.Predicate)1 Step (org.jaxen.expr.Step)1 UnionExpr (org.jaxen.expr.UnionExpr)1 XPathFactory (org.jaxen.expr.XPathFactory)1