cc.redpen.Main.java Source code

Java tutorial

Introduction

Here is the source code for cc.redpen.Main.java

Source

/**
 * redpen: a text inspection tool
 * Copyright (c) 2014-2015 Recruit Technologies Co., Ltd. and contributors
 * (see CONTRIBUTORS.md)
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 cc.redpen;

import cc.redpen.formatter.Formatter;
import cc.redpen.model.Document;
import cc.redpen.parser.DocumentParser;
import cc.redpen.util.FormatterUtils;
import cc.redpen.validator.ValidationError;
import org.apache.commons.cli.*;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Class containing main method called from command line.
 */
public final class Main {
    private static final Logger LOG = LoggerFactory.getLogger(Main.class);

    private static final String PROGRAM = "redpen-cli";

    private static final String DEFAULT_CONFIG_NAME = "redpen-conf";

    private static final int DEFAULT_LIMIT = 1;

    private static final String HELP_HEADER = "\nValidate input documents with specified configuration settings.\n\nOptions:\n";

    private static final String HELP_FOOTER = "\n\nExample:\n\n" + "$redpen -c redpen-config.xml input.md\n\n"
            + "Note:\n" + "Setting files can be generated in http://redpen.herokuapp.com/\n";

    private Main() {
        super();
    }

    /**
     * When the errors reported by RedPen is more than the specified limit, this method returns 1 otherwise return 0.
     *
     * @param args arguments
     * @throws RedPenException when failed to process validation
     */
    public static void main(String... args) throws RedPenException {
        System.exit(run(args));
    }

    @SuppressWarnings("static-access")
    public static int run(String... args) throws RedPenException {
        Options options = new Options();
        options.addOption("h", "help", false, "Displays this help information and exits");

        options.addOption(OptionBuilder.withLongOpt("format")
                .withDescription("Input file format (markdown,plain,wiki,asciidoc,latex,rest)").hasArg()
                .withArgName("FORMAT").create("f"));

        options.addOption(OptionBuilder.withLongOpt("conf").withDescription("Configuration file (REQUIRED)")
                .hasArg().withArgName("CONF FILE").create("c"));

        options.addOption(OptionBuilder.withLongOpt("result-format")
                .withDescription("Output result format (json,json2,plain,plain2,xml)").hasArg()
                .withArgName("RESULT FORMAT").create("r"));

        options.addOption(OptionBuilder.withLongOpt("limit").withDescription("Error limit number").hasArg()
                .withArgName("LIMIT NUMBER").create("l"));

        options.addOption(OptionBuilder.withLongOpt("sentence").withDescription("Input sentences").hasArg()
                .withArgName("INPUT SENTENCES").create("s"));

        options.addOption(OptionBuilder.withLongOpt("lang").withDescription("Language of error messages").hasArg()
                .withArgName("LANGUAGE").create("L"));

        options.addOption(OptionBuilder.withLongOpt("threshold")
                .withDescription("Threshold of error level (info, warn, error)").hasArg().withArgName("THRESHOLD")
                .create("t"));

        options.addOption(OptionBuilder.withLongOpt("version")
                .withDescription("Displays version information and exits").create("v"));

        CommandLineParser commandLineParser = new BasicParser();
        CommandLine commandLine;
        try {
            commandLine = commandLineParser.parse(options, args);
        } catch (ParseException e) {
            LOG.error("Error occurred in parsing command line options ");
            printHelp(options);
            return -1;
        }

        String inputFormat = "plain";
        String configFileName = null;
        String resultFormat = "plain";
        String inputSentence = null;
        String language = "en";
        String threshold = "error";

        int limit = DEFAULT_LIMIT;

        if (commandLine.hasOption("h")) {
            printHelp(options);
            return 0;
        }
        if (commandLine.hasOption("v")) {
            System.out.println(RedPen.VERSION);
            return 0;
        }
        if (commandLine.hasOption("f")) {
            inputFormat = commandLine.getOptionValue("f");
        }
        if (commandLine.hasOption("c")) {
            configFileName = commandLine.getOptionValue("c");
        }
        if (commandLine.hasOption("r")) {
            resultFormat = commandLine.getOptionValue("r");
        }
        if (commandLine.hasOption("l")) {
            limit = Integer.valueOf(commandLine.getOptionValue("l"));
        }
        if (commandLine.hasOption("L")) {
            language = commandLine.getOptionValue("L");
        }
        if (commandLine.hasOption("s")) {
            inputSentence = commandLine.getOptionValue("s");
        }
        if (commandLine.hasOption("t")) {
            threshold = commandLine.getOptionValue("t");
        }

        // set language
        if (language.equals("ja")) {
            Locale.setDefault(new Locale("ja", "JA"));
        } else {
            Locale.setDefault(new Locale("en", "EN"));
        }

        String[] inputFileNames = commandLine.getArgs();
        if (!commandLine.hasOption("f")) {
            inputFormat = guessInputFormat(inputFileNames);
        }

        File configFile = resolveConfigLocation(configFileName);
        if (configFile == null) {
            LOG.error("Configuration file is not found.");
            printHelp(options);
            return 1;
        }

        if (inputFileNames.length == 0 && inputSentence == null) {
            LOG.error("Input is not given");
            printHelp(options);
            return 1;
        }

        RedPen redPen;
        try {
            redPen = new RedPen(configFile);
        } catch (RedPenException e) {
            LOG.error("Failed to parse input files: " + e);
            return -1;
        }

        List<Document> documents = getDocuments(inputFormat, inputSentence, inputFileNames, redPen);
        Map<Document, List<ValidationError>> documentListMap = redPen.validate(documents, threshold);

        Formatter formatter = FormatterUtils.getFormatterByName(resultFormat);
        if (formatter == null) {
            LOG.error("Unsupported format: " + resultFormat + " - please use xml, plain, plain2, json or json2");
            return -1;
        }
        String result = formatter.format(documentListMap);
        System.out.println(result);

        long errorCount = documentListMap.values().stream().mapToLong(List::size).sum();

        if (errorCount > limit) {
            LOG.error("The number of errors \"{}\" is larger than specified (limit is \"{}\").", errorCount, limit);
            return 1;
        } else {
            return 0;
        }
    }

    private static List<Document> getDocuments(String inputFormat, String inputSentence, String[] inputFileNames,
            RedPen redPen) throws RedPenException {
        List<Document> documents = new ArrayList<>();
        DocumentParser parser = DocumentParser.of(inputFormat);
        if (inputSentence == null) {
            documents.addAll(redPen.parse(parser, extractInputFiles(inputFileNames)));
        } else {
            documents.add(redPen.parse(parser, inputSentence));
        }
        return documents;
    }

    static String guessInputFormat(String[] inputFileNames) {
        String inputFormat = "";
        for (String inputFileName : inputFileNames) {
            String format = detectFormat(inputFileName);
            if (!inputFormat.equals("") && !format.equals(inputFormat)) {
                LOG.warn("There are more than one file type...: {} and {}", format, inputFormat);
                LOG.warn("Guess file format as plain...");
                return "plain"; //NOTE: return file type as "plain" when there are more than one file types...
            }
            inputFormat = format;
        }
        return inputFormat.equals("") ? "plain" : inputFormat;
    }

    private static String detectFormat(String inputFileName) {
        String ext = FilenameUtils.getExtension(inputFileName);
        switch (ext) {
        case "txt":
            return "plain";
        case "adoc":
        case "asciidoc":
            return "asciidoc";
        case "markdown":
        case "md":
            return "markdown";
        case "tex":
        case "latex":
            return "latex";
        case "re":
        case "review":
            return "review";
        case "properties":
            return "properties";
        case "rst":
        case "rest":
            return "rest";
        default:
            LOG.info("No such file extension as \"{}\"", ext);
            return "plain";
        }
    }

    private static File[] extractInputFiles(String[] inputFileNames) {
        File[] inputFiles = new File[inputFileNames.length];
        for (int i = 0; i < inputFileNames.length; i++) {
            inputFiles[i] = new File(inputFileNames[i]);
        }
        return inputFiles;
    }

    private static void printHelp(Options opt) {
        HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(100);
        PrintWriter pw = new PrintWriter(System.err);
        formatter.printHelp(pw, 80, PROGRAM + " [Options] [<INPUT FILE>]", HELP_HEADER, opt, 1, 3, HELP_FOOTER);
        pw.flush();
    }

    static File resolveConfigLocation(String configFileName) {
        List<String> pathCandidates = new ArrayList<>();
        if (configFileName != null) {
            pathCandidates.add(configFileName);
        }
        pathCandidates.add(DEFAULT_CONFIG_NAME + ".xml");
        pathCandidates.add(DEFAULT_CONFIG_NAME + "-" + Locale.getDefault().getLanguage() + ".xml");
        String redpenHome = System.getenv("REDPEN_HOME");
        if (redpenHome != null) {
            pathCandidates.add(redpenHome + File.separator + DEFAULT_CONFIG_NAME + ".xml");
            pathCandidates.add(redpenHome + File.separator + DEFAULT_CONFIG_NAME + "-"
                    + Locale.getDefault().getLanguage() + ".xml");
            pathCandidates
                    .add(redpenHome + File.separator + "conf" + File.separator + DEFAULT_CONFIG_NAME + ".xml");
            pathCandidates.add(redpenHome + File.separator + "conf" + File.separator + DEFAULT_CONFIG_NAME + "-"
                    + Locale.getDefault().getLanguage() + ".xml");
        }
        File resolved = resolve(pathCandidates);
        if (resolved != null && resolved.exists() && resolved.isFile()) {
            LOG.info("Configuration file: {}", resolved.getAbsolutePath());
        } else {
            resolved = null;
        }
        return resolved;
    }

    static File resolve(List<String> pathCandidates) {
        File resolved;
        for (String pathCandidate : pathCandidates) {
            resolved = new File(pathCandidate);
            if (resolved.exists() && resolved.isFile()) {
                return resolved;
            }
        }
        return null;
    }
}