/**
* SQL-DK
* Copyright © 2013 František Kučera (frantovo.cz)
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*/
package info.globalcode.sql.dk;
import info.globalcode.sql.dk.InfoLister.InfoType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author Ing. František Kučera (frantovo.cz)
*/
public class CLIParser {
public static final String TYPE_NAME_SEPARATOR = ":";
public CLIOptions parseOptions(String[] args) throws CLIParserException {
CLIOptions options = new CLIOptions();
List<SQLType> numberedTypes = new ArrayList<>();
Map<String, SQLType> namedTypes = new HashMap<>();
for (int i = 0; i < args.length; i++) {
String arg = args[i];
switch (arg) {
case Tokens.TYPES:
String typesString = fetchNext(args, ++i);
for (String oneType : typesString.split(",")) {
int sepatratorIndex = oneType.indexOf(TYPE_NAME_SEPARATOR);
if (sepatratorIndex == -1) {
numberedTypes.add(getType(oneType.toUpperCase()));
} else {
String namePart = oneType.substring(0, sepatratorIndex).trim();
String typePart = oneType.substring(sepatratorIndex + TYPE_NAME_SEPARATOR.length(), oneType.length());
namedTypes.put(namePart, getType(typePart.toUpperCase()));
}
}
break;
case Tokens.NAME_PREFIX:
options.setNamePrefix(fetchNext(args, ++i));
break;
case Tokens.NAME_SUFFIX:
options.setNameSuffix(fetchNext(args, ++i));
break;
case Tokens.DB:
options.setDatabaseName(fetchNext(args, ++i));
break;
case Tokens.SQL:
options.setSql(fetchNext(args, ++i));
break;
case Tokens.BATCH:
options.setBatch(true);
break;
case Tokens.DATA: // --data is the last option
for (i++; i < args.length; i++) {
arg = args[i];
Parameter parameter;
if (numberedTypes.isEmpty()) {
parameter = new Parameter(arg, null);
} else {
int paramIndex = options.getNumberedParameters().size();
SQLType paramType;
try {
paramType = numberedTypes.get(paramIndex);
} catch (IndexOutOfBoundsException e) {
throw new CLIParserException("Missing type for parameter #" + paramIndex, e);
} catch (NullPointerException e) {
throw new CLIParserException("Invalid type definition for parameter #" + paramIndex, e);
}
parameter = new Parameter(arg, paramType);
}
options.addNumberedParameter(parameter);
}
break;
case Tokens.DATA_NAMED:
for (i++; i < args.length; i++) {
String paramName = args[i];
String paramValue = fetchNext(args, ++i);
options.addNamedParameter(new NamedParameter(paramName, paramValue, namedTypes.get(paramName)));
}
break;
case Tokens.FORMATTER:
options.setFormatterName(fetchNext(args, ++i));
break;
case Tokens.INFO_HELP:
options.addShowInfo(InfoType.HELP);
break;
case Tokens.INFO_FORMATTERS:
options.addShowInfo(InfoType.FORMATTERS);
break;
case Tokens.INFO_LICENSE:
options.addShowInfo(InfoType.LICENSE);
break;
case Tokens.INFO_TYPES:
options.addShowInfo(InfoType.TYPES);
break;
case Tokens.INFO_VERSION:
options.addShowInfo(InfoType.VERSION);
break;
case Tokens.INFO_DATABASES:
options.addShowInfo(InfoType.DATABASES);
break;
case Tokens.INFO_CONNECTION:
options.addShowInfo(InfoType.CONNECTION);
options.addDatabaseNameToTest(fetchNext(args, ++i));
break;
default:
throw new CLIParserException("Unknown option: " + arg);
}
}
return options;
}
private String fetchNext(String[] args, int index) throws CLIParserException {
if (index < args.length) {
return args[index];
} else {
throw new CLIParserException("Expecting value for option: " + args[index - 1]);
}
}
public static class Tokens {
// bash-completion:options:
public static final String DB = "--db"; // bash-completion:option // help: database name
public static final String SQL = "--sql"; // bash-completion:option // help: SQL query/command
public static final String BATCH = "--batch"; // bash-completion:option // help: batch mode (no argument)
public static final String DATA = "--data"; // bash-completion:option // help: list of ordinal parameters
public static final String DATA_NAMED = "--data-named"; // bash-completion:option // help: list of named parameters
public static final String NAME_PREFIX = "--name-prefix"; // bash-completion:option // help: parameter name prefix – regular expression
public static final String NAME_SUFFIX = "--name-suffix"; // bash-completion:option // help: parameter name suffix – regular expression
public static final String TYPES = "--types"; // bash-completion:option // help: comma separated list of parameter types
public static final String FORMATTER = "--formatter"; // bash-completion:option // help: name of the output formatter
public static final String INFO_HELP = "--help"; // bash-completion:option // help: print this help
public static final String INFO_VERSION = "--version"; // bash-completion:option // help: print version info
public static final String INFO_LICENSE = "--license"; // bash-completion:option // help: print license
public static final String INFO_FORMATTERS = "--list-formatters"; // bash-completion:option // help: print list of available formatters
public static final String INFO_TYPES = "--list-types"; // bash-completion:option // help: print list of supported data types
public static final String INFO_DATABASES = "--list-databases"; // bash-completion:option // help: print list of configured databases
public static final String INFO_CONNECTION = "--test-connection"; // bash-completion:option // help: test connection to particular database
private Tokens() {
}
}
private SQLType getType(String typeString) throws CLIParserException {
try {
return SQLType.valueOf(typeString.trim());
} catch (IllegalArgumentException e) {
throw new CLIParserException("Unsupported type: " + typeString, e);
}
}
}