All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.tzemp.parser.Parser Maven / Gradle / Ivy

package com.github.tzemp.parser;

import com.github.tzemp.config.Config;
import com.github.tzemp.parser.hints.Hint;
import com.github.tzemp.reporting.ReportingRequest;
import com.github.tzemp.stackoverflow.StackExchangeClient;
import com.github.tzemp.stackoverflow.StackExchangeQuestion;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by timothyzemp on 06.06.17.
 */
public class Parser {
    public static Config config;
    private List log;
    private List commands;
    private ParserSummary parserSummary;
    private List evaluations;


    /**
     * Entry Point for command line version
     *
     * @param args args
     */
    public static void main(String[] args) {
        if (args.length > 0) {
            boolean allowStats = false;
            if (args.length > 1) {
                allowStats = args[2].equals("true");
            }
            String path = args[0];
            List lines = new ArrayList<>();
            try {
                // Read File
                lines = FileUtils.readLines(new File(path));

                // Read Config
                Config config = Parser.readConfig();

                // Create Parser
                Parser parser = new Parser(lines, config);

                String output = Parser.createTXTOutput(parser);

                PrintWriter writer = new PrintWriter("summary.txt", "UTF-8");
                writer.println(output);
                writer.close();

                // if we allow reporting, we report!
                if (allowStats) {
                    ReportingRequest request = new ReportingRequest();
                    request.post(parser.getParserSummary(), parser.getLog(), "testproject");
                }


            } catch (IOException e) {
                System.out.println("File not readable");
            }
        } else {
            System.out.println("Please provide a path to a log file");
        }
    }

    private static String createTXTOutput(Parser parser) {

        ParserSummary parserSummary = parser.getParserSummary();

        String divider = "===============================\n";

        StringBuilder sb = new StringBuilder();

        // Create Title
        sb.append(divider);
        sb.append("BART - Build Summarization\n");
        sb.append(divider);

        // Create Overview

        sb.append("Build Status: Failed \n");
        sb.append("Failed goal: ").append(parserSummary.getFailedGoal()).append("\n");
        sb.append("Error cause: ").append(parserSummary.getErrorCause()).append("\n");

        if (parserSummary.hasReactor()) {
            sb.append("Reactor: \n");
            for (Module reactorModule : parserSummary.getReactor()) {
                sb.append(reactorModule.getStatus()).append(": ").append(reactorModule.getName()).append("\n");
            }
        }

        sb.append(divider);
        sb.append("Reason for Build Failure:\n");
        sb.append(parserSummary.getErrorCause()).append("\n");
        sb.append(divider);

        if (parserSummary.hasHint()) {
            sb.append(parserSummary.getHint().getTXTOutput());
            sb.append(divider);
        }

        sb.append("Stack Exchange Analysis \n");
        sb.append("This may help you fix your build: \n");

        StackExchangeQuestion bestQuestion = parser.getBestQuestion();

        if (bestQuestion != null && bestQuestion.isAnswered() && bestQuestion.getBestAnswer() != null) {
            sb.append(bestQuestion.getBestAnswer().getBody().replaceAll("\\<.*?>","")).append("\n");
            sb.append("Full Discussion: ").append(bestQuestion.getLink()).append("\n");
        } else {
            sb.append("Unfortunately there is no matching solution :-( \n");
        }

        sb.append(divider);
        sb.append("Other useful resources: \n");

        for (StackExchangeQuestionEvaluation stackExchangeQuestionEvaluation : parser.getEvaluations()) {
            sb.append(stackExchangeQuestionEvaluation.getQuestion().getTitle()).append(": ").append(stackExchangeQuestionEvaluation.getQuestion().getLink()).append("\n");
        }
        sb.append(divider);

        return sb.toString();
    }

    /**
     * Constructor.
     * Assigns the necessary dependencies and then starts the parsing
     * and ends with the StackOverflow Analysis.
     */
    public Parser(List log, Config config) {
        this.log = log;
        Parser.config = config;
        this.commands = new ArrayList<>();
        parseCommands();
        parseModules();
        stackOverflowAnalysis();
        createSummary();
    }

    /**
     * Creates the final summary which consists of different entities into a
     * single view entity to be passed to the plugin
     */
    private void createSummary() {
        this.parserSummary = new ParserSummary();
        Command lastCommand = this.getCommands().get(this.getCommands().size() - 1);
        parserSummary.setCommand(lastCommand.getName());
        if (lastCommand.hasBuildSection()) {
            BuildSection buildSection = lastCommand.getBuildSection();
            parserSummary.setBuildStatus("asdf");
            parserSummary.setErrorCause(buildSection.getErrorCause());
            parserSummary.setFailedGoal(buildSection.getFailedGoal());
            parserSummary.setAdditionalErrorInformation(buildSection.getAdditionalErrorInformation());

            if (lastCommand.hasReactor()) {
                parserSummary.setReactor(lastCommand.getModules());
            }
            if (this.getEvaluations() != null) {
                parserSummary.setBestQuestion(this.getBestQuestion());
            }
        }
        if (lastCommand.getHint() != null) {
            parserSummary.setHint(lastCommand.getHint());
        }
    }

    /**
     * Iterates through each command and first parses the modules in it
     * When the modules are parsed, we parse the (potential) build section
     * if there is a build section, we additionally extract further information
     * through the Hint interface
     */
    private void parseModules() {
        for (Command command : this.getCommands()) {
            command.parseModules();
            command.parseBuildSection();
            if (command.hasBuildSection()) {
                command.extractAdditionalInformation();
            }
        }
    }

    /**
     * Iterates through the log and identifies each Command in the log
     * by the identifiers we define in the config.yml and then assigns
     * the sections of the log to the corresponding Command
     */
    private void parseCommands() {
        boolean insideTravisFold = false;
        List tempLines = new ArrayList();
        Command tempCommand = null;

        for (String line : this.getLog()) {

            // Are we in a travis_fold section?
            if (insideTravisFold) {
                tempLines.add(line);

                //does the section ends?
                if (line.contains(Parser.config.getTravisCommandIdentifier("end")) || (line.contains("command") && line.contains("Retrying"))) {
                    insideTravisFold = false;
                    tempCommand.setLines(tempLines);
                    tempLines = new ArrayList<>();
                    this.getCommands().add(tempCommand);
                }

            } else {
                // a new section start?
                if (line.contains(Parser.config.getTravisCommandIdentifier("start")) || (line.contains("command") && line.contains("Retrying"))) {

                    // are we reading?
                    if (tempLines.size() > 0) {
                        tempCommand.setLines(tempLines);
                        this.getCommands().add(tempCommand);
                        tempLines = new ArrayList<>();
                    }
                    insideTravisFold = true;
                    Pattern p = Pattern.compile(Parser.config.getTravisCommandIdentifier("extract"));
                    Matcher m = p.matcher(line);
                    if (m.find()) {
                        tempCommand = new Command();
                        tempCommand.setName(m.group(1));
                    }
                } else {
                    if (tempLines.size() > 0) {
                        tempLines.add(line);
                    } else {
                        tempCommand = new Command();
                        tempLines.add(line);
                    }
                }
            }
        }

        if (tempLines.size() > 0) {
            tempCommand.setLines(tempLines);
            this.getCommands().add(tempCommand);
        }
    }

    public Config getConfig() {
        return config;
    }

    public List getLog() {
        return log;
    }

    public List getCommands() {
        return commands;
    }

    /**
     * Temp Function to print the content of the parser
     * it behaves kinda like var_dump from php.
     */
    public List print() {
        List temp = new ArrayList<>();
        for (Command command : this.getCommands()) {
            temp.addAll(command.print());
        }
        return temp;
    }

    /**
     * This performs the StackOverflow Analysis be creating a connection
     * to StackExchange, perform the necessary queries to obtain discussions and
     * then evaluate those discussions to find the best solution available
     */
    public void stackOverflowAnalysis() {

        // We create a connection to stackoverflow
        StackExchangeClient stackExchangeClient = new StackExchangeClient("stackoverflow");

        // we get the last command, because this is the one which lead to the build failure
        Command command = this.getCommands().get(this.getCommands().size() - 1);

        if (command.hasBuildSection()) {
            BuildSection buildSection = command.getBuildSection();
            List stackExchangeQuestions = new ArrayList<>();
            String failedGoal = buildSection.getFailedGoal();

            try {

                // do we have a hint?
                if (command.getHint() != null) {
                    Hint hint = command.getHint();
                    List stackExchangeQuestionsHint = stackExchangeClient.search(hint.getStackExchangeQuery());
                    stackExchangeQuestions.addAll(stackExchangeQuestionsHint);

                } else {

                    // we are searching for the goal as well as for the cause (2 queries)
                    if (failedGoal.equals("none")) {
                        failedGoal = Parser.config.filterStringByStopWords(buildSection.getErrorCause());
                    }

                    // Query for the failed goal
                    String cleanFailedGoal = failedGoal.replace(":", "\\").replaceAll("[0-9]", "");
                    List stackExchangeQuestionsGoal = stackExchangeClient.search(cleanFailedGoal);
                    stackExchangeQuestions.addAll(stackExchangeQuestionsGoal);

                    // Query for the error cause
                    List stackExchangeQuestionsCause = stackExchangeClient.search(buildSection.getErrorCause());
                    stackExchangeQuestions.addAll(stackExchangeQuestionsCause);
                }

                // rate
                StackExchangeQuestionRater rater = new StackExchangeQuestionRater(stackExchangeQuestions, buildSection);
                rater.rate();

                this.evaluations = rater.getQuestionsWithHigestRating(3);

            } catch (IOException | URISyntaxException e) {
                e.printStackTrace();
            }
        }
    }

    public List getEvaluations() {
        return this.evaluations;
    }

    public ParserSummary getParserSummary() {
        return parserSummary;
    }

    /**
     * returns the best Discussions from the evaluated Discussions
     */
    public StackExchangeQuestion getBestQuestion() {
        if (this.getEvaluations().size() > 0) {
            for (StackExchangeQuestionEvaluation stackExchangeQuestionEvaluation : this.getEvaluations()) {
                if (stackExchangeQuestionEvaluation.getQuestion().isAnswered()) {
                    return stackExchangeQuestionEvaluation.getQuestion();
                }
            }
            return this.getEvaluations().get(0).getQuestion();
        } else {
            return null;
        }
    }

    /**
     * Reads the config and returns it
     *
     * @return config
     */
    private static Config readConfig() {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        try {
            return mapper.readValue(new File("src/config/config.yaml"), Config.class);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy