package org.easyb; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.GnuParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.easyb.report.HtmlReportWriter; import org.easyb.report.JUnitReportWriter; import org.easyb.report.PrettyPrintReportWriter; import org.easyb.report.ReportWriter; import org.easyb.report.TxtSpecificationReportWriter; import org.easyb.report.TxtStoryReportWriter; import org.easyb.report.XmlReportWriter; import org.easyb.util.BehaviorFileToPathsBuilder; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static org.apache.commons.cli.OptionBuilder.withArgName; import static org.apache.commons.cli.OptionBuilder.withDescription; public class ConsoleConfigurator { private static final String TXT_SPECIFICATION = "txtspecification"; private static final String TXT_STORY = "txtstory"; private static final String XML_EASYB = "xml"; private static final String HTML_EASYB = "html"; private static final String JUNIT_EASYB = "junit"; private static final String JUNIT_ROOT_PACKAGE = "root"; private static final String EXCEPTION_STACK = "e"; private static final String FILTER_EXCEPTION_STACK = "ef"; private static final String REPORT_TEMPLATE = "template"; private static final String DEFAULT_JUNIT_ROOT_PACKAGE = "behavior"; private static final String NOEXECUTE_STORY_DESCRIPTION = "creates report without running any stories"; private static final String NOEXECUTE_STORY = "ne"; private static final String PRETTY_PRINT = "prettyprint"; private static final String HTML_DESCRIPTION = "create an easyb report in html format"; private static final String XML_DESCRIPTION = "create an easyb report in xml format"; private static final String JUNIT_DESCRIPTION = "create an easyb report in JUnit-compatible xml format. Reports will be created in the specified directory."; private static final String JUNIT_ROOT_DESCRIPTION = "Reports are created in this package by default. This makes the JUnit reports easier to fit into other generated JUnit reports."; private static final String STORY_DESCRIPTION = "create a story report"; private static final String BEHAVIOR_DESRCIPTION = "create a behavior report"; private static final String STACKTRACE_DESCRIPTION = "prints stacktrace information"; private static final String FILTERED_STACKTRACE_DESCRIPTION = "prints filtered stacktrace information"; private static final String PARALLEL = "parallel"; private static final String PARALLEL_DESCRIPTION = "run stories and specifications in parallel"; private static final String PRETTY_PRINT_DESCRIPTION = "prints colored behaviors"; private static final String BEHAVIOR_FILE = "f"; private static final String BEHAVIOR_FILE_DESCRIPTION = "run behaviors listed in a file"; private static final String FAILURE_BEHAVIOR_FILE = "outfail"; private static final String FAILURE_BEHAVIOR_FILE_DESCRIPTION = "caputure failed behaviors in a file " + "(for processing at a later point -- see the -f option)"; private static final String REPORT_TEMPLATE_DESCRIPTION = "the report template to use for the html output"; private static final String TAG = "tags"; private static final String TAG_DESCRIPTION = "run behaviors with tag marker"; public Configuration configure(final String[] args) { final Options options = getOptionsForMain(); try { CommandLine commandLine = getCommandLineForMain(args, options); validateArguments(commandLine); String extendedStoryClzz = getExtendedStoryClass(commandLine); String[] paths = convertArgsToPaths(commandLine); return new Configuration(paths, getConfiguredReports(commandLine), commandLine.hasOption(EXCEPTION_STACK), commandLine.hasOption(FILTER_EXCEPTION_STACK), extendedStoryClzz, isParallel(commandLine), isFailureFile(commandLine), commandLine.getOptionValue(FAILURE_BEHAVIOR_FILE), getTags(commandLine), getRootPackage(commandLine)); } catch (IllegalArgumentException iae) { System.out.println(iae.getMessage()); handleHelpForMain(options); } catch (ParseException pe) { System.out.println(pe.getMessage()); handleHelpForMain(options); } return null; } private String getRootPackage(CommandLine commandLine) { if (commandLine.hasOption(JUNIT_ROOT_PACKAGE)) { return commandLine.getOptionValue(JUNIT_ROOT_PACKAGE); } else { return DEFAULT_JUNIT_ROOT_PACKAGE; } } private String[] getTags(CommandLine cmdLine) { if (cmdLine.hasOption(TAG)) { return cmdLine.getOptionValue(TAG).split(","); } else { return null; } } /** * @param cmdLine * @return */ private String[] convertArgsToPaths(CommandLine cmdLine) { if (cmdLine.hasOption(BEHAVIOR_FILE)) { String file = cmdLine.getOptionValue(BEHAVIOR_FILE); BehaviorFileToPathsBuilder builder = new BehaviorFileToPathsBuilder(); return builder.buildPaths(((file != null) ? file : "failure-files.txt"), cmdLine.getArgs()); } else { return cmdLine.getArgs(); } } private String getExtendedStoryClass(CommandLine commandLine) { String extendedStoryClzz = null; if (commandLine.hasOption(NOEXECUTE_STORY)) { extendedStoryClzz = "NonExecutableStory"; } return extendedStoryClzz; } private boolean isFailureFile(CommandLine cmdLine) { return cmdLine.hasOption(FAILURE_BEHAVIOR_FILE); } private boolean isParallel(CommandLine commandLine) { return commandLine.hasOption(PARALLEL); } /** * @param args command line arguments passed into main * @param options options that are available to this specification runner * @return representation of command line arguments passed in that match the available options * @throws org.apache.commons.cli.ParseException * if there are any problems encountered while parsing the command line tokens */ private static CommandLine getCommandLineForMain(final String[] args, final Options options) throws ParseException { final CommandLineParser commandLineParser = new GnuParser(); return commandLineParser.parse(options, args); } private static void validateArguments(final CommandLine commandLine) throws IllegalArgumentException { if (commandLine.getArgs().length == 0) { if (!commandLine.hasOption(BEHAVIOR_FILE)) { throw new IllegalArgumentException("Required arguments missing. At a minimum, " + "you must provide a path to a behavior for easyb to run or provide the -f flag pointing to" + " a file containing behaviors."); } } if(commandLine.hasOption(REPORT_TEMPLATE)) { if(!new File(commandLine.getOptionValue(REPORT_TEMPLATE)).exists()) { throw new IllegalArgumentException("The specified report template [" + commandLine.getOptionValue(REPORT_TEMPLATE) + "] does not exist."); } } } /** * @param line command line to scan for reports * @return immutable list of ReportWriter objects */ private static List<ReportWriter> getConfiguredReports(final CommandLine line) { List<ReportWriter> configuredReports = new ArrayList<ReportWriter>(); if (line.hasOption(TXT_STORY)) { configuredReports.add(new TxtStoryReportWriter(line.getOptionValue(TXT_STORY))); } if (line.hasOption(TXT_SPECIFICATION)) { configuredReports.add(new TxtSpecificationReportWriter(line.getOptionValue(TXT_SPECIFICATION))); } if (line.hasOption(XML_EASYB)) { configuredReports.add(new XmlReportWriter(line.getOptionValue(XML_EASYB))); } if (line.hasOption(HTML_EASYB)) { configuredReports.add(new HtmlReportWriter(line.getOptionValue(REPORT_TEMPLATE), line.getOptionValue(HTML_EASYB))); } if (line.hasOption(PRETTY_PRINT)) { configuredReports.add(new PrettyPrintReportWriter()); } if (line.hasOption(JUNIT_EASYB)) { configuredReports.add(new JUnitReportWriter(line.getOptionValue(JUNIT_EASYB))); } return Collections.unmodifiableList(configuredReports); } /** * @param options options that are available to this specification runner */ private static void handleHelpForMain(final Options options) { new HelpFormatter().printHelp("BehaviorRunner my/path/to/MyFile.story or provide the -f flag", options); } /** * @return representation of a collection of Option objects, which describe the possible options for a command-line. */ @SuppressWarnings({"static-access", "AccessStaticViaInstance"}) private static Options getOptionsForMain() { final Options options = new Options(); options.addOption(withDescription(HTML_DESCRIPTION).hasOptionalArg().create(HTML_EASYB)); options.addOption(withDescription(XML_DESCRIPTION).hasOptionalArg().create(XML_EASYB)); options.addOption(withDescription(JUNIT_DESCRIPTION).hasOptionalArg().create(JUNIT_EASYB)); options.addOption(withDescription(STORY_DESCRIPTION).hasOptionalArg().create(TXT_STORY)); options.addOption(withDescription(BEHAVIOR_DESRCIPTION).hasOptionalArg().create(TXT_SPECIFICATION)); options.addOption(withDescription(STACKTRACE_DESCRIPTION).hasOptionalArg().create(EXCEPTION_STACK)); options.addOption(withDescription(FILTERED_STACKTRACE_DESCRIPTION).hasOptionalArg().create(FILTER_EXCEPTION_STACK)); options.addOption(withArgName(NOEXECUTE_STORY).withDescription(NOEXECUTE_STORY_DESCRIPTION).create(NOEXECUTE_STORY)); options.addOption(withDescription(PRETTY_PRINT_DESCRIPTION).hasOptionalArg().create(PRETTY_PRINT)); options.addOption(withArgName(PARALLEL).withDescription(PARALLEL_DESCRIPTION).create(PARALLEL)); options.addOption(withDescription(BEHAVIOR_FILE_DESCRIPTION).hasOptionalArg().create(BEHAVIOR_FILE)); options.addOption(withDescription(FAILURE_BEHAVIOR_FILE_DESCRIPTION).hasOptionalArg().create(FAILURE_BEHAVIOR_FILE)); options.addOption(withDescription(TAG_DESCRIPTION).hasOptionalArg().create(TAG)); options.addOption(withDescription(JUNIT_ROOT_DESCRIPTION).hasOptionalArg().create(JUNIT_ROOT_PACKAGE)); options.addOption(withDescription(REPORT_TEMPLATE_DESCRIPTION).hasArg().create(REPORT_TEMPLATE)); return options; } }