001package org.maltparser.core.options;
002
003import java.util.Collections;
004import java.util.SortedMap;
005import java.util.SortedSet;
006import java.util.TreeMap;
007import java.util.TreeSet;
008
009import org.maltparser.core.options.option.Option;
010
011/**
012 * An option container stores the option values for one instance usage. For example, a
013 * single malt configuration there will only be one option container, but for an ensemble parser there
014 * could be several option containers. 
015 * 
016 * There are four types internal option container:
017 * <ul>
018 * <li>SAVEDOPTION, contains option values load from the saved option file.
019 * <li>DEPENDENCIES_RESOLVED, contains option values that overload option values in COMMANDLINE and OPTIONFILE
020 * due to dependencies with other options.
021 * <li>COMMANDLINE, contains option values that are read from the command-line prompt.
022 * <li>OPTIONFILE, contains option values that are read from the option file.
023 * </ul>
024 * <p>These internal option containers have following priority: SAVEDOPTION, DEPENDENCIES_RESOLVED, COMMANDLINE,
025 * OPTIONFILE. If an option cannot be found in the SAVEDOPTION internal option container it will continue to
026 * look in the DEPENDENCIES_RESOLVED internal option container and and so fourth. If the option value cannot be
027 * found in none of the internal option container, the option manager uses the default option value provided by
028 * the option description.</p>
029 *
030 * @author Johan Hall
031 * @since 1.0
032**/
033public class OptionContainer implements Comparable<OptionContainer>{
034        /* Types of internal option container */
035        public static final int SAVEDOPTION = 0;
036        public static final int DEPENDENCIES_RESOLVED = 1; 
037        public static final int COMMANDLINE = 2; 
038        public static final int OPTIONFILE = 3;
039        
040        private final int index;
041        private final SortedMap<Option,Object> savedOptionMap;
042        private final SortedMap<Option,Object> dependenciesResolvedOptionMap;
043        private final SortedMap<Option,Object> commandLineOptionMap;
044        private final SortedMap<Option,Object> optionFileOptionMap;
045
046        /**
047         * Creates an option container
048         * 
049         * @param index The index of the option container (0..n).
050         */
051        public OptionContainer(int index) throws OptionException {
052                this.index = index;
053                savedOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option,Object>());
054                dependenciesResolvedOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option,Object>());
055                commandLineOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option,Object>());
056                optionFileOptionMap = Collections.synchronizedSortedMap(new TreeMap<Option,Object>());
057        }
058        
059        /**
060         * Adds an option value to an option to one of the internal option container specified by the type.
061         * 
062         * @param type  the internal option container
063         * @param option        the option object
064         * @param value         the option value object
065         * @throws OptionException
066         */
067        protected void addOptionValue(int type, Option option, Object value) throws OptionException {
068                if (type == OptionContainer.SAVEDOPTION) {
069                        savedOptionMap.put(option, value);
070                } else if (type == OptionContainer.DEPENDENCIES_RESOLVED) {
071                        dependenciesResolvedOptionMap.put(option, value);
072                } else if (type == OptionContainer.COMMANDLINE) {
073                        commandLineOptionMap.put(option, value);
074                } else if (type == OptionContainer.OPTIONFILE) {
075                        optionFileOptionMap.put(option, value);
076                } else {
077                        throw new OptionException("Unknown option container type");
078                }
079        }
080        
081        /**
082         * Returns the option value object for the option. It uses the priority amongst the internal 
083         * option containers.
084         * 
085         * @param option the option object
086         * @return the option value object
087         */
088        public Object getOptionValue(Option option) {
089                Object value = null;
090                for (int i = OptionContainer.SAVEDOPTION; i <= OptionContainer.OPTIONFILE; i++) {
091                        if (i == OptionContainer.SAVEDOPTION) {
092                                value = savedOptionMap.get(option);
093                        } else if (i == OptionContainer.DEPENDENCIES_RESOLVED) {
094                                value = dependenciesResolvedOptionMap.get(option);
095                        } else if (i == OptionContainer.COMMANDLINE) {
096                                value = commandLineOptionMap.get(option);
097                        } else if (i == OptionContainer.OPTIONFILE) {
098                                value = optionFileOptionMap.get(option);
099                        }
100                        if (value != null) {
101                                return value;
102                        }
103                }
104                return null;
105        }
106        
107        /**
108         * Returns a string representation of the option value for the specified option. It uses the priority 
109         * amongst the internal option containers.
110         * 
111         * @param option the option object
112         * @return a string representation of the option value
113         */
114        public String getOptionValueString(Option option) {
115                String value = null;
116                for (int i = OptionContainer.SAVEDOPTION; i <= OptionContainer.OPTIONFILE; i++) {
117                        if (i == OptionContainer.SAVEDOPTION) {
118                                value = option.getStringRepresentation(savedOptionMap.get(option));
119                        } else if (i == OptionContainer.DEPENDENCIES_RESOLVED) {
120                                value = option.getStringRepresentation(dependenciesResolvedOptionMap.get(option));
121                        } else if (i == OptionContainer.COMMANDLINE) {
122                                value = option.getStringRepresentation(commandLineOptionMap.get(option));
123                        } else if (i == OptionContainer.OPTIONFILE) {
124                                value = option.getStringRepresentation(optionFileOptionMap.get(option));
125                        }
126                        if (value != null) {
127                                return value;
128                        }
129                }
130                return null;
131        }
132        
133        
134        /**
135         * Returns true if the option is present in the specified internal option container, otherwise false.
136         * 
137         * @param type  the internal option container
138         * @param option        the option object
139         * @return true if the option is present in the specified internal option container, otherwise false
140         * @throws OptionException
141         */
142        public boolean contains(int type, Option option) throws OptionException {
143                if (type == OptionContainer.SAVEDOPTION) {
144                        return savedOptionMap.containsValue(option);
145                } else if (type == OptionContainer.DEPENDENCIES_RESOLVED) {
146                        return dependenciesResolvedOptionMap.containsValue(option);
147                } else if (type == OptionContainer.COMMANDLINE) {
148                        return commandLineOptionMap.containsValue(option);
149                } else if (type == OptionContainer.OPTIONFILE) {
150                        return optionFileOptionMap.containsValue(option);
151                } else {
152                        throw new OptionException("Unknown option container type");
153                }       
154        }
155        
156        /**
157         * Returns the number of option values amongst all internal option containers.
158         * 
159         * @return the number of option values amongst all internal option containers
160         */
161        public int getNumberOfOptionValues() {
162                SortedSet<Option> union = new TreeSet<Option>(savedOptionMap.keySet());
163                union.addAll(dependenciesResolvedOptionMap.keySet());
164                union.addAll(commandLineOptionMap.keySet());
165                union.addAll(optionFileOptionMap.keySet());
166                return union.size();
167        }
168        
169        /**
170         * Returns the option container index.
171         * 
172         * @return the option container index
173         */
174        public int getIndex() {
175                return index;
176        }
177
178        public int compareTo(OptionContainer that) {
179                final int BEFORE = -1;
180            final int EQUAL = 0;
181            final int AFTER = 1;
182            if (this == that) return EQUAL;
183            if (this.index < that.index) return BEFORE;
184            if (this.index > that.index) return AFTER;
185            return EQUAL;
186        }
187        
188        
189        /* (non-Javadoc)
190         * @see java.lang.Object#toString()
191         */
192        public String toString() {
193                final StringBuilder sb = new StringBuilder();
194                SortedSet<Option> union = new TreeSet<Option>(savedOptionMap.keySet());
195                union.addAll(dependenciesResolvedOptionMap.keySet());
196                union.addAll(commandLineOptionMap.keySet());
197                union.addAll(optionFileOptionMap.keySet());
198                for (Option option : union) {
199                        Object value = null;
200                        for (int i = OptionContainer.SAVEDOPTION; i <= OptionContainer.OPTIONFILE; i++) {
201                                if (i == OptionContainer.SAVEDOPTION) {
202                                        value = savedOptionMap.get(option);
203                                } else if (i == OptionContainer.DEPENDENCIES_RESOLVED) {
204                                        value = dependenciesResolvedOptionMap.get(option);
205                                } else if (i == OptionContainer.COMMANDLINE) {
206                                        value = commandLineOptionMap.get(option);
207                                } else if (i == OptionContainer.OPTIONFILE) {
208                                        value = optionFileOptionMap.get(option);
209                                }
210                                if (value != null) {
211                                        break;
212                                }
213                        }
214                        sb.append(option.getGroup().getName()+"\t"+option.getName()+"\t"+value+"\n");
215                }
216                return sb.toString();
217        }
218
219}