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 }