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