de.uniwue.info2.main.CommandLineInterpreter.java Source code

Java tutorial

Introduction

Here is the source code for de.uniwue.info2.main.CommandLineInterpreter.java

Source

/*
 *    IaTestGen - Interval arithmetic test generator
 *    Copyright 2013
 *
 *    Marco Nehmeier (nehmeier@informatik.uni-wuerzburg.de)
 *    Institute of Computer Science,
 *    University of Wuerzburg, Germany
 *
 *    Michael Jedich (m.jedich@gmail.com)
 *    University of Wuerzburg, Germany
 *
 *
 *    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 de.uniwue.info2.main;

import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.apache.commons.cli.BasicParser;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang.StringUtils;

import de.uniwue.info2.generator.ArithmeticLibrarySpecification;
import de.uniwue.info2.generator.LanguageFactory;
import de.uniwue.info2.generator.LanguageSpecification;
import de.uniwue.info2.generator.TestcaseGenerator;
import de.uniwue.info2.generator.UnitTestLibrarySpecification;

/**
 * Main class with Commandline-Interpreter.
 * <p>
 * User has to specify location of a Domain-Specific-Language-File, output-folder
 *
 * @author Michael Jedich
 *
 */
public class CommandLineInterpreter {

    // options and associated information
    private static final String GENERATING_DIALOG = "Generating test-file for target-language: ";

    private static final String HELP_OPTION = "help";
    private static final String HELP_OPTION_SHORT = "h";
    private static final String HELP_DESCRIPTION = "Shows this infopage.";

    private static final String HELP2_OPTION = "extended_help";
    private static final String HELP2_OPTION_SHORT = "H";
    private static final String HELP2_DESCRIPTION = "Shows a detailed infopage.";

    private static final String DSL_OPTION = "dsl";
    private static final String DSL_OPTION_SHORT = "i";
    private static final String DSL_DESCRIPTION = "Domain Specific Language.";
    private static final String DSL_ARGUMENT = "dsl-file";

    private static final String OUTPUT_OPTION = "output";
    private static final String OUTPUT_OPTION_SHORT = "o";
    private static final String OUTPUT_DESCRIPTION = "Folder for generated unit test-files.\n";
    private static final String OUTPUT_ARGUMENT = "output-dir";

    private static final String OPTIONAL_OPTION = "optional";
    private static final String OPTIONAL_OPTION_SHORT = "p";
    private static final String OPTIONAL_DESCRIPTION = "Generate test-functions for operations marked as optional.\n";

    private static final String OPTIONAL_FUNCTIONS_CONFIG_OPTION = "optional_config";
    private static final String OPTIONAL_FUNCTIONS_CONFIG_SHORT = "P";
    private static final String OPTIONAL_FUNCTIONS_CONFIG_DESCRIPTION = "Specify exceptions for optional operations.";
    private static final String OPTIONAL_FUNCTIONS_CONFIG_ARGUMENT = "config-file";

    private static final String BIG_ENDIAN_OPTION = "big_endian";
    private static final String BIG_ENDIAN_OPTION_SHORT = "q";
    private static final String BIG_ENDIAN_DESCRIPTION = "Use big endian to format hexadecimal.\n";

    private static final String LITTLE_ENDIAN_OPTION = "little_endian";
    private static final String LITTLE_ENDIAN_OPTION_SHORT = "r";
    private static final String LITTLE_ENDIAN_DESCRIPTION = "Use little endian to format hexadecimal.\n";

    private static final String LANGUAGE_SPECIFICATION = "Generate unit-tests for all available libraries in ";

    // name of program/jar-file
    private static final String CLASS = "ia_gen.jar";

    private static final String SEPERATOR = StringUtils.repeat("*", 74);
    private static final DecimalFormat INDEX = new DecimalFormat("00");

    private static final String HEADER = "--by default, test-files "
            + "are generated for all available language specs.--\n";

    /**
     * Prints Help for Commandline-Interpreter.
     *
     * @param options
     *         possible options
     */
    private static void printHelp(Options options) {
        HelpFormatter helpFormater = new HelpFormatter();
        helpFormater.printHelp(CLASS, "\n" + SEPERATOR + "\n" + HEADER + SEPERATOR + "\n", options,
                SEPERATOR + "\n", true);
    }

    /**
     * Prints Help for Commandline-Interpreter.
     *
     * @param options
     *         possible options
     */
    private static void printExtendedHelp(Options options) {
        HelpFormatter helpFormater = new HelpFormatter();
        helpFormater.printHelp(CLASS, "\n" + SEPERATOR + "\n" + HEADER + SEPERATOR + "\n", options,
                SEPERATOR + "\n", true);
    }

    @SuppressWarnings("static-access")
    public static void main(String[] args) {

        /*-------------------------------------------------------- */
        /*---------------SETTING TARGET LANGUAGE------------------ */
        /*-------------------------------------------------------- */
        LanguageFactory languageFactory = new LanguageFactory();

        CommandLine line = null;
        CommandLineParser parser = new BasicParser();
        Options options = new Options();
        // options to display in the help page
        Options options_short = new Options();

        // add help option
        Option help_option = new Option(HELP_OPTION_SHORT, HELP_OPTION, false, HELP_DESCRIPTION);
        options.addOption(help_option);
        options_short.addOption(help_option);
        // add extended help option
        Option help2_option = new Option(HELP2_OPTION_SHORT, HELP2_OPTION, false, HELP2_DESCRIPTION);
        options.addOption(help2_option);
        options_short.addOption(help2_option);
        // add optional operations option
        options.addOption(new Option(OPTIONAL_OPTION_SHORT, OPTIONAL_OPTION, false, OPTIONAL_DESCRIPTION));
        options.addOption(new Option(BIG_ENDIAN_OPTION_SHORT, BIG_ENDIAN_OPTION, false, BIG_ENDIAN_DESCRIPTION));
        options.addOption(
                new Option(LITTLE_ENDIAN_OPTION_SHORT, LITTLE_ENDIAN_OPTION, false, LITTLE_ENDIAN_DESCRIPTION));
        // add optional operations config option
        options.addOption(OptionBuilder.withLongOpt(OPTIONAL_FUNCTIONS_CONFIG_OPTION)
                .withArgName(OPTIONAL_FUNCTIONS_CONFIG_ARGUMENT)
                .withDescription(OPTIONAL_FUNCTIONS_CONFIG_DESCRIPTION).hasArg()
                .create(OPTIONAL_FUNCTIONS_CONFIG_SHORT));
        // add dsl option
        Option dsl_option = OptionBuilder.withLongOpt(DSL_OPTION).withArgName(DSL_ARGUMENT)
                .withDescription(DSL_DESCRIPTION).hasArg().isRequired().create(DSL_OPTION_SHORT);
        options.addOption(dsl_option);
        options_short.addOption(dsl_option);
        // add output-folder option
        Option output_option = OptionBuilder.withLongOpt(OUTPUT_OPTION).isRequired().withArgName(OUTPUT_ARGUMENT)
                .withDescription(OUTPUT_DESCRIPTION).hasArg().create(OUTPUT_OPTION_SHORT);
        options.addOption(output_option);
        options_short.addOption(output_option);

        // count possible language-specifications
        short optionCounter = 1;

        // get all possible language-specifications from language-factory and iterate through them
        List<LanguageSpecification> lSpecs = languageFactory.getAvailableLanguageSpecifications_();

        for (LanguageSpecification lSpec : lSpecs) {
            // get all possible unit-specifications for current language and iterate through them
            List<UnitTestLibrarySpecification> uSpecs = languageFactory
                    .getAvailableUnitTestLibraries_(lSpec.getOptionName());
            String languageDescriptionAll = LANGUAGE_SPECIFICATION + lSpec.getLanguageName();
            String languageCounter = "s" + INDEX.format(optionCounter++);

            for (UnitTestLibrarySpecification uSpec : uSpecs) {
                // get all possible arithmetic-library-specifications for current language and iterate through
                // them
                List<ArithmeticLibrarySpecification> aSpecs = languageFactory
                        .getAvailableArithmeticLibraries_(lSpec.getOptionName());
                for (ArithmeticLibrarySpecification aSpec : aSpecs) {
                    String languageDescription = "Generate unit-test for " + lSpec.getLanguageName() + "\n*["
                            + uSpec.getLibraryName() + " - " + uSpec.getVersion() + "]\n*[" + aSpec.getLibraryName()
                            + " - " + aSpec.getVersion() + "]";

                    // if there is more than one option, generate suitable option-names and add them all to
                    // commandline options
                    if (uSpecs.size() > 1 || aSpecs.size() > 1) {
                        options.addOption(OptionBuilder
                                .withLongOpt(lSpec.getOptionName() + "_" + uSpec.getOptionName() + "_"
                                        + aSpec.getOptionName())
                                .withDescription(languageDescription).hasArg(false)
                                .create("s" + INDEX.format(optionCounter++)));
                    } else {
                        // if there is only one option, use language-name as option-name
                        languageDescriptionAll = languageDescription;
                    }
                }
                // add specifications to options
                options.addOption(OptionBuilder.withLongOpt(lSpec.getOptionName())
                        .withDescription(languageDescriptionAll).hasArg(false).create(languageCounter));
            }
        }

        /*-------------------------------------------------------- */
        /*-------------------PARSE USER INPUT--------------------- */
        /*-------------------------------------------------------- */
        try {
            // manual search for help-arguments
            for (String arg : args) {
                arg = arg.trim().replace("-", "");
                if (arg.equals(HELP_OPTION_SHORT) || arg.equals(HELP_OPTION)) {
                    printHelp(options_short);
                    return;
                }
                if (arg.equals(HELP2_OPTION_SHORT) || arg.equals(HELP2_OPTION)) {
                    printExtendedHelp(options);
                    return;
                }
            }

            // parse arguments   
            line = parser.parse(options, args);

            File dsl_file = null;
            File output_folder = null;
            File optional_config = null;
            Properties optional_operations = null;
            Boolean optional = false;
            Boolean little_endian = null;
            ArrayList<String> optional_exceptions = new ArrayList<String>();

            // if help-option found print help
            if (line.hasOption(HELP2_OPTION_SHORT) || args.length == 0) {
                printExtendedHelp(options);
                return;
            }

            // if help-option found print help
            if (line.hasOption(HELP_OPTION_SHORT) || args.length == 0) {
                System.out.println("\n");
                printHelp(options_short);
                return;
            }

            if (line.hasOption(OPTIONAL_OPTION_SHORT)) {
                optional = true;
            }

            if (line.hasOption(LITTLE_ENDIAN_OPTION)) {
                little_endian = true;
            }

            if (line.hasOption(BIG_ENDIAN_OPTION)) {
                little_endian = false;
            }

            // if dsl-option found, check if file exists and is readable
            // print help if error occurs
            if (line.hasOption(DSL_OPTION_SHORT)) {
                dsl_file = new File(line.getOptionValue(DSL_OPTION_SHORT));
                if (!dsl_file.exists()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - DSL-file doesn't exist:\n" + dsl_file
                            + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                } else if (dsl_file.isDirectory()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - DSL-file is a directory:\n" + dsl_file
                            + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                } else if (!dsl_file.canRead()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - Need read-permission for DSL-file:\n"
                            + dsl_file + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                }
            }

            // if output-option found, check if folder exists and if write-permission was granted
            // print help if error occurs
            if (line.hasOption(OUTPUT_OPTION_SHORT)) {
                output_folder = new File(line.getOptionValue(OUTPUT_OPTION_SHORT));
                if (!output_folder.exists()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - Output-folder doesn't exist:\n"
                            + output_folder + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                } else if (!output_folder.isDirectory()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - Output-folder is not a directory:\n"
                            + output_folder + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                } else if (!output_folder.canWrite() || !output_folder.canRead()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - Missing permissions for output-folder:\n"
                            + output_folder + "\n" + SEPERATOR + "\n");
                    printHelp(options_short);
                    return;
                }
            }

            if (line.hasOption(OPTIONAL_FUNCTIONS_CONFIG_SHORT)) {
                optional_config = new File(line.getOptionValue(OPTIONAL_FUNCTIONS_CONFIG_OPTION));
                if (!dsl_file.exists()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - config-file doesn't exist:\n" + dsl_file
                            + "\n" + SEPERATOR + "\n");
                    printExtendedHelp(options);
                    return;
                } else if (dsl_file.isDirectory()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - config-file is a directory:\n" + dsl_file
                            + "\n" + SEPERATOR + "\n");
                    printExtendedHelp(options);
                    return;
                } else if (!dsl_file.canRead()) {
                    System.err.println("\n" + SEPERATOR + "\n" + "ERROR - Need read-permission for config-file:\n"
                            + dsl_file + "\n" + SEPERATOR + "\n");
                    printExtendedHelp(options);
                    return;
                }
            }

            if (optional_config != null) {
                optional_operations = new Properties();
                BufferedInputStream stream = new BufferedInputStream(new FileInputStream(optional_config));
                optional_operations.load(stream);
                stream.close();
                String optional_prop = optional_operations.getProperty("GENERATE_OPTIONAL");
                if (optional_prop != null) {
                    if (optional_prop.trim().toLowerCase().equals("true")) {
                        optional = true;
                    } else if (optional_prop.trim().toLowerCase().equals("false")) {
                        optional = false;
                    } else if (!optional_prop.trim().isEmpty()) {
                        System.err.println("\n" + SEPERATOR + "\n"
                                + "ERROR - Syntax incorrect in config-file:\nUse \"true\" or \"false\" for \"GENERATE_OPTIONAL\"\n"
                                + SEPERATOR + "\n");
                        printExtendedHelp(options);
                        return;
                    }
                }
                String exceptions = optional_operations.getProperty("EXCLUSIONS");
                if (exceptions != null) {
                    for (String exc : optional_operations.getProperty("EXCLUSIONS").split(";")) {
                        optional_exceptions.add(exc.trim());
                    }
                }
            }

            /*-------------------------------------------------------- */
            /*-------------------START GENERATING--------------------- */
            /*-------------------------------------------------------- */

            // instantiate generator for unit-tests
            TestcaseGenerator mainGenerator = new TestcaseGenerator(dsl_file, output_folder);

            boolean overrideDefaultSpecs = false;

            // check if user input contains a language-specifications
            // if user specified language, set overrideDefaultSpecs to true, so that only given specifications
            // are used
            for (int i = 1; i <= optionCounter; i++) {
                String opt = "s" + INDEX.format(i);
                if (line.hasOption(opt)) {
                    LanguageSpecification targetSpecification = languageFactory
                            .getLanguageSpecification(options.getOption(opt).getLongOpt());
                    String output = (GENERATING_DIALOG + targetSpecification.getLanguageName());

                    // finally generate unit-test for current language-specification
                    boolean successful = mainGenerator.generateUnitTest(targetSpecification, optional,
                            optional_exceptions, little_endian);

                    if (successful) {
                        System.out.println(output + "\n--> Successfully generated.");
                    } else {
                        System.err.println(output + "\n--> ERROR - see logfile");
                    }
                    overrideDefaultSpecs = true;
                }
            }

            // skip, if user already defined one language-specification
            // if user did not define language-specification, generate unit-tests for all
            // possible language-specifications (default)
            if (!overrideDefaultSpecs) {
                for (int i = 0; i < lSpecs.size(); i++) {
                    LanguageSpecification specification = languageFactory
                            .getLanguageSpecification(lSpecs.get(i).getOptionName());

                    String output = INDEX.format(i + 1) + " - " + GENERATING_DIALOG
                            + specification.getLanguageName();

                    // finally generate unit-test for current language-specification
                    boolean successful = mainGenerator.generateUnitTest(specification, optional,
                            optional_exceptions, little_endian);

                    if (successful) {
                        System.out.println(output + "\n--> Successfully generated.");
                    } else {
                        System.err.println(output + "\n--> ERROR - see logfile");
                    }
                }
            }

        } catch (ParseException | IOException p) {
            System.err.println("\n" + SEPERATOR + "\n" + "ERROR - WRONG ARGUMENTS:\n" + p.getMessage() + "\n"
                    + SEPERATOR + "\n");
            printHelp(options_short);
            System.out.println("\n");
        }
    }
}