/* * 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.HashMap; import java.util.Map; import java.util.logging.Logger; /** * Simple parser for options (typically command line arguments). * @author jwbroek */ public class SimpleOptionsParser { /** * The logger for this class. */ private final static Logger logger = Logger.getLogger(SimpleOptionsParser.class.getCanonicalName()); /** * Interface that you must implement if you want to handle options. {@link jwbroek.util.SimpleOptionsParser} * will call the OptionHandler that is registered for an option, when it encounters that option. */ public interface OptionHandler { /** * Handle the option found at the specified offset in the options list. The handler must handle at least the option * at the offset. If it cannot, it must throw an Exception. It may handle more than one option. * @param options * @param offset * @return The index of the last option parsed + 1. The handler must handle at least the option at the offset. If * it cannot, it must throw an Exception. */ public int handleOption(String [] options, int offset); } /** * Map from option key to handler for that option. */ Map<String, OptionHandler> optionHandlers = new HashMap<String, OptionHandler>(); /** * Create a new SimpleOptionsParser. */ public SimpleOptionsParser() { SimpleOptionsParser.logger.entering(SimpleOptionsParser.class.getCanonicalName(), "SimpleOptionsParser()"); SimpleOptionsParser.logger.exiting(SimpleOptionsParser.class.getCanonicalName(), "SimpleOptionsParser()"); } /** * <p>Register an option with the parser. If the option is found, then the specified handler will be called.</p> * @param optionKey The option to be registered. For instance "-a". * @param handler The handler to handle this option. * @deprecated The prefered method is {@link #registerOption(jwbroek.util.SimpleOptionsParser.OptionHandler, String[])}. */ public void registerOption(String optionKey, OptionHandler handler) { SimpleOptionsParser.logger.entering ( SimpleOptionsParser.class.getCanonicalName() , "registerOption(String,OptionHandler)" , new Object [] {optionKey, handler} ); this.optionHandlers.put(optionKey, handler); SimpleOptionsParser.logger.exiting (SimpleOptionsParser.class.getCanonicalName(), "registerOption(String,OptionHandler)"); } /** * <p>Register options with identical handler with the parser. When one of the the options is found, * the specified handler will be called.</p> * @param optionKeys The options to be registered. For instance "-a", "--alpha". * @param handler The handler to handle these options. */ public void registerOption(OptionHandler handler, String ... optionKeys) { SimpleOptionsParser.logger.entering ( SimpleOptionsParser.class.getCanonicalName() , "registerOption(OptionHandler,String[])" , new Object [] {handler, optionKeys} ); for (String optionKey : optionKeys) { this.optionHandlers.put(optionKey, handler); } SimpleOptionsParser.logger.exiting (SimpleOptionsParser.class.getCanonicalName(), "registerOption(OptionHandler,String[])"); } /** * Parse the previously registered options. * @param options The options to parse. Each element will be considered an atomic option element. * @return The index of the first option that could not be matched, or options.length if everything was matched. */ public int parseOptions(final String [] options) { SimpleOptionsParser.logger.entering (SimpleOptionsParser.class.getCanonicalName(), "parseOptions(String[])", new Object [] {options}); int result = parseOptions(options, 0); SimpleOptionsParser.logger.exiting (SimpleOptionsParser.class.getCanonicalName(), "registerOption(OptionHandler,String[])", result); return result; } /** * Parse the previously registered options. * @param options The options to parse. Each element will be considered an atomic option element. * @param offset First option element to parse. * @return The index of the first option that could not be matched, or options.length if everything was matched. */ public int parseOptions(final String [] options, final int offset) { SimpleOptionsParser.logger.entering (SimpleOptionsParser.class.getCanonicalName(), "parseOptions(String[],int)", new Object [] {options, offset}); int currentOffset = offset; OptionHandler currentHandler = null; loopOverOptions: while (currentOffset < options.length) { currentHandler = this.optionHandlers.get(options[currentOffset]); // Can't handle this option. if (currentHandler==null) { break loopOverOptions; } int nextOffset = currentHandler.handleOption(options, currentOffset); // Handler did not handle at least the first option. This is an exception state, as it would lead // to an infinite loop. if (nextOffset==currentOffset) { IllegalStateException e = new IllegalStateException ( "Handler registered for option \"" + options[currentOffset] + "\" did not handle it." ); SimpleOptionsParser.logger.throwing(SimpleOptionsParser.class.getCanonicalName(), "parseOptions(String[],int)", e); throw e; } // Handler claims to have handled more options than actually exist. if (nextOffset > options.length) { IllegalStateException e = new IllegalStateException ( "Handler registered for option \"" + options[currentOffset] + "\" claims to have handled more options than are existent." ); SimpleOptionsParser.logger.throwing(SimpleOptionsParser.class.getCanonicalName(), "parseOptions(String[],int)", e); throw e; } currentOffset = nextOffset; } SimpleOptionsParser.logger.exiting (SimpleOptionsParser.class.getCanonicalName(), "parseOptions(String[],int)", currentOffset); return currentOffset; } }