001: package net.sourceforge.pmd;
002:
003: import java.io.File;
004: import java.util.ArrayList;
005: import java.util.Collection;
006: import java.util.HashSet;
007: import java.util.Iterator;
008: import java.util.List;
009: import java.util.Set;
010:
011: import net.sourceforge.pmd.ast.CompilationUnit;
012:
013: /**
014: * Grouping of Rules per Language in a RuleSet.
015: *
016: * @author pieter_van_raemdonck - Application Engineers NV/SA - www.ae.be
017: */
018: public class RuleSets {
019: /**
020: * Map of RuleLanguage on RuleSet.
021: */
022: private Collection<RuleSet> ruleSets = new ArrayList<RuleSet>();
023:
024: /**
025: * RuleChain for efficient AST visitation.
026: */
027: private RuleChain ruleChain = new RuleChain();
028:
029: /**
030: * Public constructor.
031: */
032: public RuleSets() {
033: }
034:
035: /**
036: * Public constructor. Add the given rule set.
037: *
038: * @param ruleSet the RuleSet
039: */
040: public RuleSets(RuleSet ruleSet) {
041: this ();
042: addRuleSet(ruleSet);
043: }
044:
045: /**
046: * Add a ruleset for a language. Only one ruleset can be added for a specific
047: * language. If ruleSet.getLanguage() is null, it is assumed to be a RuleSet of java
048: * rules.
049: *
050: * @param ruleSet the RuleSet
051: */
052: public void addRuleSet(RuleSet ruleSet) {
053: ruleSets.add(ruleSet);
054: ruleChain.add(ruleSet);
055: }
056:
057: /**
058: * Get all the RuleSets.
059: *
060: * @return RuleSet[]
061: */
062: public RuleSet[] getAllRuleSets() {
063: return ruleSets.toArray(new RuleSet[ruleSets.size()]);
064: }
065:
066: public Iterator<RuleSet> getRuleSetsIterator() {
067: return ruleSets.iterator();
068: }
069:
070: /**
071: * Return all rules from all rulesets.
072: *
073: * @return Set
074: */
075: public Set<Rule> getAllRules() {
076: HashSet<Rule> result = new HashSet<Rule>();
077: for (RuleSet r : ruleSets) {
078: result.addAll(r.getRules());
079: }
080: return result;
081: }
082:
083: /**
084: * Check if a given source file should be checked by rules in this RuleSets.
085: *
086: * @param file the source file to check
087: * @return <code>true</code> if the file should be checked, <code>false</code> otherwise
088: */
089: public boolean applies(File file) {
090: for (Iterator i = ruleSets.iterator(); i.hasNext();) {
091: if (((RuleSet) i.next()).applies(file)) {
092: return true;
093: }
094: }
095: return false;
096: }
097:
098: /**
099: * 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,
109: Language languageOfRule) {
110: return (languageOfSource.equals(languageOfRule) || (languageOfSource
111: .equals(Language.JAVA) && (null == languageOfRule)));
112: }
113:
114: /**
115: * Notify all rules of the start of processing.
116: */
117: public void start(RuleContext ctx) {
118: for (RuleSet ruleSet : ruleSets) {
119: ruleSet.start(ctx);
120: }
121: }
122:
123: /**
124: * Apply all applicable rules to the compilation units.
125: * Applicable means the language of the rules must match the language
126: * of the source (@see applies).
127: *
128: * @param acuList the List of compilation units; the type these must have,
129: * depends on the source language
130: * @param ctx the RuleContext
131: * @param language the Language of the source
132: */
133: public void apply(List<CompilationUnit> acuList, RuleContext ctx,
134: Language language) {
135: ruleChain.apply(acuList, ctx, language);
136: for (RuleSet ruleSet : ruleSets) {
137: if (applies(language, ruleSet.getLanguage())) {
138: ruleSet.apply(acuList, ctx);
139: }
140: }
141: }
142:
143: /**
144: * Notify all rules of the end of processing.
145: */
146: public void end(RuleContext ctx) {
147: for (RuleSet ruleSet : ruleSets) {
148: ruleSet.end(ctx);
149: }
150: }
151:
152: /**
153: * Check if the rules that apply to a source of the given language
154: * use DFA.
155: *
156: * @param language the language of a source
157: * @return true if any rule in the RuleSet needs the DFA layer
158: */
159: public boolean usesDFA(Language language) {
160: for (RuleSet ruleSet : ruleSets) {
161: if (applies(language, ruleSet.getLanguage())
162: && 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()
178: && (rule == null);) {
179: RuleSet ruleSet = i.next();
180: rule = ruleSet.getRuleByName(ruleName);
181: }
182: return rule;
183: }
184:
185: public boolean usesTypeResolution(Language language) {
186: for (RuleSet ruleSet : ruleSets) {
187: if (applies(language, ruleSet.getLanguage())
188: && ruleSet.usesTypeResolution()) {
189: return true;
190: }
191: }
192: return false;
193: }
194: }
|