org.pz.platypus.CommandLineArgs.java Source code

Java tutorial

Introduction

Here is the source code for org.pz.platypus.CommandLineArgs.java

Source

/***
 *  Platypus: Page Layout and Typesetting Software (free at platypus.pz.org)
 *
 *  Platypus is (c) Copyright 2006-09 Pacific Data Works LLC. All Rights Reserved.
 *  Licensed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0.html)
 */
package org.pz.platypus;

import org.pz.platypus.exceptions.HelpMessagePrinted;
import org.pz.platypus.exceptions.StopExecutionException;
import org.apache.commons.cli.*;

import java.util.ArrayList;
import java.util.List;

/**
 * Uses apache commons CLI to parse the command line.
 *
 * @author alb
 * @author atul - moved the command line parsing to apache commons CLI
 */
public class CommandLineArgs {

    @SuppressWarnings("unchecked")

    private Options options = new Options();
    private CommandLineParser parser = new GnuParser();
    private CommandLine line;

    /**
     * Configures the CLI parser with a list of valid Options.
     * And parses the command line args.
     *
     * @param args command-line args passed to main()
     */
    public CommandLineArgs(final String[] args) {
        initOptions();

        if (args == null || args.length == 0) {
            parseArguments(new String[] { "-help" });
        } else {
            parseArguments(args);
        }
    }

    private void parseArguments(String[] args) {
        try {
            String[] preprocessedArgs = CommandLineArgs.preProcessCommandLine(args);
            line = parser.parse(options, preprocessedArgs);
        } catch (ParseException e) {
            System.err.println(e.getLocalizedMessage());
            throw new StopExecutionException(e.getLocalizedMessage());
        }
    }

    private void initOptions() {
        Option[] optsArr = getSupportedOptions();

        for (Option opt : optsArr) {
            options.addOption(opt);
        }
    }

    /**
     * All valid supported options are here.
     * @return a list of such options.
     */
    private Option[] getSupportedOptions() {
        Option inputFile = OptionBuilder.withArgName("file").hasArg().withDescription("input file")
                .create("inputFile");
        Option outputFile = OptionBuilder.withArgName("file").hasArg().withDescription("output file")
                .create("outputFile");
        Option configFile = OptionBuilder.withArgName("configfile").hasArg().withDescription("config file")
                .create("config");
        Option format = OptionBuilder.withArgName("formatname").hasArg().withDescription("output format")
                .create("format");

        Option verbose = new Option("verbose", "verbose help");
        Option vverbose = new Option("vverbose", "very verbose help");
        Option fontlist = new Option("fontlist", "list of fonts");
        Option help = new Option("help", "print this message");

        return new Option[] { inputFile, outputFile, configFile, format, verbose, vverbose, fontlist, help };
    }

    /**
     * Creates a single string from all the args specified by the user on the command line
     *
     * @param args the user-specified args
     * @return the command line as one string. If there were no args, a single space is returned.
     */
    public String createCommandLine(final String[] args) {

        StringBuffer sb = new StringBuffer(args.length * 15);

        if (args.length == 0) {
            return (" ");
        }

        for (String arg : args) {
            sb.append(arg);
            sb.append(' ');
        }

        return (sb.toString().trim());
    }

    /**
     * Determines whether an item was specified on the command-line. And if so,
     * what any argument for it is.
     *
     * @param argToFind argument to lookup
     * @return null if the item was not specified; "" if the item was specified but had no argument,
     *         and the argument if item was specified and has an argument.
     */
    public String lookup(final String argToFind) {
        if (argToFind == null) {
            return (null);
        }
        if (shouldGenerateOutputOption(argToFind)) {
            return generateOutputFile();
        }
        if (!line.hasOption(argToFind))
            return null;
        String opt = line.getOptionValue(argToFind);
        if (opt == null)
            return "true";
        return opt;
    }

    private String generateOutputFile() {
        String inputFile = line.getOptionValue("inputFile");
        String ret = getNameMinusExtension(inputFile);
        return appendFormatExtension(ret);
    }

    private String appendFormatExtension(String ret) {
        final String formatExt = getFormatExtension();
        return ret + "." + formatExt;
    }

    private String getFormatExtension() {
        String formatExtension = "pdf";
        if (line.hasOption("format")) {
            formatExtension = line.getOptionValue("format");
        }
        return formatExtension;
    }

    private String getNameMinusExtension(String str) {
        String ret = str;
        StringBuilder fileBuilder = new StringBuilder(str);
        int lastDotAt = fileBuilder.lastIndexOf(".");
        if (lastDotAt != -1) {
            ret = ret.substring(0, lastDotAt);
        }
        return ret;
    }

    private boolean shouldGenerateOutputOption(final String argStr) {
        if (argStr.equals("outputFile")) {
            if (!line.hasOption("outputFile")) {
                if (line.hasOption("inputFile")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Processes some command-line options
     *
     * @param gdd GDD that will hold the state of some switches (such as verbosity)
     * @throws HelpMessagePrinted if no command-line args specified
     */ //curr: improve method name
    public void process(GDD gdd) throws HelpMessagePrinted {
        showUsageIfZeroArgs(gdd);

        // Note: the -config option is entirely handled in Platypus.processConfigFile(), not here.

        processHelpOption(gdd);

        processVerboseOption(gdd);

        processVeryVerboseOption(gdd);

        processFontListOption(gdd);
    }

    private void processFontListOption(GDD gdd) throws HelpMessagePrinted {
        if (line.hasOption("fontlist")) {
            TypefaceMap tfm = new TypefaceMap(gdd);
            tfm.loadFamilies();
            tfm.writeMapToFile(gdd.getHomeDirectory() + "config/fontlist.txt");
            throw new HelpMessagePrinted("OK"); //todo: fix this way of escaping processing.
        }
    }

    private void processVeryVerboseOption(GDD gdd) {
        if (line.hasOption("vverbose")) {
            gdd.setClVVerbose(true);
        }
    }

    private void processVerboseOption(GDD gdd) {
        if (line.hasOption("verbose")) {
            gdd.setClVerbose(true);
        }
    }

    private void processHelpOption(GDD gdd) throws HelpMessagePrinted {
        if (line.hasOption("help")) {
            Platypus.showUsage(gdd);
            // this exception exits Platypus without further processing and w/out
            // an error message. Technically, this is not an exception, but it's
            // the cleanest way of closing down from here.
            throw new HelpMessagePrinted("OK");
        }
    }

    private void showUsageIfZeroArgs(GDD gdd) {
        if (line.getOptions().length == 0) {
            Platypus.showUsage(gdd);
            System.err.println(gdd.getLit("PLEASE_RERUN_WITH_FILENAMES"));
            throw new UnsupportedOperationException("ERR"); //curr: delete ERR
        } //curr: combine with graf below, using same exit exception.
    }

    /**
     * Injects the -inputFile and -outputFile options before correct barewords
     * The algorithm first checks if we have encountered an option with zero or one argument.
     * If so, it copies the elements to the result array.
     * Else, it injects -inputFile before the first bareword
     * and -outputFile after the second bareword.
     *
     * @param args
     * @return correctly injects -inputFile and -outputFile before the barewords...
     */

    public static String[] preProcessCommandLine(final String[] args) {
        final List<String> newArgs = new ArrayList<String>();
        boolean inOption = false;
        boolean inputSeen = false;

        for (String arg : args) {
            if (inOption == false) {
                if (isArgAnOption(arg)) {
                    if (doesOptionHaveArg(arg)) {
                        inOption = true;
                    }
                } else if (inputSeen == false) { // we have encountered a bareword
                    newArgs.add("-inputFile"); // first bareword is taken as input file
                    inputSeen = true;
                } else if (inputSeen == true) {
                    newArgs.add("-outputFile"); // next bareword is output file
                    inputSeen = false;
                }
            } else if (inOption == true) {
                inOption = false; // this bareword is an option argument
            }
            newArgs.add(arg);
        }
        return newArgs.toArray(new String[0]); // java collections idiom for converting to an array :-)
    }

    private static boolean doesOptionHaveArg(String arg) {
        return arg.equals("-config") || arg.equals("-format");

    }

    private static boolean isArgAnOption(String arg) {
        if (!arg.isEmpty()) {
            if (arg.charAt(0) == '-') {
                return true;
            }
        }
        return false;
    }
}