Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cli module refactoring #1607

Merged
merged 11 commits into from
Apr 10, 2024
287 changes: 62 additions & 225 deletions cli/src/main/java/de/jplag/cli/CLI.java

Large diffs are not rendered by default.

104 changes: 104 additions & 0 deletions cli/src/main/java/de/jplag/cli/JPlagOptionsBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package de.jplag.cli;

import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.cli.options.CliOptions;
import de.jplag.cli.picocli.CliInputHandler;
import de.jplag.clustering.ClusteringOptions;
import de.jplag.clustering.Preprocessing;
import de.jplag.merging.MergingOptions;
import de.jplag.options.JPlagOptions;

/**
* Handles the building of JPlag options from the cli options
*/
public class JPlagOptionsBuilder {
private static final Logger logger = LoggerFactory.getLogger(JPlagOptionsBuilder.class);

private final CliInputHandler cliInputHandler;
private final CliOptions cliOptions;

/**
* @param cliInputHandler The cli handler containing the parsed cli options
*/
public JPlagOptionsBuilder(CliInputHandler cliInputHandler) {
this.cliInputHandler = cliInputHandler;
this.cliOptions = this.cliInputHandler.getCliOptions();
}

/**
* Builds the JPlag options
* @return The JPlag options
* @throws CliException If the input handler could properly parse everything.
*/
public JPlagOptions buildOptions() throws CliException {
Set<File> submissionDirectories = new HashSet<>(List.of(this.cliOptions.rootDirectory));
Set<File> oldSubmissionDirectories = Set.of(this.cliOptions.oldDirectories);
List<String> suffixes = List.of(this.cliOptions.advanced.suffixes);
submissionDirectories.addAll(List.of(this.cliOptions.newDirectories));
submissionDirectories.addAll(this.cliInputHandler.getSubcommandSubmissionDirectories());

JPlagOptions jPlagOptions = initializeJPlagOptions(submissionDirectories, oldSubmissionDirectories, suffixes);

String baseCodePath = this.cliOptions.baseCode;
File baseCodeDirectory = baseCodePath == null ? null : new File(baseCodePath);
if (baseCodeDirectory == null || baseCodeDirectory.exists()) {
return jPlagOptions.withBaseCodeSubmissionDirectory(baseCodeDirectory);
}
logger.error("Using legacy partial base code API. Please migrate to new full path base code API.");
return jPlagOptions.withBaseCodeSubmissionName(baseCodePath);
}

private JPlagOptions initializeJPlagOptions(Set<File> submissionDirectories, Set<File> oldSubmissionDirectories, List<String> suffixes)
throws CliException {
ClusteringOptions clusteringOptions = getClusteringOptions();
MergingOptions mergingOptions = getMergingOptions();

return new JPlagOptions(this.cliInputHandler.getSelectedLanguage(), this.cliOptions.minTokenMatch, submissionDirectories,
oldSubmissionDirectories, null, this.cliOptions.advanced.subdirectory, suffixes, this.cliOptions.advanced.exclusionFileName,
JPlagOptions.DEFAULT_SIMILARITY_METRIC, this.cliOptions.advanced.similarityThreshold, this.cliOptions.shownComparisons,
clusteringOptions, this.cliOptions.advanced.debug, mergingOptions, this.cliOptions.normalize);
}

private ClusteringOptions getClusteringOptions() {
ClusteringOptions clusteringOptions = new ClusteringOptions().withEnabled(!this.cliOptions.clustering.disable)
.withAlgorithm(this.cliOptions.clustering.enabled.algorithm).withSimilarityMetric(this.cliOptions.clustering.enabled.metric)
.withSpectralKernelBandwidth(this.cliOptions.clusterSpectralBandwidth)
.withSpectralGaussianProcessVariance(this.cliOptions.clusterSpectralNoise).withSpectralMinRuns(this.cliOptions.clusterSpectralMinRuns)
.withSpectralMaxRuns(this.cliOptions.clusterSpectralMaxRuns)
.withSpectralMaxKMeansIterationPerRun(this.cliOptions.clusterSpectralKMeansIterations)
.withAgglomerativeThreshold(this.cliOptions.clusterAgglomerativeThreshold)
.withAgglomerativeInterClusterSimilarity(this.cliOptions.clusterAgglomerativeInterClusterSimilarity);

if (this.cliOptions.clusterPreprocessingNone) {
clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.NONE);
}

if (this.cliOptions.clusterPreprocessingCdf) {
clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.CUMULATIVE_DISTRIBUTION_FUNCTION);
}

if (this.cliOptions.clusterPreprocessingPercentile != 0) {
clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.PERCENTILE)
.withPreprocessorPercentile(this.cliOptions.clusterPreprocessingPercentile);
}

if (this.cliOptions.clusterPreprocessingThreshold != 0) {
clusteringOptions = clusteringOptions.withPreprocessor(Preprocessing.THRESHOLD)
.withPreprocessorThreshold(this.cliOptions.clusterPreprocessingThreshold);
}

return clusteringOptions;
}

private MergingOptions getMergingOptions() {
return new MergingOptions(this.cliOptions.merging.enabled, this.cliOptions.merging.minimumNeighborLength,
this.cliOptions.merging.maximumGapSize);
}
}
52 changes: 52 additions & 0 deletions cli/src/main/java/de/jplag/cli/JPlagRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package de.jplag.cli;

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.JPlag;
import de.jplag.JPlagResult;
import de.jplag.cli.server.ReportViewer;
import de.jplag.exceptions.ExitException;
import de.jplag.options.JPlagOptions;

/**
* Wraps the execution of the JPlag components
*/
public final class JPlagRunner {
private static final Logger logger = LoggerFactory.getLogger(JPlagRunner.class);

private JPlagRunner() {
}

/**
* Executes JPlag
* @param options The options to pass to JPlag
* @return The result returned by JPlag
* @throws ExitException If JPlag throws an error
*/
public static JPlagResult runJPlag(JPlagOptions options) throws ExitException {
return JPlag.run(options);
}

/**
* Runs the internal server. Blocks until the server has stopped.
* @param zipFile The zip file to pass to the server. May be null.
* @param port The port to open the server on
* @throws IOException If the internal server throws an exception
*/
public static void runInternalServer(File zipFile, int port) throws IOException {
ReportViewer reportViewer = new ReportViewer(zipFile, port);
int actualPort = reportViewer.start();
logger.info("ReportViewer started on port http://localhost:{}", actualPort);
Desktop.getDesktop().browse(URI.create("http://localhost:" + actualPort + "/"));

System.out.println("Press Enter key to exit...");
System.in.read();
reportViewer.stop();
}
}
22 changes: 20 additions & 2 deletions cli/src/main/java/de/jplag/cli/OutputFileGenerator.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package de.jplag.cli;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.JPlagResult;
import de.jplag.cli.options.CliOptions;
import de.jplag.csv.comparisons.CsvComparisonOutput;
import de.jplag.reporting.reportobject.ReportObjectFactory;

/**
* Manages the creation of output files
*/
public final class OutputFileGenerator {
private static final Logger logger = LoggerFactory.getLogger(OutputFileGenerator.class);

private OutputFileGenerator() {
// Prevents default constructor
}

/**
* Exports the given result as csvs, if the csvExport is activated in the options. Both a full and an anonymized version
* Exports the given result as CSVs, if the csvExport is activated in the options. Both a full and an anonymized version
* will be written.
* @param result The result to export
* @param outputRoot The root folder for the output
Expand All @@ -33,4 +38,17 @@ public static void generateCsvOutput(JPlagResult result, File outputRoot, CliOpt
}
}
}

/**
* Generates the JPLag result zip
* @param result The JPlag result
* @param outputFile The output file
* @throws FileNotFoundException If the file cannot be written
*/
public static void generateJPlagResultZip(JPlagResult result, File outputFile) throws FileNotFoundException {
ReportObjectFactory reportObjectFactory = new ReportObjectFactory(outputFile);
reportObjectFactory.createAndSaveReport(result);
logger.info("Successfully written the result: {}", outputFile.getPath());
logger.info("View the result using --mode or at: https://jplag.github.io/JPlag/");
}
}
Loading
Loading