net.lldp.checksims.ChecksimsRunner.java Source code

Java tutorial

Introduction

Here is the source code for net.lldp.checksims.ChecksimsRunner.java

Source

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * See LICENSE.txt included in this distribution for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at LICENSE.txt.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 *
 * Copyright (c) 2014-2015 Nicholas DeMarinis, Matthew Heon, and Dolan Murvihill
 */

package net.lldp.checksims;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import net.lldp.checksims.algorithm.AlgorithmResults;
import net.lldp.checksims.algorithm.AlgorithmRunner;
import net.lldp.checksims.algorithm.preprocessor.PreprocessSubmissions;
import net.lldp.checksims.algorithm.preprocessor.SubmissionPreprocessor;
import net.lldp.checksims.algorithm.similaritymatrix.SimilarityMatrix;
import net.lldp.checksims.algorithm.similaritymatrix.output.MatrixPrinter;
import net.lldp.checksims.submission.Submission;
import net.lldp.checksims.util.PairGenerator;
import net.lldp.checksims.util.threading.ParallelAlgorithm;
import org.apache.commons.cli.ParseException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * CLI Entry point and main public API endpoint for Checksims.
 */
public final class ChecksimsRunner {

    private ChecksimsRunner() {
    }

    /**
     * CLI entrypoint of Checksims.
     *
     * @param args CLI arguments
     */
    public static void main(String[] args) {
        try {
            ChecksimsCommandLine.runCLI(args);
        } catch (ParseException e) {
            System.err.println(e.getMessage());
            System.exit(-1);
        } catch (ChecksimsException e) {
            System.err.println(e.toString());
            if (e.getCause() != null) {
                System.err.println("Caused by: " + e.getCause().toString());
            }
            // Print the stack trace for internal exceptions, they may be serious
            e.printStackTrace();
            System.exit(-1);
        } catch (IOException e) {
            System.err.println("I/O Error!");
            System.err.println(e.getMessage());
            System.exit(-1);
        }

        System.exit(0);
    }

    /**
     * Get current version.
     *
     * @return Current version of Checksims
     */
    public static String getChecksimsVersion() throws ChecksimsException {
        InputStream resource = ChecksimsCommandLine.class.getResourceAsStream("version.txt");

        if (resource == null) {
            throw new ChecksimsException("Error obtaining resource for version!");
        }

        try {
            return IOUtils.toString(resource);
        } catch (IOException e) {
            throw new ChecksimsException("IO Exception reading version: " + e.getMessage(), e);
        }
    }

    /**
     * Main public entrypoint to Checksims. Runs similarity detection according to given configuration.
     *
     * @param config Configuration defining how Checksims will be run
     * @return Map containing output of all output printers requested. Keys are name of output printer.
     * @throws ChecksimsException Thrown on error performing similarity detection
     */
    public static ImmutableMap<String, String> runChecksims(ChecksimsConfig config) throws ChecksimsException {
        checkNotNull(config);

        // Create a logger to log activity
        Logger logs = LoggerFactory.getLogger(ChecksimsRunner.class);

        // Set parallelism
        int threads = config.getNumThreads();
        ParallelAlgorithm.setThreadCount(threads);
        // TODO following line may not be necessary as we no longer use parallel streams?
        System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "" + threads);

        ImmutableSet<Submission> submissions = config.getSubmissions();

        logs.info("Got " + submissions.size() + " submissions to test.");

        ImmutableSet<Submission> archiveSubmissions = config.getArchiveSubmissions();

        if (!archiveSubmissions.isEmpty()) {
            logs.info("Got " + archiveSubmissions.size() + " archive submissions to test.");
        }

        if (submissions.size() == 0) {
            throw new ChecksimsException("No student submissions were found - cannot run Checksims!");
        }

        // Apply all preprocessors
        for (SubmissionPreprocessor p : config.getPreprocessors()) {
            submissions = ImmutableSet
                    .copyOf(PreprocessSubmissions.process(p, submissions, config.getStatusLogger()));

            if (!archiveSubmissions.isEmpty()) {
                archiveSubmissions = ImmutableSet
                        .copyOf(PreprocessSubmissions.process(p, archiveSubmissions, config.getStatusLogger()));
            }
        }

        if (submissions.size() < 2) {
            throw new ChecksimsException("Did not get at least 2 student submissions! Cannot run Checksims!");
        }

        // Apply algorithm to submissions
        Set<Pair<Submission, Submission>> allPairs = PairGenerator.generatePairsWithArchive(submissions,
                archiveSubmissions);
        Set<AlgorithmResults> results = AlgorithmRunner.runAlgorithm(allPairs, config.getAlgorithm(),
                config.getStatusLogger());

        if (config.isIgnoringInvalid()) {
            Set<Submission> validSubmissions = new HashSet<>();
            Set<Submission> validArchivedSubmissions = new HashSet<>();
            Set<AlgorithmResults> validResults = new HashSet<>();
            submissions.stream().filter(S -> !S.testFlag("invalid")).forEach(S -> validSubmissions.add(S));
            archiveSubmissions.stream().filter(S -> !S.testFlag("invalid"))
                    .forEach(S -> validArchivedSubmissions.add(S));
            results.stream().filter(S -> S.isValid()).forEach(S -> validResults.add(S));

            submissions = ImmutableSet.copyOf(validSubmissions);
            archiveSubmissions = ImmutableSet.copyOf(validArchivedSubmissions);
            results = validResults;

        }

        SimilarityMatrix resultsMatrix = SimilarityMatrix.generateMatrix(submissions, archiveSubmissions, results);

        // All parallel jobs are done, shut down the parallel executor
        ParallelAlgorithm.shutdownExecutor();
        config.getStatusLogger().end();

        Map<String, String> outputMap = new HashMap<>();

        // Output using all output printers
        for (MatrixPrinter p : config.getOutputPrinters()) {
            logs.info("Generating " + p.getName() + " output");

            outputMap.put(p.getName(), p.printMatrix(resultsMatrix));
        }

        ChecksimsCommandLine.deleteTempFiles();

        return ImmutableMap.copyOf(outputMap);
    }
}