1
2
3
4 package net.sourceforge.pmd.lang.rule;
5
6 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0;
7 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_1_0_COMPATIBILITY;
8 import static net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery.XPATH_2_0;
9
10 import java.util.List;
11
12 import net.sourceforge.pmd.PropertySource;
13 import net.sourceforge.pmd.RuleContext;
14 import net.sourceforge.pmd.lang.ast.Node;
15 import net.sourceforge.pmd.lang.rule.properties.EnumeratedProperty;
16 import net.sourceforge.pmd.lang.rule.properties.StringProperty;
17 import net.sourceforge.pmd.lang.rule.xpath.JaxenXPathRuleQuery;
18 import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery;
19 import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
20 import net.sourceforge.pmd.util.StringUtil;
21
22
23
24
25
26
27 public class XPathRule extends AbstractRule {
28
29 public static final StringProperty XPATH_DESCRIPTOR = new StringProperty("xpath", "XPath expression", "", 1.0f);
30 public static final EnumeratedProperty<String> VERSION_DESCRIPTOR = new EnumeratedProperty<String>("version",
31 "XPath specification version",
32 new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 },
33 new String[] { XPATH_1_0, XPATH_1_0_COMPATIBILITY, XPATH_2_0 },
34 0, 2.0f);
35
36 private XPathRuleQuery xpathRuleQuery;
37
38 public XPathRule() {
39 definePropertyDescriptor(XPATH_DESCRIPTOR);
40 definePropertyDescriptor(VERSION_DESCRIPTOR);
41 }
42
43 public XPathRule(String xPath) {
44 this();
45 setXPath(xPath);
46 }
47
48 public void setXPath(String xPath) {
49 setProperty(XPathRule.XPATH_DESCRIPTOR, xPath);
50 }
51
52 public void setVersion(String version) {
53 setProperty(XPathRule.VERSION_DESCRIPTOR, version);
54 }
55
56
57
58
59 public void apply(List<? extends Node> nodes, RuleContext ctx) {
60 for (Node node : nodes) {
61 evaluate(node, ctx);
62 }
63 }
64
65
66
67
68
69
70
71
72 public void evaluate(Node node, RuleContext data) {
73 init();
74 List<Node> nodes = xpathRuleQuery.evaluate(node, data);
75 if (nodes != null) {
76 for (Node n : nodes) {
77 addViolation(data, n, n.getImage());
78 }
79 }
80
81 }
82
83 @Override
84 public List<String> getRuleChainVisits() {
85 if (init()) {
86 for (String nodeName : xpathRuleQuery.getRuleChainVisits()) {
87 super.addRuleChainVisit(nodeName);
88 }
89 }
90 return super.getRuleChainVisits();
91 }
92
93 private boolean init() {
94 if (xpathRuleQuery == null) {
95 String xpath = getProperty(XPATH_DESCRIPTOR);
96 String version = (String) getProperty(VERSION_DESCRIPTOR);
97 if (XPATH_1_0.equals(version)) {
98 xpathRuleQuery = new JaxenXPathRuleQuery();
99 } else {
100 xpathRuleQuery = new SaxonXPathRuleQuery();
101 }
102 xpathRuleQuery.setXPath(xpath);
103 xpathRuleQuery.setVersion(version);
104 xpathRuleQuery.setProperties(this.getPropertiesByPropertyDescriptor());
105 return true;
106 }
107 return false;
108 }
109
110
111 public boolean hasXPathExpression() {
112 String xPath = getProperty(XPATH_DESCRIPTOR);
113 return StringUtil.isNotEmpty(xPath);
114 }
115
116
117
118
119 public String dysfunctionReason() {
120 return hasXPathExpression() ? null : "Missing xPath expression";
121 }
122 }