001    /*--------------------------------------------------------------------------+
002    $Id: OptionRegistry.java 26283 2010-02-18 11:18:57Z juergens $
003    |                                                                          |
004    | Copyright 2005-2010 Technische Universitaet Muenchen                     |
005    |                                                                          |
006    | Licensed under the Apache License, Version 2.0 (the "License");          |
007    | you may not use this file except in compliance with the License.         |
008    | You may obtain a copy of the License at                                  |
009    |                                                                          |
010    |    http://www.apache.org/licenses/LICENSE-2.0                            |
011    |                                                                          |
012    | Unless required by applicable law or agreed to in writing, software      |
013    | distributed under the License is distributed on an "AS IS" BASIS,        |
014    | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
015    | See the License for the specific language governing permissions and      |
016    | limitations under the License.                                           |
017    +--------------------------------------------------------------------------*/
018    package edu.tum.cs.commons.options;
019    
020    import java.lang.reflect.Method;
021    import java.util.ArrayList;
022    import java.util.HashMap;
023    import java.util.List;
024    import java.util.Map;
025    
026    /**
027     * This class supports collecting options from several objects whose methods
028     * have been annotated with {@link AOption}.
029     * 
030     * @author Benjamin Hummel
031     * @author $Author: juergens $
032     * 
033     * @version $Rev: 26283 $
034     * @levd.rating GREEN Hash: 547CB47E6DA25E5AC375D3F72B123FD3
035     */
036    public class OptionRegistry {
037    
038            /** Mapping from short option names to actual option applicator. */
039            private final Map<Character, OptionApplicator> shortOptions = new HashMap<Character, OptionApplicator>();
040    
041            /** Mapping from long option names to actual option applicator. */
042            private final Map<String, OptionApplicator> longOptions = new HashMap<String, OptionApplicator>();
043    
044            /** List of all options (including description). */
045            private final List<AOption> allOptions = new ArrayList<AOption>();
046    
047            /**
048             * Default constructor. Does nothing but we want to allow this too.
049             */
050            public OptionRegistry() {
051                    // nothing to do
052            }
053    
054            /**
055             * Construct a new option registry and register the given option handler.
056             * 
057             * @param optionHandler
058             *            the option handler to register.
059             */
060            public OptionRegistry(Object optionHandler) {
061                    registerOptionHandler(optionHandler);
062            }
063    
064            /**
065             * Adds all options provided by the given object to this registry. Options
066             * are public methods annotated with AOption.
067             * 
068             * @param optionHandler
069             *            The object to extract the options from.
070             */
071            public void registerOptionHandler(Object optionHandler) {
072                    for (Method m : optionHandler.getClass().getMethods()) {
073                            AOption optionDescriptor = m.getAnnotation(AOption.class);
074                            if (optionDescriptor != null) {
075                                    allOptions.add(optionDescriptor);
076                                    OptionApplicator applicator = new OptionApplicator(
077                                                    optionHandler, m, optionDescriptor.greedy());
078                                    if (optionDescriptor.shortName() != 0) {
079                                            registerApplicator(applicator, shortOptions,
080                                                            optionDescriptor.shortName());
081                                    }
082                                    if (optionDescriptor.longName().length() > 0) {
083                                            registerApplicator(applicator, longOptions,
084                                                            optionDescriptor.longName());
085                                    }
086                            }
087                    }
088            }
089    
090            /**
091             * Registers an applicator under the given name in a map. Throws an
092             * exception if the name was already taken.
093             * 
094             * @param <T>
095             *            type of the option name used in the map.
096             * @param applicator
097             *            the option applicator to register.
098             * @param map
099             *            the map to add the applicator to.
100             * @param optionName
101             *            the name of the option.
102             */
103            private <T> void registerApplicator(OptionApplicator applicator,
104                            Map<T, OptionApplicator> map, T optionName) {
105                    if (map.containsKey(optionName)) {
106                            throw new IllegalArgumentException("An option of the name "
107                                            + optionName + " already exists!");
108                    }
109                    map.put(optionName, applicator);
110            }
111    
112            /**
113             * Returns the OptionApplicator for the given short option name or null if
114             * no such options exists.
115             * 
116             * @param name
117             *            the name of the requested option.
118             * @return the OptionApplicator for the given short option name or null if
119             *         no such options exists.
120             */
121            public OptionApplicator getShortOption(char name) {
122                    return shortOptions.get(name);
123            }
124    
125            /**
126             * Returns the OptionApplicator for the given short option name or null if
127             * no such options exists.
128             * 
129             * @param name
130             *            the name of the requested option.
131             * @return the OptionApplicator for the given short option name or null if
132             *         no such options exists.
133             */
134            public OptionApplicator getLongOption(String name) {
135                    return longOptions.get(name);
136            }
137    
138            /**
139             * Returns a list containing all supported options.
140             * 
141             * @return a list containing all supported options.
142             */
143            public List<AOption> getAllOptions() {
144                    return allOptions;
145            }
146    }