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 = (RuleChainVisitor) language.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 }
|