View Javadoc

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