01 /**
02 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
03 */
04 package net.sourceforge.pmd.lang.rule;
05
06 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0;
07 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0_COMPATIBILITY;
08 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_2_0;
09
10 import java.util.List;
11
12 import net.sourceforge.pmd.RuleContext;
13 import net.sourceforge.pmd.lang.ast.Node;
14 import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty;
15 import net.sourceforge.pmd.lang.rule.properties.StringProperty;
16 import net.sourceforge.pmd.lang.rule.xpath.JaxenXPathRuleQuery;
17 import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery;
18 import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
19
20 /**
21 * Rule that tries to match an XPath expression against a DOM view of an AST.
22 * <p/>
23 * This rule needs a property "xpath".
24 */
25 public class XPathRule extends AbstractRule {
26
27 public static final StringProperty XPATH_DESCRIPTOR = new StringProperty("xpath", "XPath expression", "", 1.0f);
28 public static final EnumeratedProperty<String> VERSION_DESCRIPTOR = new EnumeratedProperty<String>("version",
29 "XPath specification version", new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 },
30 new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 }, 0, 2.0f);
31
32 private XPathRuleQuery xpathRuleQuery;
33
34 public XPathRule() {
35 definePropertyDescriptor(XPATH_DESCRIPTOR);
36 definePropertyDescriptor(VERSION_DESCRIPTOR);
37 }
38
39 /**
40 * Apply the rule to all nodes.
41 */
42 public void apply(List<? extends Node> nodes, RuleContext ctx) {
43 for (Node node : nodes) {
44 evaluate(node, ctx);
45 }
46 }
47
48 /**
49 * Evaluate the XPath query with the AST node.
50 * All matches are reported as violations.
51 *
52 * @param node The Node that to be checked.
53 * @param data The RuleContext.
54 */
55 public void evaluate(Node node, RuleContext data) {
56 init();
57 List<Node> nodes = xpathRuleQuery.evaluate(node, data);
58 if (nodes != null) {
59 for (Node n : nodes) {
60 addViolation(data, n, n.getImage());
61 }
62 }
63
64 }
65
66 @Override
67 public List<String> getRuleChainVisits() {
68 if (init()) {
69 for (String nodeName : xpathRuleQuery.getRuleChainVisits()) {
70 super.addRuleChainVisit(nodeName);
71 }
72 }
73 return super.getRuleChainVisits();
74 }
75
76 private boolean init() {
77 if (xpathRuleQuery == null) {
78 String xpath = getProperty(XPATH_DESCRIPTOR);
79 String version = (String) getProperty(VERSION_DESCRIPTOR);
80 if (XPATH_1_0.equals(version)) {
81 xpathRuleQuery = new JaxenXPathRuleQuery();
82 } else {
83 xpathRuleQuery = new SaxonXPathRuleQuery();
84 }
85 xpathRuleQuery.setXPath(xpath);
86 xpathRuleQuery.setVersion(version);
87 xpathRuleQuery.setProperties(this.getPropertiesByPropertyDescriptor());
88 return true;
89 }
90 return false;
91 }
92 }
|