org.jboss.jbossset.CommandLineParser.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.jbossset.CommandLineParser.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2015, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This 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 software 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 software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.jbossset;

import org.apache.commons.cli.CommandLine;
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 org.apache.commons.csv.CSVFormat;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author Ryan Emerson
 */
public class CommandLineParser {

    private final Map<String, CSVFormat> validCSVFormats;
    private final String[] args;
    private final Options options = new Options();
    private List<String> usernames;
    private LocalDate startDate = LocalDate.of(1990, 1, 1);
    private LocalDate endDate = LocalDate.now();
    private String issueOrder = "ASC";
    private CSVFormat csvFormat = CSVFormat.EXCEL;
    private int issueLimit = 50;
    private Map<String, String> domains = new HashMap<>();

    public CommandLineParser(String[] args) {
        this.args = args;

        validCSVFormats = new HashMap<>();
        validCSVFormats.put("excel", CSVFormat.EXCEL);
        validCSVFormats.put("mysql", CSVFormat.MYSQL);
        validCSVFormats.put("rfc4180", CSVFormat.RFC4180);
        validCSVFormats.put("tdf", CSVFormat.TDF);

        addOptions();
    }

    public void parse() throws ParseException {
        CommandLine cmd = new DefaultParser().parse(options, args);

        if (cmd.hasOption("help")) {
            new HelpFormatter().printHelp(JiraReporter.class.getSimpleName(), options);
            System.exit(0);
            return;
        }

        usernames = getValidUsernames(cmd);
        domains = getValidDomains(cmd);

        if (cmd.hasOption("startDate"))
            startDate = getValidLocalDate(cmd.getOptionValue("startDate"), "startDate");

        if (cmd.hasOption("endDate"))
            endDate = getValidLocalDate(cmd.getOptionValue("endDate"), "endDate");

        if (startDate.isAfter(endDate))
            throw new ParseException("startDate cannot be after the specified endDate.");

        if (cmd.hasOption("lifo"))
            issueOrder = "DESC";

        if (cmd.hasOption("csvFormat"))
            csvFormat = getValidCSVFormat(cmd.getOptionValue("csvFormat"));

        if (cmd.hasOption("issueLimit"))
            issueLimit = getValidIssueLimit(cmd.getOptionValue("issueLimit"));
    }

    public Options getOptions() {
        return options;
    }

    public List<String> getUsernames() {
        return usernames;
    }

    public LocalDate getStartDate() {
        return startDate;
    }

    public LocalDate getEndDate() {
        return endDate;
    }

    public String getIssueOrder() {
        return issueOrder;
    }

    public CSVFormat getCSVFormat() {
        return csvFormat;
    }

    public int getIssueLimit() {
        return issueLimit;
    }

    public Map<String, String> getDomains() {
        return domains;
    }

    private LocalDate getValidLocalDate(String date, String optionName) throws ParseException {
        try {
            LocalDate localDate = LocalDate.parse(date);
            if (optionName.equals("startDate") && localDate.isAfter(LocalDate.now()))
                throw new ParseException("startDate cannot be in the future.");
            return localDate;
        } catch (DateTimeParseException e) {
            throw new ParseException("Invalid " + optionName + ". Date format must be YYYY-MM-DD.");
        }
    }

    private List<String> getValidUsernames(CommandLine cmd) throws ParseException {
        boolean userFileSet = cmd.hasOption("userFile");
        boolean usernamesSet = cmd.hasOption("usernames");
        if (!userFileSet && !usernamesSet)
            throw new ParseException("You must specify either the usernames or userFile option");

        if (userFileSet && usernamesSet)
            throw new ParseException("The usernames and userFile cannot be set at the same time");

        if (usernamesSet) {
            String[] values = cmd.getOptionValues("usernames");
            return Arrays.asList(values);
        }

        String url = cmd.getOptionValue("userFile");
        if (!new File(url).exists())
            throw new ParseException("The specified file <" + url + "> does not exist");

        List<String> users;
        try {
            users = Files.readAllLines(Paths.get(url));
        } catch (IOException e) {
            throw new ParseException("The specified file <" + url + "> cannot be opened");
        }
        return users;
    }

    private Map<String, String> getValidDomains(CommandLine cmd) throws ParseException {
        Properties properties = new Properties();
        if (cmd.hasOption("domainFile")) {
            String url = cmd.getOptionValue("domainFile");
            File file = new File(url);
            if (!file.exists())
                throw new ParseException("The specified file does not exist");

            try (InputStream in = new FileInputStream(file)) {
                properties.load(in);
            } catch (IOException e) {
                throw new ParseException(e.getMessage() + ": " + e.getCause());
            }

            if (properties.isEmpty())
                throw new ParseException("The specified file does not contain any domain pairs");
        } else {
            try (InputStream in = JiraReporter.class.getClassLoader().getResourceAsStream("domains")) {
                properties.load(in);
            } catch (IOException e) {
                throw new ParseException("Default domains file could not be read: " + e);
            }
        }
        @SuppressWarnings("unchecked")
        Map<String, String> map = (Map) properties;
        return map;
    }

    private CSVFormat getValidCSVFormat(String specifiedFormat) throws ParseException {
        CSVFormat format = validCSVFormats.get(specifiedFormat.toLowerCase());

        if (format == null)
            throw new ParseException("Invalid CSV format. Valid options are " + validCSVFormats.entrySet());
        return format;
    }

    private int getValidIssueLimit(String issueLimit) throws ParseException {
        try {
            int limit = new Integer(issueLimit);
            if (limit > 0)
                return limit;
        } catch (NumberFormatException e) {
        }
        throw new ParseException("Invalid issueLimit value: " + issueLimit + ". A positive integer is expected");
    }

    private void addOptions() {
        addUsernameOptions();
        addDateOptions();
        addBooleanFlags();
        addCSVTypeOption();
        addIssueLimitOption();
        addDomainFileOption();
    }

    private void addUsernameOptions() {
        options.addOption(Option.builder("u").argName("usernames").longOpt("usernames")
                .desc("Pass the JIRA usernames to be searched as command line options.").required(false)
                .numberOfArgs(Option.UNLIMITED_VALUES).valueSeparator(' ').build());

        options.addOption(Option.builder("uf").argName("userFile").longOpt("userFile")
                .desc("Read JIRA usernames from the specified file.").required(false).numberOfArgs(1).build());
    }

    private void addDateOptions() {
        options.addOption(Option.builder("s").argName("startDate").longOpt("startDate")
                .desc("The date from which JIRAs are returned.").required(false).numberOfArgs(1).build());

        options.addOption(Option.builder("e").argName("endDate").longOpt("endDate")
                .desc("The date of the most recent JIRA to be returned.").required(false).numberOfArgs(1).build());
    }

    private void addBooleanFlags() {
        options.addOption(new Option("lifo", "JIRA issues are output from the most recently updated issue."));
        options.addOption(new Option("h", "help", false, "Display this help and exit."));
    }

    private void addCSVTypeOption() {
        options.addOption(Option.builder("c").argName("csvFormat").longOpt("csvFormat")
                .desc("The format of the created CSV files. Valid options are " + validCSVFormats.keySet())
                .required(false).numberOfArgs(1).build());
    }

    private void addIssueLimitOption() {
        options.addOption(Option.builder("l").argName("issueLimit").longOpt("issueLimit")
                .desc("The maximum number of JIRA issues that will be returned for each domain.").required(false)
                .numberOfArgs(1).build());
    }

    private void addDomainFileOption() {
        options.addOption(Option.builder("d").argName("domainFile").longOpt("domainFile")
                .desc("A properties file which contains a key name and url for each of the domains to be searched.")
                .required(false).numberOfArgs(1).build());
    }
}