/* * Cuelib library for manipulating cue sheets. * Copyright (C) 2007-2008 Jan-Willem van den Broek * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package jwbroek.util; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.logging.Logger; /** * Simple parser for putting arguments (typically command line arguments) into a Properties instance. * @author jwbroek */ public class SimpleOptionsToPropertiesParser { /** * The logger for this class. */ private final static Logger logger = Logger.getLogger(SimpleOptionsToPropertiesParser.class.getCanonicalName()); /** * Map from option key to a list of property keys. */ Map<String, List<String>> argumentData = new HashMap<String, List<String>>(); public SimpleOptionsToPropertiesParser() { // Nothing to do. Could have used the default constructor, but I like to be explicit. SimpleOptionsToPropertiesParser.logger.entering (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "SimpleOptionsToPropertiesParser()"); SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "SimpleOptionsToPropertiesParser()"); } /** * <p>Register an option with the parser. If the option is found, then the specified properties will be set to the * values following the option. The first property key is special in that it will be set to the option key that was * parsed. This property key may be null.</p> * * <p>For instance, suppose that optionKey is "-add" and that propertyKeys is ["OPERATION", "FIRST", * "SECOND"]. In this case, after parsing ["-add", "1", "5"], the property "OPERATION" will be set to * "-add", property "FIRST" will be set to "1", and property "SECOND" will be set to "5".</p> * @param optionKey The option to be registered. For instance "-a". * @param propertyKeys The property keys to set when the option is parsed. */ public void registerOption(String optionKey, String ... propertyKeys) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "registerOption(String,String[])" , new Object[] {optionKey, propertyKeys} ); this.argumentData.put(optionKey, Arrays.asList(propertyKeys)); SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "registerOption(String,String[])"); } /** * <p>Register an option with the parser. If the option is found, then the specified properties will be set to the * values following the option. The first property key is special in that it will be set to the option key that was * parsed. This property key may be null.</p> * * <p>For instance, suppose that optionKey is "-add" and that propertyKeys is {"OPERATION", "FIRST", * "SECOND"}. In this case, after parsing ["-add", "1", "5"], the property "OPERATION" will be set to * "-add", property "FIRST" will be set to "1", and property "SECOND" will be set to "5".</p> * @param optionKey The option to be registered. For instance "-a". * @param propertyKeys The property keys to set when the option is parsed. */ public void registerOption(String optionKey, List<String> propertyKeys) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "registerOption(String,List<String>)" , new Object[] {optionKey, propertyKeys} ); this.argumentData.put(optionKey, propertyKeys); SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "registerOption(String,List<String>)"); } /** * <p>Register an option with the parser. If one of the alternatives for the option is found, then the specified * properties will be set to the values following the option. The first property key is special in that it will be * set to the option key that was parsed. This property key may be null.</p> * * <p>For instance, suppose that optionKeyAlternatives is {"-a", "-add", "-add-numbers"} and that propertyKeys is * {"OPERATION", "FIRST", "SECOND"}. In this case, after parsing ["-add", "1", "5"], the property "OPERATION" will be * set to "-add", property "FIRST" will be set to "1", and property "SECOND" will be set to "5".</p> * @param optionKeyAlternatives A list of option keys that indicate the same option. For instance {"-a", "-add", * "-add-numbers"}. * @param propertyKeys The property keys to set when the option is parsed. */ public void registerOption(List<String> optionKeyAlternatives, List<String> propertyKeys) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "registerOption(List<String>,List<String>)" , new Object[] {optionKeyAlternatives, propertyKeys} ); for (String optionKey : optionKeyAlternatives) { registerOption(optionKey, propertyKeys); } SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "registerOption(List<String>,List<String>)"); } /** * <p>Register an option with the parser. If one of the alternatives for the option is found, then the specified * properties will be set to the values following the option. The first property key is special in that it will be * set to the option key that was parsed. This property key may be null.</p> * * <p>For instance, suppose that optionKeyAlternatives is ["-a", "-add", "-add-numbers"] and that propertyKeys is * ["OPERATION", "FIRST", "SECOND"]. In this case, after parsing ["-add", "1", "5"], the property "OPERATION" will be * set to "-add", property "FIRST" will be set to "1", and property "SECOND" will be set to "5".</p> * @param optionKeyAlternatives An array of option keys that indicate the same option. For instance ["-a", "-add", * "-add-numbers"]. * @param propertyKeys The property keys to set when the option is parsed. */ public void registerOption(String [] optionKeyAlternatives, String ... propertyKeys) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "registerOption(String[],String [])" , new Object[] {optionKeyAlternatives, propertyKeys} ); for (String optionKey : optionKeyAlternatives) { registerOption(optionKey, propertyKeys); } SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "registerOption(String[],String [])"); } /** * Parse the previously registered options. * @param options The options to parse. Each element will be considered an atomic option element. * @param properties The Properties instance in which the keys will be set that were specified when the options * were registered. * @return The index of the first option that could not be matched, options.length if everything was matched, or -1 * if there was a problem. */ public int parseOptions(String [] options, Properties properties) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "registerOption(String[],Properties)" , new Object[] {options, properties} ); int result = parseOptions(options, 0, options.length, properties); SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "registerOption(String[],Properties)", result); return result; } /** * Parse the previously registered options. * @param options The options to parse. Each element will be considered an atomic option element. * @param beginIndex First option element to parse. * @param endIndex Only parse option elements up to (excluding) this index. * @param properties The Properties instance in which the keys will be set that were specified when the options * were registered. * @return The index of the first option that could not be matched, endIndex if everything was matched, or -1 if * there was a problem. */ public int parseOptions(String [] options, int beginIndex, int endIndex, Properties properties) { SimpleOptionsToPropertiesParser.logger.entering ( SimpleOptionsToPropertiesParser.class.getCanonicalName() , "parseOptions(String[],int,int,Properties)" , new Object[] {options, beginIndex, endIndex, properties} ); int result = endIndex; loopOverOptions: for (int optionIndex = beginIndex; optionIndex < endIndex; optionIndex++) { List<String> propertyKeys = this.argumentData.get(options[optionIndex]); if (propertyKeys==null) { // Unknown option. result = optionIndex; break loopOverOptions; } // We don't count the first optionValueKey as that one corresponds to the option itself. So, we're actually // checking !(optionIndex + propertyKeys.size() - 1 < endIndex), which is // optionIndex + propertyKeys.size() - 1 >= endIndex, which is optionIndex + propertyKeys.size() > endIndex. if (optionIndex + propertyKeys.size() > endIndex) { // Insufficient values. result = -1; break loopOverOptions; } // If the first optionValueKeys value is present, then we'll set this property to the parsed option key. if (propertyKeys.get(0)!=null) { properties.setProperty(propertyKeys.get(0), options[optionIndex]); } // Set the various property keys to the specified values. for (int propertyKeyIndex = 1; propertyKeyIndex < propertyKeys.size(); propertyKeyIndex++) { properties.setProperty(propertyKeys.get(propertyKeyIndex), options[++optionIndex]); } } SimpleOptionsToPropertiesParser.logger.exiting (SimpleOptionsToPropertiesParser.class.getCanonicalName(), "parseOptions(String[],int,int,Properties)", result); return result; } }