diff -r 7e08730da258 -r 4a1864c3e867 java/sql-dk/src/main/java/info/globalcode/sql/dk/CLIOptions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/java/sql-dk/src/main/java/info/globalcode/sql/dk/CLIOptions.java Mon Mar 04 20:15:24 2019 +0100 @@ -0,0 +1,283 @@ +/** + * 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 . + */ +package info.globalcode.sql.dk; + +import static info.globalcode.sql.dk.Functions.isNotEmpty; +import static info.globalcode.sql.dk.Functions.equalz; +import info.globalcode.sql.dk.InfoLister.InfoType; +import info.globalcode.sql.dk.configuration.Properties; +import info.globalcode.sql.dk.configuration.Property; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +/** + * Holds options from command line, validates them, combines with configuration and provides derived + * objects. + * + * @author Ing. František Kučera (frantovo.cz) + */ +public class CLIOptions { + + public static final String DEFAULT_NAME_PREFIX = ":"; + public static final String DEFAULT_NAME_SUFFIX = "(?=([^\\w]|$))"; + private String sql; + private String databaseName; + private final Set databaseNamesToTest = new LinkedHashSet<>(); + private final Set databaseNamesToListProperties = new LinkedHashSet<>(); + private final Set formatterNamesToListProperties = new LinkedHashSet<>(); + private String namePrefix = DEFAULT_NAME_PREFIX; + private String nameSuffix = DEFAULT_NAME_SUFFIX; + private String formatterName; + private boolean batch; + private final Properties formatterProperties = new Properties(); + private final Properties databaseProperties = new Properties(); + + public enum MODE { + + QUERY_NOW, + PREPARE_BATCH, + EXECUTE_BATCH, + JUST_SHOW_INFO + } + private final List namedParameters = new ArrayList<>(); + private final List numberedParameters = new ArrayList<>(); + private final EnumSet showInfo = EnumSet.noneOf(InfoType.class); + + public void validate() throws InvalidOptionsException { + InvalidOptionsException e = new InvalidOptionsException(); + + MODE mode = getMode(); + if (mode == null) { + e.addProblem(new InvalidOptionsException.OptionProblem("Invalid combination of DB, SQL and BATCH – please specify just 2 of this 3 options")); + } else if (mode == MODE.JUST_SHOW_INFO) { + if (!namedParameters.isEmpty()) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not use named parameters if just showing info.")); + } + if (!numberedParameters.isEmpty()) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not use numbered parameters if just showing info.")); + } + if (isNotEmpty(sql, false)) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not specify SQL if just showing info.")); + } + if (isNotEmpty(databaseName, false)) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not specify database if just showing info.")); + } + if (batch) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not specify batch if just showing info.")); + } + if (!equalz(namePrefix, DEFAULT_NAME_PREFIX)) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not specify name prefix if just showing info.")); + } + if (!equalz(nameSuffix, DEFAULT_NAME_SUFFIX)) { + e.addProblem(new InvalidOptionsException.OptionProblem("Do not specify name suffix if just showing info.")); + } + if (showInfo.contains(InfoType.CONNECTION) && databaseNamesToTest.isEmpty()) { + e.addProblem(new InvalidOptionsException.OptionProblem("Please specify which database should be tested.")); + } + if (showInfo.contains(InfoType.JDBC_PROPERTIES) && databaseNamesToListProperties.isEmpty()) { + e.addProblem(new InvalidOptionsException.OptionProblem("Please specify for which database the properties should be listed.")); + } + } + + if (!namedParameters.isEmpty() && !numberedParameters.isEmpty()) { + e.addProblem(new InvalidOptionsException.OptionProblem("Named and numbered parameters can not be used together in one command.")); + } + + try { + Pattern.compile(namePrefix + "test" + nameSuffix); + } catch (PatternSyntaxException regexException) { + e.addProblem(new InvalidOptionsException.OptionProblem("Ivalid regular expression in name prefix or suffix", regexException)); + } + + if (e.hasProblems()) { + throw e; + } + } + + private boolean hasSql() { + return isNotEmpty(getSql(), true); + } + + private boolean hasDb() { + return isNotEmpty(getDatabaseName(), true); + } + + /** + * Depends on options: DB, BATCH, SQL + * + * @return mode | or null if options are not yet initialized or combination of options is + * invalid + */ + public MODE getMode() { + if (hasDb() && !batch && hasSql()) { + return MODE.QUERY_NOW; + } else if (!hasDb() && batch && hasSql()) { + return MODE.PREPARE_BATCH; + } else if (hasDb() && batch && !hasSql()) { + return MODE.EXECUTE_BATCH; + } else { + return showInfo.isEmpty() ? null : MODE.JUST_SHOW_INFO; + } + } + + public String getSql() { + return sql; + } + + public void setSql(String sql) { + this.sql = sql; + } + + public String getDatabaseName() { + return databaseName; + } + + public void setDatabaseName(String databaseName) { + this.databaseName = databaseName; + } + + public void setBatch(boolean batch) { + this.batch = batch; + } + + public Collection getNamedParameters() { + return namedParameters; + } + + public List getNumberedParameters() { + return numberedParameters; + } + + public void addNumberedParameter(Parameter p) { + numberedParameters.add(p); + } + + public void addNamedParameter(NamedParameter p) { + namedParameters.add(p); + } + + public Properties getDatabaseProperties() { + return databaseProperties; + } + + public Properties getFormatterProperties() { + return formatterProperties; + } + + public void addDatabaseProperty(Property p) { + databaseProperties.add(p); + } + + public void addFormatterProperty(Property p) { + formatterProperties.add(p); + } + + /** + * @return regular expression describing the name prefix + */ + public String getNamePrefix() { + return namePrefix; + } + + /** + * @param namePrefix + * @see #getNamePrefix() + */ + public void setNamePrefix(String namePrefix) { + this.namePrefix = namePrefix; + } + + /** + * @return regular expression describing the name prefix + */ + public String getNameSuffix() { + return nameSuffix; + } + + /** + * @param nameSuffix + * @see #getNameSuffix() + */ + public void setNameSuffix(String nameSuffix) { + this.nameSuffix = nameSuffix; + } + + public String getFormatterName() { + return formatterName; + } + + public void setFormatterName(String formatterName) { + this.formatterName = formatterName; + } + + public void addShowInfo(InfoType info) { + showInfo.add(info); + } + + public EnumSet getShowInfo() { + return showInfo; + } + + public Set getDatabaseNamesToTest() { + return databaseNamesToTest; + } + + public void addDatabaseNameToTest(String name) { + databaseNamesToTest.add(name); + } + + public Set getDatabaseNamesToListProperties() { + return databaseNamesToListProperties; + } + + public void addDatabaseNameToListProperties(String name) { + databaseNamesToListProperties.add(name); + } + + public Set getFormatterNamesToListProperties() { + return formatterNamesToListProperties; + } + + public void addFormatterNameToListProperties(String name) { + formatterNamesToListProperties.add(name); + } + + public SQLCommand getSQLCommand() { + if (namedParameters.isEmpty()) { + return new SQLCommandNumbered(sql, numberedParameters); + } else { + return new SQLCommandNamed(sql, namedParameters, namePrefix, nameSuffix); + } + } + + public OutputStream getOutputStream() { + return System.out; + } + + public InputStream getInputStream() { + return System.in; + } +}