1 package net.sourceforge.pmd;
2
3 import java.text.MessageFormat;
4 import java.util.Properties;
5
6 import net.sourceforge.pmd.ast.Node;
7 import net.sourceforge.pmd.ast.SimpleNode;
8
9 /***
10 * Basic abstract implementation of all parser-independent methods of the
11 * Rule interface.
12 *
13 * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
14 */
15 public abstract class CommonAbstractRule implements Rule {
16
17 protected String name = getClass().getName();
18 protected Properties properties = new Properties();
19 protected String message;
20 protected String description;
21 protected String example;
22 protected String ruleSetName;
23 protected boolean include;
24 protected boolean usesDFA;
25 protected boolean usesTypeResolution;
26 protected int priority = LOWEST_PRIORITY;
27 protected String externalInfoUrl;
28
29 public String getRuleSetName() {
30 return ruleSetName;
31 }
32
33 public void setRuleSetName(String ruleSetName) {
34 this.ruleSetName = ruleSetName;
35 }
36
37 public String getDescription() {
38 return description;
39 }
40
41 public void setDescription(String description) {
42 this.description = description;
43 }
44
45 public String getExample() {
46 return example;
47 }
48
49 public void setExample(String example) {
50 this.example = example;
51 }
52
53 public boolean hasProperty(String name) {
54 return properties.containsKey(name);
55 }
56
57 public void addProperty(String name, String value) {
58 properties.setProperty(name, value);
59 }
60
61 public void addProperties(Properties properties) {
62 this.properties.putAll(properties);
63 }
64
65 public double getDoubleProperty(String name) {
66 return Double.parseDouble(properties.getProperty(name));
67 }
68
69 public int getIntProperty(String name) {
70 return Integer.parseInt(properties.getProperty(name));
71 }
72
73 public boolean getBooleanProperty(String name) {
74 return Boolean.valueOf(properties.getProperty(name)).booleanValue();
75 }
76
77 public String getStringProperty(String name) {
78 return properties.getProperty(name);
79 }
80
81 public String getName() {
82 return name;
83 }
84
85 public void setName(String name) {
86 this.name = name;
87 }
88
89 public String getMessage() {
90 return message;
91 }
92
93 public void setMessage(String message) {
94 this.message = message;
95 }
96
97 public String getExternalInfoUrl() {
98 return externalInfoUrl;
99 }
100
101 public void setExternalInfoUrl(String url) {
102 this.externalInfoUrl = url;
103 }
104
105 /***
106 * Test if rules are equals. Rules are equals if
107 * 1. they have the same implementation class
108 * 2. they have the same name
109 * 3. they have the same priority
110 * 4. they share the same properties/values
111 */
112 public boolean equals(Object o) {
113 if (o == null) {
114 return false;
115 }
116
117 if (this == o) {
118 return true;
119 }
120
121 Rule rule = null;
122 boolean equality = this.getClass().getName().equals(o.getClass().getName());
123
124 if (equality) {
125 rule = (Rule) o;
126 equality = this.getName().equals(rule.getName())
127 && this.getPriority() == rule.getPriority()
128 && this.getProperties().equals(rule.getProperties());
129 }
130
131 return equality;
132 }
133
134 /***
135 * Return a hash code to conform to equality. Try with a string.
136 */
137 public int hashCode() {
138 String s = this.getClass().getName() + this.getName() + this.getPriority() + this.getProperties().toString();
139 return s.hashCode();
140 }
141
142
143 public Properties getProperties() {
144 return properties;
145 }
146
147 public boolean include() {
148 return include;
149 }
150
151 public void setInclude(boolean include) {
152 this.include = include;
153 }
154
155 public int getPriority() {
156 return priority;
157 }
158
159 public String getPriorityName() {
160 return PRIORITIES[getPriority() - 1];
161 }
162
163 public void setPriority(int priority) {
164 this.priority = priority;
165 }
166
167 public void setUsesDFA() {
168 this.usesDFA = true;
169 }
170
171 public boolean usesDFA() {
172 return this.usesDFA;
173 }
174
175 public void setUsesTypeResolution() {
176 this.usesTypeResolution= true;
177 }
178
179 public boolean usesTypeResolution() {
180 return this.usesTypeResolution;
181 }
182
183
184 /***
185 * Adds a violation to the report.
186 *
187 * @param ctx the RuleContext
188 * @param node the node that produces the violation
189 */
190 protected final void addViolation(Object data, SimpleNode node) {
191 RuleContext ctx = (RuleContext) data;
192 ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node));
193 }
194
195 /***
196 * Adds a violation to the report.
197 *
198 * @param ctx the RuleContext
199 * @param node the node that produces the violation
200 * @param msg specific message to put in the report
201 */
202 protected final void addViolationWithMessage(Object data, SimpleNode node, String msg) {
203 RuleContext ctx = (RuleContext) data;
204 ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, msg));
205 }
206
207 /***
208 * Adds a violation to the report.
209 *
210 * @param ctx the RuleContext
211 * @param node the node that produces the violation
212 * @param embed a variable to embed in the rule violation message
213 */
214 protected final void addViolation(Object data, SimpleNode node, String embed) {
215 RuleContext ctx = (RuleContext) data;
216 ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, node, MessageFormat.format(getMessage(), new Object[]{embed})));
217 }
218
219 /***
220 * Adds a violation to the report.
221 *
222 * @param ctx the RuleContext
223 * @param node the node that produces the violation, may be null, in which case all line and column info will be set to zero
224 * @param args objects to embed in the rule violation message
225 */
226 protected final void addViolation(Object data, Node node, Object[] args) {
227 RuleContext ctx = (RuleContext) data;
228 ctx.getReport().addRuleViolation(new RuleViolation(this, ctx, (SimpleNode) node, MessageFormat.format(getMessage(), args)));
229 }
230
231 public PropertyDescriptor propertyDescriptorFor(String name) {
232 return null;
233 }
234 }