001package org.unix4j.codegen.optset; 002 003import java.util.ArrayList; 004import java.util.Collection; 005import java.util.LinkedHashMap; 006import java.util.List; 007import java.util.Map; 008import java.util.Set; 009import java.util.TreeMap; 010 011import org.unix4j.codegen.command.def.CommandDef; 012import org.unix4j.codegen.command.def.OptionDef; 013import org.unix4j.codegen.def.TypeDef; 014import org.unix4j.codegen.optset.constraint.OptionConstraint; 015import org.unix4j.codegen.optset.def.ActiveSetDef; 016import org.unix4j.codegen.optset.def.OptionGroupDef; 017import org.unix4j.codegen.optset.def.OptionSetDef; 018 019public class OptionSetDefinitionLoader { 020 021 public OptionSetDef create(CommandDef commandDef) { 022 final OptionSetDef def = createOptionSetDef(commandDef); 023 final Collection<OptionConstraint> constraints = Constraints.getOptionConstraints(commandDef); 024 final Map<String, ActiveSetDef> initialActiveSets = new ActiveSetPermutationBuilder(constraints).generateActiveSetsForGroup(commandDef.options); 025// print("", initialActiveSets); 026// if (true) return null; 027 addGroupsDerivedFromActiveSets(def, initialActiveSets); 028 return def; 029 } 030 031 @SuppressWarnings("unused") 032 private void print(String indent, Map<String, ActiveSetDef> activeSets) { 033 for (final Map.Entry<String, ActiveSetDef> e : activeSets.entrySet()) { 034 System.out.println(indent + e.getKey() + ": " + e.getValue().name); 035 print(indent + "\t", e.getValue().next); 036 } 037 } 038 039 private void addGroupsDerivedFromActiveSets(OptionSetDef def, Map<String, ActiveSetDef> initialActiveSets) { 040 //create groups first 041 final Map<Set<String>, OptionGroupDef> optionsToGroup = createGroupsFromActiveSets(def, initialActiveSets); 042 043// //initial level 044 for (final ActiveSetDef initialSet : initialActiveSets.values()) { 045 addGroupsDerivedFromActiveSets(optionsToGroup, initialSet); 046 } 047 048 //recurse all other levels now 049 int level = 1; 050 while (populateLevelActiveSetsToGroups(optionsToGroup, level)) { 051 level++; 052 } 053 054 //set initial group 055 def.initialGroup = optionsToGroup.get(def.command.options.keySet()); 056 057 //now add groups to def 058 def.groups.addAll(optionsToGroup.values()); 059 } 060 061 private Map<Set<String>, OptionGroupDef> createGroupsFromActiveSets(OptionSetDef def, Map<String, ActiveSetDef> initialActiveSets) { 062 final Map<Set<String>, OptionGroupDef> optionsToGroup = new LinkedHashMap<Set<String>, OptionGroupDef>(); 063 //first, simply add the options 064 addGroupsForActiveSets(def.command, optionsToGroup, initialActiveSets.values()); 065 final Set<String> allOptions = def.command.options.keySet(); 066 if (!optionsToGroup.containsKey(allOptions)) { 067 optionsToGroup.put(allOptions, createGroupFor(def.command, allOptions)); 068 } 069 //now, fill the optionToNextGroup values 070 final OptionGroupDef allOptionsGroup = getGroupForOptions(optionsToGroup, allOptions); 071 fillOptionToNextGroup(optionsToGroup, allOptionsGroup, initialActiveSets); 072 //done 073 return optionsToGroup; 074 } 075 076 private void addGroupsForActiveSets(CommandDef commandDef, Map<Set<String>, OptionGroupDef> optionsToGroup, Iterable<ActiveSetDef> activeSets) { 077 for (final ActiveSetDef activeSet : activeSets) { 078 final Set<String> options = activeSet.getAllOptions(); 079 OptionGroupDef grp = optionsToGroup.get(options); 080 if (grp == null) { 081 grp = createGroupFor(commandDef, options); 082 optionsToGroup.put(options, grp); 083 addGroupsForActiveSets(commandDef, optionsToGroup, activeSet.next.values()); 084 } 085 } 086 } 087 088 private void addGroupsDerivedFromActiveSets(final Map<Set<String>, OptionGroupDef> optionsToGroup, ActiveSetDef activeSet) { 089 final OptionGroupDef group = getGroupForActiveSet(optionsToGroup, activeSet); 090 if (group == null) { 091 throw new IllegalArgumentException("group not found for active options " + activeSet.getAllOptions() + ", group options=" + optionsToGroup.keySet()); 092 } 093 getLevelSetFor(group, activeSet.active.size(), true).put(activeSet.name, activeSet); 094 } 095 096 private void fillOptionToNextGroup(Map<Set<String>, OptionGroupDef> optionsToGroup, OptionGroupDef group, Map<String, ActiveSetDef> newActiveToActiveSet) { 097 for (final Map.Entry<String, ActiveSetDef> e : newActiveToActiveSet.entrySet()) { 098 final String newActive = e.getKey(); 099 final ActiveSetDef activeSet = e.getValue(); 100 final OptionGroupDef nextGroup = getGroupForActiveSet(optionsToGroup, activeSet); 101 group.optionToNextGroup.put(newActive, nextGroup); 102 fillOptionToNextGroup(optionsToGroup, nextGroup, activeSet.next); 103 } 104 } 105 106 private OptionGroupDef getGroupForActiveSet(final Map<Set<String>, OptionGroupDef> optionsToGroup, final ActiveSetDef activeSet) { 107 return getGroupForOptions(optionsToGroup, activeSet.getAllOptions()); 108 } 109 private OptionGroupDef getGroupForOptions(final Map<Set<String>, OptionGroupDef> optionsToGroup, final Set<String> options) { 110 final OptionGroupDef grp = optionsToGroup.get(options); 111 if (grp == null) { 112 throw new IllegalArgumentException("no option group for options=" + options + ", groups exist for " + optionsToGroup.keySet()); 113 } 114 return grp; 115 } 116 117 private boolean populateLevelActiveSetsToGroups(final Map<Set<String>, OptionGroupDef> optionsToGroup, int level) { 118 boolean anyAdded = false; 119 for (final OptionGroupDef group : optionsToGroup.values()) { 120 final Map<String, ActiveSetDef> setsForThisLevel = getLevelSetFor(group, level, false); 121 for (final ActiveSetDef activeSet : setsForThisLevel.values()) { 122 for (ActiveSetDef next : activeSet.next.values()) { 123 addGroupsDerivedFromActiveSets(optionsToGroup, next); 124 anyAdded = true; 125 } 126 } 127 } 128 return anyAdded; 129 } 130 131 private Map<String, ActiveSetDef> getLevelSetFor(OptionGroupDef group, int level, boolean create) { 132 final Map<String, ActiveSetDef> lastLevelSet = getLastLevelSet(group); 133 if (lastLevelSet != null && lastLevelSet.get(lastLevelSet.keySet().iterator().next()).active.size() == level) { 134 return lastLevelSet; 135 } 136 if (create) { 137 final Map<String, ActiveSetDef> newLastLevelSet = new LinkedHashMap<String, ActiveSetDef>(); 138 group.levelActiveSets.add(newLastLevelSet); 139 return newLastLevelSet; 140 } 141 return new TreeMap<String, ActiveSetDef>(); 142 } 143 private Map<String, ActiveSetDef> getLastLevelSet(OptionGroupDef group) { 144 final int size = group.levelActiveSets.size(); 145 return size == 0 ? null : group.levelActiveSets.get(size - 1); 146 } 147 148 private OptionSetDef createOptionSetDef(CommandDef commandDef) { 149 final TypeDef optionType = new TypeDef(commandDef.command.simpleName + "Option", commandDef.pkg.name); 150 final OptionSetDef def = new OptionSetDef(commandDef, optionType); 151 return def; 152 } 153 154 private OptionGroupDef createGroupFor(CommandDef commandDef, Set<String> options) { 155 final List<OptionDef> optionDefs = new ArrayList<OptionDef>(options.size()); 156 for (final String opt : options) { 157 optionDefs.add(commandDef.options.get(opt)); 158 } 159 return createGroupFor(commandDef, optionDefs); 160 } 161 private OptionGroupDef createGroupFor(CommandDef commandDef, Collection<OptionDef> options) { 162 final OptionGroupDef grp = new OptionGroupDef(commandDef, options); 163 for (final OptionDef opt : options) { 164 grp.options.put(opt.name, opt); 165 } 166 return grp; 167 } 168 169}