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}