001package org.unix4j.codegen.optset; 002 003import java.util.Collection; 004import java.util.HashMap; 005import java.util.LinkedHashMap; 006import java.util.Map; 007import java.util.Set; 008import java.util.SortedMap; 009import java.util.SortedSet; 010import java.util.TreeMap; 011import java.util.TreeSet; 012 013import org.unix4j.codegen.command.def.OptionDef; 014import org.unix4j.codegen.optset.constraint.OptionConstraint; 015import org.unix4j.codegen.optset.def.ActiveSetDef; 016 017/** 018 * Generates all "active option" permutations ignoring possible constraints on 019 * the options. For {@code n} options, this class generates all possible 020 * <tt>2<sup>n</sup>-1</tt> active permutations (the set with no active options 021 * is omitted). 022 */ 023public class ActiveSetPermutationBuilder { 024 025 private final Collection<OptionConstraint> constraints; 026 027 public ActiveSetPermutationBuilder(Collection<OptionConstraint> constraints) { 028 this.constraints = constraints; 029 } 030 031 public Map<String, ActiveSetDef> generateActiveSetsForGroup(Map<String, OptionDef> options) { 032 return generateNextActiveSets(options, new HashMap<String, ActiveSetDef>(), new TreeSet<String>()); 033 } 034 private Map<String, ActiveSetDef> generateNextActiveSets(Map<String, OptionDef> options, Map<String, ActiveSetDef> activeSetsByName, SortedSet<String> active) { 035 final Map<String, ActiveSetDef> activeSets = new LinkedHashMap<String, ActiveSetDef>(); 036 for (final String opt : options.keySet()) { 037 if (!active.contains(opt)) { 038 final SortedMap<String, OptionDef> newActive = new TreeMap<String, OptionDef>(); 039 for (final String act : active) { 040 newActive.put(act, options.get(act)); 041 } 042 newActive.put(opt, options.get(opt)); 043 if (isValidActiveSet(newActive.keySet())) { 044 final ActiveSetDef activeSet = new ActiveSetDef(newActive); 045 if (activeSetsByName.containsKey(activeSet.name)) { 046 activeSets.put(opt, activeSetsByName.get(activeSet.name)); 047 } else { 048 activeSetsByName.put(activeSet.name, activeSet); 049 activeSet.next.putAll(generateNextActiveSets(options, activeSetsByName, activeSet.active)); 050 activeSets.put(opt, activeSet); 051 } 052 } 053 } 054 } 055 return activeSets; 056 } 057 058 private boolean isValidActiveSet(Set<String> activeSet) { 059 for (final OptionConstraint constraint : constraints) { 060 if (!constraint.isValidActiveSet(activeSet)) { 061 return false; 062 } 063 } 064 return true; 065 } 066}