/* Copyright (C) 2009 Diego Darriba This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package es.uvigo.darwin.prottest.util.argumentparser; import static es.uvigo.darwin.prottest.global.ProtTestConstants.DEFAULT_NCAT; import static es.uvigo.darwin.prottest.global.ProtTestConstants.DEFAULT_STRATEGY_MODE; import static es.uvigo.darwin.prottest.global.ProtTestConstants.DEFAULT_THREADS; import static es.uvigo.darwin.prottest.global.ProtTestConstants.OPTIMIZE_VALUES; import static es.uvigo.darwin.prottest.global.ProtTestConstants.TREE_SEARCH_BEST; import static es.uvigo.darwin.prottest.global.ProtTestConstants.TREE_SEARCH_NNI; import static es.uvigo.darwin.prottest.global.ProtTestConstants.TREE_SEARCH_SPR; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import es.uvigo.darwin.prottest.global.ProtTestConsoleParameters; import es.uvigo.darwin.prottest.global.options.ApplicationOptions; /** * The Class ProtTestArgumentParser. */ public abstract class ProtTestArgumentParser implements ProtTestConsoleParameters { /** Hashtable to associate parameter tokens within parameter localArguments requirements. */ protected static final HashMap<String, Boolean> valuesRequired; /** Hashtable to associate parameter tokens within parameter localArguments range. */ protected static final HashMap<String, String[]> argumentValues; /** Hashtable to handle special localArguments like "all-distributions". */ protected static final HashMap<String, Map<String, String>> specialArguments; /** The default APPLICATION_PROPERTIES. */ private static final Properties defaultProperties; /** The argument prefix. */ public static final String ARG_TOKEN = "-"; /** The command line localArguments. */ private Properties arguments; static { valuesRequired = new HashMap<String, Boolean>(); argumentValues = new HashMap<String, String[]>(); specialArguments = new HashMap<String, Map<String, String>>(); valuesRequired.put(PARAM_HELP, false); valuesRequired.put(PARAM_ALIGNMENT_FILE, true); valuesRequired.put(PARAM_OUTPUT_FILE, true); valuesRequired.put(PARAM_TREE_FILE, true); String[] optimizationStrategies = new String[OPTIMIZE_VALUES.length]; for (int index = 0; index < OPTIMIZE_VALUES.length; index++) { optimizationStrategies[index] = String.valueOf(OPTIMIZE_VALUES[index]); } valuesRequired.put(PARAM_OPTIMIZATION_STRATEGY, true); argumentValues.put(PARAM_OPTIMIZATION_STRATEGY, optimizationStrategies); String[] treeSearchOps = { TREE_SEARCH_NNI, TREE_SEARCH_SPR, TREE_SEARCH_BEST }; String[] enabling = { "enabled", "disabled" }; valuesRequired.put(PARAM_TREE_SEARCH_OP, true); argumentValues.put(PARAM_TREE_SEARCH_OP, treeSearchOps); valuesRequired.put(PARAM_NUM_THREADS, true); valuesRequired.put(PARAM_ALL_FRAMEWORK_COMPARISON, false); valuesRequired.put(PARAM_DISPLAY_NEWICK_TREE, false); valuesRequired.put(PARAM_DISPLAY_ASCII_TREE, false); valuesRequired.put(PARAM_DISPLAY_CONSENSUS_TREE, true); valuesRequired.put(PARAM_PLUSF, false); valuesRequired.put(PARAM_PLUSI, false); valuesRequired.put(PARAM_PLUSG, false); valuesRequired.put(PARAM_PLUSIG, false); valuesRequired.put(PARAM_NCAT, true); valuesRequired.put(PARAM_ALL_DISTRIBUTIONS, false); valuesRequired.put(PARAM_VERBOSE, false); valuesRequired.put(PARAM_DO_AIC, false); valuesRequired.put(PARAM_DO_BIC, false); valuesRequired.put(PARAM_DO_AICC, false); valuesRequired.put(PARAM_DO_DT, false); valuesRequired.put(PARAM_LOGGING, true); argumentValues.put(PARAM_LOGGING, enabling); Map<String, String> distributionsMap = new HashMap<String, String>(3); distributionsMap.put(PARAM_PLUSG, "T"); distributionsMap.put(PARAM_PLUSI, "T"); distributionsMap.put(PARAM_PLUSIG, "T"); specialArguments.put(PARAM_ALL_DISTRIBUTIONS, distributionsMap); defaultProperties = new Properties(); defaultProperties.setProperty(PARAM_NUM_THREADS, String.valueOf(DEFAULT_THREADS)); defaultProperties.setProperty(PARAM_NCAT, String.valueOf(DEFAULT_NCAT)); defaultProperties.setProperty(PARAM_OPTIMIZATION_STRATEGY, String.valueOf(DEFAULT_STRATEGY_MODE)); defaultProperties.setProperty(PARAM_DATA_TYPE, DATA_TYPE_AMINOACID); } /** * Instantiates a new model test argument parser. * * @param args the command line localArguments * @param options the application options * * @throws IllegalArgumentException when exists some error in the command line argument */ public ProtTestArgumentParser(String[] args, ApplicationOptions options) throws IllegalArgumentException { arguments = checkArgs(args); if (!(exists(PARAM_DO_BIC) || exists(PARAM_DO_AIC) || exists(PARAM_DO_AICC) || exists(PARAM_DO_DT))) { putArgument(PARAM_DO_BIC, "T", arguments); } options.fillIn(this); } /** * Check localArguments are grammatically correct and parse them into * the instance. * * @param args the command line localArguments * * @return the argument APPLICATION_PROPERTIES * * @throws IllegalArgumentException when exists some error in the command line argument */ protected Properties checkArgs(String[] args) throws IllegalArgumentException { Properties localArguments = new Properties(defaultProperties); int i = 0; while (i < args.length) { String arg = args[i]; if (!arg.startsWith(ARG_TOKEN)) { System.err.print("Command line: "); for (String simpleArg : args) { System.err.print(simpleArg + " "); } System.err.println(" "); throw new IllegalArgumentException("Arguments must start with \"-\". The ofending argument was: " + arg); } arg = arg.substring(ARG_TOKEN.length()); if (valuesRequired.containsKey(arg)) { if (valuesRequired.get(arg)) { if (i + 1 < args.length && !args[i+1].startsWith("-")) { i++; String value = args[i]; if (argumentValues.containsKey(arg)) { String[] values = argumentValues.get(arg); if (!Arrays.asList(values).contains(value.toLowerCase())) { throw new IllegalArgumentException("Invalid argument value " + value + " for parameter " + arg); } } // special cases if (specialArguments.containsKey(arg)) { Map<String, String> mapValues = specialArguments.get(arg); for (String key : mapValues.keySet()) { if (mapValues.get(key).equals("?")) { mapValues.put(key, value); } } putArgument(mapValues, localArguments); } else { putArgument(arg, value, localArguments); } } else { IllegalArgumentException e = new IllegalArgumentException("Parameter " + arg + " requires a value"); throw e; } } else { if (specialArguments.containsKey(arg)) { Map<String, String> mapValues = specialArguments.get(arg); putArgument(mapValues, localArguments); } else { putArgument(arg, "T", localArguments); } } } else { // Obsolete arguments checking... if (arg.equals("-sort")) { System.err.println(" WARNING! \"sort\" argument is obsolete since 3.2 version. You should use one or more of the following instead: -AIC -AICC -BIC -DT"); } throw new IllegalArgumentException("Invalid argument " + arg); } i++; } return localArguments; } /** * Checks if a concrete argument exists in the application. * * @param arg the argument to check * * @return true, if the argument has a value */ public boolean exists(String arg) { return arguments.containsKey(arg); } /** * Checks if a boolean argument is set in the application. * The method will return false if the boolean argument * is set to 'false', the argument is not boolean or the * argument does not exist in the argument list. * * @param arg the argument to check * * @return true, if the boolean argument is set to 'true' */ public boolean isSet(String arg) { boolean isSet; try { isSet = arguments.get(arg).equals("T"); } catch (NullPointerException npe) { isSet = false; } return isSet; } /** * Gets the value of an argument. If the argument key is not found, * the default localArguments will be checked. If the argument key does * not exist, the method will return null. * * @param arg the argument to check * * @return the argument value */ public String getValue(String arg) { return arguments.getProperty(arg); } /** * Puts an argument into the argument list, with specified key and value. * If the argument was already set to a certain value, the argument will * take the new value, and a warning message will be printed into * standard error output. * * @param key the argument key * @param value the argument value * @param localArguments the argument list */ private void putArgument(String key, String value, Properties arguments) { if (arguments.containsKey(key)) { System.err.println("WARNING! Repeated argument \"" + key + "\". New value is " + value); } arguments.setProperty(key, value); } /** * Puts a set of couples argument-value into the argument list. * For each argument that was already set to a certain value, the * argument will take the new value, and a warning message will be * printed into standard error output. * * @param items the new localArguments to put * @param localArguments the argument list */ private void putArgument(Map<String, String> items, Properties arguments) { // localArguments.putAll(items); for (String key : items.keySet()) { putArgument(key, items.get(key), arguments); } } /** * Gets the matrix name list of all supported matrices. * * @return the matrix name list */ public abstract List<String> getMatrices(); }