package net.sourceforge.pmd.eclipse.ui.preferences.br; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Rule; import net.sourceforge.pmd.RulePriority; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.eclipse.ui.preferences.panelmanagers.Configuration; import net.sourceforge.pmd.lang.Language; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.rule.RuleReference; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.StringProperty; import net.sourceforge.pmd.util.CollectionUtil; import net.sourceforge.pmd.util.StringUtil; /** * Represents a set of selected rules in a rule selection widget. Provides useful metrics * and determines common properties (if any). * * @author Brian Remedios */ public class RuleSelection implements RuleCollection { private Object[] ruleItems; public RuleSelection(Rule soleRule) { this(new Object[] {soleRule} ); } public RuleSelection(Object[] theRuleItems) { ruleItems = theRuleItems; } public boolean isEmpty() { return ruleItems == null || ruleItems.length == 0; } public void soleRule(Rule theRule) { ruleItems = new Object[] { theRule }; } /** * Iterate through all the rules ultimately held by the receiver. * Returns true if it went through every one, false if it stopped * along the way. * * @param visitor * @return */ public boolean rulesDo(RuleVisitor visitor) { for (Object item : ruleItems) { if (item instanceof Rule) { if (!visitor.accept((Rule)item)) return false; continue; } if (item instanceof RuleGroup) { if (!((RuleGroup)item).rulesDo(visitor)) return false; } } return true; } public ImplementationType implementationType() { if (ruleItems == null || ruleItems.length == 0) return ImplementationType.Mixed; final Set<ImplementationType> types = new HashSet<ImplementationType>(); RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { types.add( implementationType(rule) ); return types.size() < 2; } }; rulesDo(visitor); return types.size() > 1 ? ImplementationType.Mixed : types.iterator().next(); } /** * Returns whether all the elements match by equality and position * including any possible children they may have. * * @param thisArray Object[] * @param thatArray Object[] * @return boolean */ public static final boolean valuesAreTransitivelyEqual(Object[] thisArray, Object[] thatArray) { if (thisArray == thatArray) return true; if ((thisArray == null) || (thatArray == null)) return false; if (thisArray.length != thatArray.length) return false; for (int i = 0; i < thisArray.length; i++) { if (!CollectionUtil.areEqual(thisArray[i], thatArray[i])) return false; // recurse if req'd } return true; } public boolean haveDefaultValues() { RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { return rule.usesDefaultValues(); } }; return rulesDo(visitor); } public boolean hasOneRule() { if (ruleItems == null || ruleItems.length > 1) return false; return allRules().size() == 1; } public boolean hasMultipleRules() { return ruleItems != null && allRules().size() > 1; } public Rule soleRule() { if (ruleItems == null || ruleItems.length != 1) return null; if (ruleItems[0] instanceof Rule) return (Rule)ruleItems[0]; if (ruleItems[0] instanceof RuleGroup) { return ((RuleGroup)ruleItems[0]).soleRule(); } return null; // should not get here } public Collection<String> ruleGroupNames() { if (ruleItems == null) return Collections.emptyList(); Collection<String> names = new ArrayList<String>(); for (Object item : ruleItems) { if (item instanceof RuleGroup) { names.add( ((RuleGroup)item).label() ); } } return names; } private static void useDefaultValues(Rule rule) { for (Map.Entry<PropertyDescriptor<?>, Object> entry : Configuration.filteredPropertiesOf(rule).entrySet()) { rule.useDefaultValueFor(entry.getKey()); } } public void useDefaultValues() { RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { useDefaultValues(rule); return true; } }; rulesDo(visitor); } public static ImplementationType implementationType(Rule rule) { if (rule instanceof RuleReference) { return ((RuleReference)rule).getRule() instanceof XPathRule ? ImplementationType.XPath : ImplementationType.Java; } else { return rule instanceof XPathRule ? ImplementationType.XPath : ImplementationType.Java; } } public static String commonStringValueFor(Object item, StringProperty desc) { return item instanceof Rule ? ((Rule)item).getProperty(desc) : ((RuleGroup)item).commonStringProperty(desc); } public void setLanguage(final Language language) { if (ruleItems == null) return; RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rule.setLanguage(language); return true; } }; rulesDo(visitor); } public void setMinLanguageVersion(final LanguageVersion version) { if (ruleItems == null) return; RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rule.setMinimumLanguageVersion(version); return true; } }; rulesDo(visitor); } public void setMaxLanguageVersion(final LanguageVersion version) { if (ruleItems == null) return; RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rule.setMaximumLanguageVersion(version); return true; } }; rulesDo(visitor); } public void setPriority(final RulePriority priority) { if (ruleItems == null) return; RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rule.setPriority(priority); return true; } }; rulesDo(visitor); } public int removeAllFrom(RuleSet ruleSet) { List<Rule> rules = allRules(); if (rules.isEmpty()) return 0; Set<Rule> rulesAsSet = new HashSet<Rule>(); rulesAsSet.addAll(rules); Iterator<Rule> currentRuleIter = ruleSet.getRules().iterator(); int removed = 0; while (currentRuleIter.hasNext()) { Rule curRule = currentRuleIter.next(); // could be rule or a ruleReference // if (curRule instanceof RuleReference) { // RuleReference rr = (RuleReference)curRule; // curRule = rr.getRule(); // } if (rulesAsSet.contains(curRule)) { currentRuleIter.remove(); removed++; } } return removed; } public List<Rule> allRules() { if (ruleItems == null || ruleItems.length == 0) { return Collections.emptyList(); } final List<Rule> rules = new ArrayList<Rule>(ruleItems.length); RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rules.add( rule ); return true; } }; rulesDo(visitor); return rules; } public String commonStringValue(StringProperty desc) { if (ruleItems == null || ruleItems.length == 0 || desc == null) return null; String value = commonStringValueFor(ruleItems[0], desc); if (value == null) return null; for (int i=1; i<ruleItems.length; i++) { if (StringUtil.areSemanticEquals(value, commonStringValueFor(ruleItems[i], desc))) return null; } return value; } public void setValue(final StringProperty desc, final String value) { if (ruleItems == null || ruleItems.length == 0) return; RuleVisitor visitor = new RuleVisitor() { public boolean accept(Rule rule) { rule.setProperty(desc, value); return true; } }; rulesDo(visitor); } public String toString() { StringBuilder sb = new StringBuilder(); Collection<String> rgNames = ruleGroupNames(); if (!rgNames.isEmpty()) { sb.append("groups: ").append(rgNames.size()); } List<Rule> rulz = allRules(); if (!rulz.isEmpty()) { sb.append(" rules: ").append(rulz.size()); } return sb.toString(); } }