RuleChain.java
01 package net.sourceforge.pmd;
02 
03 import java.util.HashMap;
04 import java.util.List;
05 import java.util.Map;
06 
07 import net.sourceforge.pmd.lang.Language;
08 import net.sourceforge.pmd.lang.ast.Node;
09 import net.sourceforge.pmd.lang.rule.RuleChainVisitor;
10 
11 /**
12  * The RuleChain is a means by which Rules can participate in a uniform
13  * visitation of the AST, and not need perform their own independent visitation.
14  * The RuleChain exists as a means to improve the speed of PMD when there are
15  * many Rules.
16  */
17 public class RuleChain {
18     // Mapping from Language to RuleChainVisitor
19     private final Map<Language, RuleChainVisitor> languageToRuleChainVisitor = new HashMap<Language, RuleChainVisitor>();
20 
21     /**
22      * Add all Rules from the given RuleSet which want to participate in the
23      * RuleChain.
24      
25      @param ruleSet
26      *            The RuleSet to add Rules from.
27      */
28     public void add(RuleSet ruleSet) {
29   for (Rule r : ruleSet.getRules()) {
30             add(ruleSet, r);
31   }
32     }
33 
34     /**
35      * Add the given Rule if it wants to participate in the RuleChain.
36      
37      @param ruleSet
38      *            The RuleSet to which the rule belongs.
39      @param rule
40      *            The Rule to add.
41      */
42     private void add(RuleSet ruleSet, Rule rule) {
43   RuleChainVisitor visitor = getRuleChainVisitor(rule.getLanguage());
44   if (visitor != null) {
45             visitor.add(ruleSet, rule);
46   }
47     }
48 
49     /**
50      * Apply the RuleChain to the given Nodes using the given
51      * RuleContext, for those rules using the given Language.
52      
53      @param nodes
54      *            The Nodes.
55      @param ctx
56      *            The RuleContext.
57      @param language
58      *            The Language.
59      */
60     public void apply(List<Node> nodes, RuleContext ctx, Language language) {
61   RuleChainVisitor visitor = getRuleChainVisitor(language);
62   if (visitor != null) {
63       visitor.visitAll(nodes, ctx);
64   }
65     }
66 
67     // Get the RuleChainVisitor for the appropriate Language.
68     private RuleChainVisitor getRuleChainVisitor(Language language) {
69   RuleChainVisitor visitor = languageToRuleChainVisitor.get(language);
70   if (visitor == null) {
71       if (language.getRuleChainVisitorClass() != null) {
72     try {
73         visitor = (RuleChainVisitorlanguage.getRuleChainVisitorClass().newInstance();
74     catch (InstantiationException e) {
75         throw new IllegalStateException("Failure to created RuleChainVisitor: "
76           + language.getRuleChainVisitorClass(), e);
77     catch (IllegalAccessException e) {
78         throw new IllegalStateException("Failure to created RuleChainVisitor: "
79           + language.getRuleChainVisitorClass(), e);
80     }
81     languageToRuleChainVisitor.put(language, visitor);
82       else {
83     throw new IllegalArgumentException("Language does not have a RuleChainVisitor: " + language);
84       }
85   }
86   return visitor;
87     }
88 }