com.teradata.tempto.runner.TemptoRunnerCommandLineParser.java Source code

Java tutorial

Introduction

Here is the source code for com.teradata.tempto.runner.TemptoRunnerCommandLineParser.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.teradata.tempto.runner;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.teradata.tempto.internal.configuration.TestConfigurationFactory;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkArgument;
import static com.teradata.tempto.runner.TemptoRunnerOptions.CONFIG_FILE;
import static com.teradata.tempto.runner.TemptoRunnerOptions.CONFIG_FILE_LOCAL;
import static com.teradata.tempto.runner.TemptoRunnerOptions.EXCLUDED_GROUPS;
import static com.teradata.tempto.runner.TemptoRunnerOptions.GROUPS;
import static com.teradata.tempto.runner.TemptoRunnerOptions.HELP;
import static com.teradata.tempto.runner.TemptoRunnerOptions.PACKAGE;
import static com.teradata.tempto.runner.TemptoRunnerOptions.REPORT_DIR;
import static com.teradata.tempto.runner.TemptoRunnerOptions.TESTS;
import static java.lang.Boolean.TRUE;
import static java.util.Objects.requireNonNull;

public class TemptoRunnerCommandLineParser {
    public static class ParsingException extends RuntimeException {
        public ParsingException(String message, Throwable cause) {
            super(message, cause);
        }
    }

    private static final Comparator<Option> OPTION_BY_LONG_OPT_COMPARATOR = Comparator
            .comparing(Option::getLongOpt);

    private final String appName;
    private final List<Option> options;
    private final Map<String, DefaultValue> defaults;

    private TemptoRunnerCommandLineParser(String appName, List<Option> options,
            Map<String, DefaultValue> defaults) {
        requireNonNull(appName, "appName is null");
        requireNonNull(options, "options is null");
        requireNonNull(defaults, "defaults is null");

        this.appName = appName;
        this.options = ImmutableList.copyOf(options);
        this.defaults = ImmutableMap.copyOf(defaults);
    }

    public TemptoRunnerOptions parseCommandLine(String[] argv) {
        Options options = buildOptions();
        CommandLineParser parser = new DefaultParser();
        try {
            CommandLine commandLine = parser.parse(options, argv);
            return commandLineToOptions(commandLine);
        } catch (ParseException e) {
            throw new ParsingException(e.getMessage(), e);
        }
    }

    public void printHelpMessage() {
        printHelpMessage(new PrintWriter(System.err));
    }

    public void printHelpMessage(PrintWriter printWriter) {
        Options options = buildOptions();
        HelpFormatter helpFormatter = new HelpFormatter();
        helpFormatter.setOptionComparator(OPTION_BY_LONG_OPT_COMPARATOR);
        helpFormatter.printHelp(printWriter, 120, appName, null, options, HelpFormatter.DEFAULT_LEFT_PAD,
                HelpFormatter.DEFAULT_DESC_PAD, null);
        printWriter.flush();
    }

    private Options buildOptions() {
        Options options = new Options();
        for (Option option : this.options) {
            if (isChangable(option.getLongOpt())) {
                options.addOption(option);
            }
        }
        return options;
    }

    private boolean isChangable(String option) {
        return !defaults.containsKey(option) || defaults.get(option).isChangeable();
    }

    private TemptoRunnerOptions commandLineToOptions(CommandLine commandLine) {
        ImmutableMap.Builder<String, String> values = ImmutableMap.<String, String>builder();
        for (Option option : options) {
            Optional<String> value = getOptionValue(commandLine, option);
            if (value.isPresent()) {
                values.put(option.getLongOpt(), value.get());
            }
        }
        return new TemptoRunnerOptions(values.build());
    }

    private Optional<String> getOptionValue(CommandLine commandLine, Option option) {
        String longOpt = option.getLongOpt();
        if (defaults.containsKey(longOpt)) {
            return Optional.of(commandLine.getOptionValue(longOpt, defaults.get(longOpt).getValue()));
        }
        Optional<String> value = Optional.ofNullable(commandLine.getOptionValue(longOpt));
        if (!value.isPresent() && commandLine.hasOption(longOpt)) {
            return Optional.of(TRUE.toString());
        }
        return value;
    }

    public static Builder builder(String appName) {
        return new Builder(appName);
    }

    public static class Builder {
        private final String appName;
        private final List<Option> options = new ArrayList<>();
        private final Map<String, DefaultValue> defaults = new HashMap<>();

        private Builder(String appName) {
            this.appName = appName;
            addOption(CONFIG_FILE);
            addOption(CONFIG_FILE_LOCAL);
            addOption(EXCLUDED_GROUPS);
            addOption(GROUPS);
            addOption(PACKAGE);
            addOption(REPORT_DIR);
            addOption(TESTS);
            addOption(HELP);
            setReportDir("./test-reports", true);
            setConfigFile(TestConfigurationFactory.DEFAULT_TEST_CONFIGURATION_LOCATION, true);
            setConfigLocalFile(TestConfigurationFactory.DEFAULT_LOCAL_TEST_CONFIGURATION_LOCATION, true);
        }

        public Builder addOption(Option option) {
            checkArgument(!contains(option), "Options %s is already added", option.getLongOpt());
            options.add(option);
            return this;
        }

        private boolean contains(Option option) {
            return options.stream().anyMatch(o -> o.getLongOpt().equals(option.getLongOpt()));
        }

        public Builder setTestsPackage(String testsPackage, boolean changeable) {
            return setDefaultValue(PACKAGE, testsPackage, changeable);
        }

        public Builder setConfigFile(String configFile, boolean changeable) {
            return setDefaultValue(CONFIG_FILE, configFile, changeable);
        }

        private void setConfigLocalFile(String configFile, boolean changeable) {
            setDefaultValue(CONFIG_FILE_LOCAL, configFile, changeable);
        }

        public Builder setReportDir(String reportDir, boolean changeable) {
            return setDefaultValue(REPORT_DIR, reportDir, changeable);
        }

        public Builder setExcludedGroups(String excludedGroups, boolean changeable) {
            return setDefaultValue(EXCLUDED_GROUPS, excludedGroups, changeable);
        }

        public Builder setGroups(String groups, boolean changeable) {
            return setDefaultValue(GROUPS, groups, changeable);
        }

        public Builder setDefaultValue(Option option, Object value) {
            return setDefaultValue(option, value.toString(), true);
        }

        private Builder setDefaultValue(Option option, String value, boolean changeable) {
            if (!contains(option)) {
                addOption(option);
            }
            defaults.put(option.getLongOpt(), new DefaultValue(value.toString(), changeable));
            return this;
        }

        public TemptoRunnerCommandLineParser build() {
            return new TemptoRunnerCommandLineParser(appName, options, defaults);
        }
    }

    private static class DefaultValue {
        private final String value;
        private final boolean changeable;

        private DefaultValue(String value, boolean changeable) {
            this.value = value;
            this.changeable = changeable;
        }

        public String getValue() {
            return value;
        }

        public boolean isChangeable() {
            return changeable;
        }
    }
}