View Javadoc

    1   package net.sourceforge.pmd;
    2
    3   import java.util.HashMap;
    4   import java.util.List;
    5   import java.util.Map;
    6
    7   import net.sourceforge.pmd.lang.Language;
    8   import net.sourceforge.pmd.lang.ast.Node;
    9   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  }