1 package net.sourceforge.pmd;
2
3 import java.io.File;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Set;
10
11 import net.sourceforge.pmd.ast.CompilationUnit;
12
13 /**
14 * Grouping of Rules per Language in a RuleSet.
15 *
16 * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
17 */
18 public class RuleSets {
19 /**
20 * Map of RuleLanguage on RuleSet.
21 */
22 private Collection<RuleSet> ruleSets = new ArrayList<RuleSet>();
23
24 /**
25 * RuleChain for efficient AST visitation.
26 */
27 private RuleChain ruleChain = new RuleChain();
28
29 /**
30 * Public constructor.
31 */
32 public RuleSets() {
33 }
34
35 /**
36 * Public constructor. Add the given rule set.
37 *
38 * @param ruleSet the RuleSet
39 */
40 public RuleSets(RuleSet ruleSet) {
41 this();
42 addRuleSet(ruleSet);
43 }
44
45 /**
46 * Add a ruleset for a language. Only one ruleset can be added for a specific
47 * language. If ruleSet.getLanguage() is null, it is assumed to be a RuleSet of java
48 * rules.
49 *
50 * @param ruleSet the RuleSet
51 */
52 public void addRuleSet(RuleSet ruleSet) {
53 ruleSets.add(ruleSet);
54 ruleChain.add(ruleSet);
55 }
56
57 /**
58 * Get all the RuleSets.
59 *
60 * @return RuleSet[]
61 */
62 public RuleSet[] getAllRuleSets() {
63 return ruleSets.toArray(new RuleSet[ruleSets.size()]);
64 }
65
66 public Iterator<RuleSet> getRuleSetsIterator() {
67 return ruleSets.iterator();
68 }
69
70 /**
71 * Return all rules from all rulesets.
72 *
73 * @return Set
74 */
75 public Set<Rule> getAllRules() {
76 HashSet<Rule> result = new HashSet<Rule>();
77 for (RuleSet r: ruleSets) {
78 result.addAll(r.getRules());
79 }
80 return result;
81 }
82
83 /**
84 * Check if a given source file should be checked by rules in this RuleSets.
85 *
86 * @param file the source file to check
87 * @return <code>true</code> if the file should be checked, <code>false</code> otherwise
88 */
89 public boolean applies(File file) {
90 for (Iterator i = ruleSets.iterator(); i.hasNext();) {
91 if (((RuleSet)i.next()).applies(file)) {
92 return true;
93 }
94 }
95 return false;
96 }
97
98 /**
99 * Check if a source with given language should be checked by rules for a given
100 * language. This is the case if both languages are equal, or if the source is in
101 * java, and the language of the rules is unknown (for backward-compatibility
102 * reasons).
103 *
104 * @param languageOfSource language of a source; can not be null
105 * @param languageOfRule language of a ruleset; can be null
106 * @return boolean true if the rule applies, else false
107 */
108 public boolean applies(Language languageOfSource, Language languageOfRule) {
109 return (languageOfSource.equals(languageOfRule) || (languageOfSource
110 .equals(Language.JAVA) && (null == languageOfRule)));
111 }
112
113 /**
114 * Notify all rules of the start of processing.
115 */
116 public void start(RuleContext ctx) {
117 for (RuleSet ruleSet: ruleSets) {
118 ruleSet.start(ctx);
119 }
120 }
121
122 /**
123 * Apply all applicable rules to the compilation units.
124 * Applicable means the language of the rules must match the language
125 * of the source (@see applies).
126 *
127 * @param acuList the List of compilation units; the type these must have,
128 * depends on the source language
129 * @param ctx the RuleContext
130 * @param language the Language of the source
131 */
132 public void apply(List<CompilationUnit> acuList, RuleContext ctx, Language language) {
133 ruleChain.apply(acuList, ctx, language);
134 for (RuleSet ruleSet: ruleSets) {
135 if (applies(language, ruleSet.getLanguage())) {
136
137 if (ruleSet.applies(ctx.getSourceCodeFile())) {
138 ruleSet.apply(acuList, ctx);
139 }
140 }
141 }
142 }
143
144 /**
145 * Notify all rules of the end of processing.
146 */
147 public void end(RuleContext ctx) {
148 for (RuleSet ruleSet: ruleSets) {
149 ruleSet.end(ctx);
150 }
151 }
152
153 /**
154 * Check if the rules that apply to a source of the given language
155 * use DFA.
156 *
157 * @param language the language of a source
158 * @return true if any rule in the RuleSet needs the DFA layer
159 */
160 public boolean usesDFA(Language language) {
161 for (RuleSet ruleSet: ruleSets) {
162 if (applies(language, ruleSet.getLanguage()) && ruleSet.usesDFA()) {
163 return true;
164 }
165 }
166 return false;
167 }
168
169 /**
170 * Returns the Rule with the given name
171 *
172 * @param ruleName the name of the rule to find
173 * @return the rule or null if not found
174 */
175 public Rule getRuleByName(String ruleName) {
176 Rule rule = null;
177 for (Iterator<RuleSet> i = ruleSets.iterator(); i.hasNext() && (rule == null);) {
178 RuleSet ruleSet = i.next();
179 rule = ruleSet.getRuleByName(ruleName);
180 }
181 return rule;
182 }
183
184 public boolean usesTypeResolution(Language language) {
185 for (RuleSet ruleSet: ruleSets) {
186 if (applies(language, ruleSet.getLanguage()) && ruleSet.usesTypeResolution()) {
187 return true;
188 }
189 }
190 return false;
191 }
192 }