|
|
@@ -1,320 +1,254 @@
|
|
|
package de.jplag.options;
|
|
|
|
|
|
+import static de.jplag.options.Verbosity.LONG;
|
|
|
import static de.jplag.strategy.ComparisonMode.NORMAL;
|
|
|
|
|
|
-import java.io.File;
|
|
|
+import java.io.BufferedReader;
|
|
|
+import java.io.FileReader;
|
|
|
+import java.io.IOException;
|
|
|
import java.nio.charset.Charset;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.Collections;
|
|
|
import java.util.List;
|
|
|
import java.util.Optional;
|
|
|
import java.util.Set;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
+import de.jplag.JPlag;
|
|
|
import de.jplag.Language;
|
|
|
import de.jplag.clustering.ClusteringOptions;
|
|
|
import de.jplag.strategy.ComparisonMode;
|
|
|
|
|
|
-public class JPlagOptions {
|
|
|
+/**
|
|
|
+ * This record defines the options to configure {@link JPlag}.
|
|
|
+ * @param language Language to use when parsing the submissions.
|
|
|
+ * @param minimumTokenMatch Tunes the comparison sensitivity by adjusting the minimum token required to be counted as
|
|
|
+ * matching section. A smaller {@code <n>} increases the sensitivity but might lead to more false-positives.
|
|
|
+ * @param submissionDirectories Directories with new submissions. These must be checked for plagiarism.
|
|
|
+ * @param oldSubmissionDirectories Directories with old submissions to check against.
|
|
|
+ * @param baseCodeSubmissionName Path name of the directory containing the base code.
|
|
|
+ * @param subdirectoryName Example: If the subdirectoryName is 'src', only the code inside submissionDir/src of each
|
|
|
+ * submission will be used for comparison.
|
|
|
+ * @param fileSuffixes List of file suffixes that should be included.
|
|
|
+ * @param exclusionFileName Name of the file that contains the names of files to exclude from comparison.
|
|
|
+ * @param similarityMetric The similarity metric determines how the minimum similarity threshold required for a
|
|
|
+ * comparison (of two submissions) is calculated. This affects which comparisons are stored and thus make it into the
|
|
|
+ * result object.
|
|
|
+ * @param similarityThreshold Percentage value (must be between 0 and 100). Comparisons (of submissions pairs) with a
|
|
|
+ * similarity below this threshold will be ignored. The default value of 0 allows all matches to be stored. This affects
|
|
|
+ * which comparisons are stored and thus make it into the result object. See also {@link #similarityMetric()}.
|
|
|
+ * @param maximumNumberOfComparisons The maximum number of comparisons that will be shown in the generated report. If
|
|
|
+ * set to {@link #SHOW_ALL_COMPARISONS} all comparisons will be shown.
|
|
|
+ * @param clusteringOptions Clustering options
|
|
|
+ * @param comparisonMode Determines which strategy to use for the comparison of submissions.
|
|
|
+ * @param verbosity Level of output verbosity.
|
|
|
+ * @param debugParser If true, submissions that cannot be parsed will be stored in a separate directory.
|
|
|
+ */
|
|
|
+public record JPlagOptions(Language language, Integer minimumTokenMatch, List<String> submissionDirectories, List<String> oldSubmissionDirectories,
|
|
|
+ String baseCodeSubmissionName, String subdirectoryName, List<String> fileSuffixes, String exclusionFileName,
|
|
|
+ SimilarityMetric similarityMetric, double similarityThreshold, int maximumNumberOfComparisons, ClusteringOptions clusteringOptions,
|
|
|
+ ComparisonMode comparisonMode, Verbosity verbosity, boolean debugParser) {
|
|
|
|
|
|
- private static final Logger logger = LoggerFactory.getLogger("JPlag");
|
|
|
public static final ComparisonMode DEFAULT_COMPARISON_MODE = NORMAL;
|
|
|
- public static final float DEFAULT_SIMILARITY_THRESHOLD = 0;
|
|
|
+ public static final double DEFAULT_SIMILARITY_THRESHOLD = 0;
|
|
|
public static final int DEFAULT_SHOWN_COMPARISONS = 30;
|
|
|
-
|
|
|
+ public static final int SHOW_ALL_COMPARISONS = 0;
|
|
|
+ public static final SimilarityMetric DEFAULT_SIMILARITY_METRIC = SimilarityMetric.AVG;
|
|
|
public static final Charset CHARSET = StandardCharsets.UTF_8;
|
|
|
|
|
|
- /**
|
|
|
- * The identifier of the language used to parse the submissions.
|
|
|
- */
|
|
|
- private final String languageIdentifier;
|
|
|
-
|
|
|
- /**
|
|
|
- * Language used to parse the submissions.
|
|
|
- */
|
|
|
- private Language language;
|
|
|
-
|
|
|
- /**
|
|
|
- * Determines which strategy to use for the comparison of submissions.
|
|
|
- */
|
|
|
- private ComparisonMode comparisonMode = DEFAULT_COMPARISON_MODE;
|
|
|
-
|
|
|
- /**
|
|
|
- * If true, submissions that cannot be parsed will be stored in a separate directory.
|
|
|
- */
|
|
|
- private boolean debugParser = false;
|
|
|
-
|
|
|
- /**
|
|
|
- * Array of file suffixes that should be included.
|
|
|
- */
|
|
|
- private String[] fileSuffixes;
|
|
|
-
|
|
|
- /**
|
|
|
- * Percentage value (must be between 0 and 100). Comparisons (of submissions pairs) with a similarity below this
|
|
|
- * threshold will be ignored. The default value of 0 allows all matches to be stored. This affects which comparisons are
|
|
|
- * stored and thus make it into the result object.
|
|
|
- * @see JPlagOptions#similarityMetric
|
|
|
- */
|
|
|
- private float similarityThreshold = DEFAULT_SIMILARITY_THRESHOLD;
|
|
|
-
|
|
|
- /**
|
|
|
- * The maximum number of comparisons that will be shown in the generated report. If set to -1 all comparisons will be
|
|
|
- * shown.
|
|
|
- */
|
|
|
- private int maximumNumberOfComparisons = DEFAULT_SHOWN_COMPARISONS;
|
|
|
-
|
|
|
- /**
|
|
|
- * The similarity metric determines how the minimum similarity threshold required for a comparison (of two submissions)
|
|
|
- * is calculated. This affects which comparisons are stored and thus make it into the result object.
|
|
|
- * @see JPlagOptions#similarityThreshold
|
|
|
- */
|
|
|
- private SimilarityMetric similarityMetric = SimilarityMetric.AVG;
|
|
|
-
|
|
|
- /**
|
|
|
- * Tunes the comparison sensitivity by adjusting the minimum token required to be counted as matching section. A smaller
|
|
|
- * <n> increases the sensitivity but might lead to more false-positives.
|
|
|
- */
|
|
|
- private Integer minimumTokenMatch;
|
|
|
-
|
|
|
- /**
|
|
|
- * Name of the file that contains the names of files to exclude from comparison.
|
|
|
- */
|
|
|
- private String exclusionFileName;
|
|
|
-
|
|
|
- /**
|
|
|
- * Names of the excluded files.
|
|
|
- */
|
|
|
- private Set<String> excludedFiles = Collections.emptySet();
|
|
|
-
|
|
|
- /**
|
|
|
- * Directories with new submissions. These must be checked for plagiarism.
|
|
|
- */
|
|
|
- private List<String> submissionDirectories;
|
|
|
-
|
|
|
- /**
|
|
|
- * Directories with old submissions to check against.
|
|
|
- */
|
|
|
- private List<String> oldSubmissionDirectories;
|
|
|
-
|
|
|
- /**
|
|
|
- * Path name of the directory containing the base code.
|
|
|
- * <p>
|
|
|
- * For backwards compatibility it may also be a directory name inside the root directory. Condition for the latter is
|
|
|
- * <ul>
|
|
|
- * <li>Specified path does not exist.</li>
|
|
|
- * <li>Name has not have a separator character after trimming them from both ends (leaving at least a one-character
|
|
|
- * name).</li>
|
|
|
- * <li>A submission with the specified name exists in the root directory.</li>
|
|
|
- * </ul>
|
|
|
- * It's an error if a string has been provided but it is neither an existing path nor does it fulfill all the conditions
|
|
|
- * of the compatibility fallback listed above.
|
|
|
- * </p>
|
|
|
- */
|
|
|
- private String baseCodeSubmissionName = null;
|
|
|
-
|
|
|
- /**
|
|
|
- * Example: If the subdirectoryName is 'src', only the code inside submissionDir/src of each submission will be used for
|
|
|
- * comparison.
|
|
|
- */
|
|
|
- private String subdirectoryName;
|
|
|
-
|
|
|
- /**
|
|
|
- * Level of output verbosity.
|
|
|
- */
|
|
|
- private Verbosity verbosity;
|
|
|
-
|
|
|
- /**
|
|
|
- * Clustering options
|
|
|
- */
|
|
|
- private ClusteringOptions clusteringOptions = new ClusteringOptions.Builder().build();
|
|
|
-
|
|
|
- /**
|
|
|
- * Constructor with required attributes.
|
|
|
- * @param languageIdentifier the identifier of the language to use. If set to {@code null} you have to use
|
|
|
- * {@link #setLanguage(Language)} to set the language programmatically.
|
|
|
- */
|
|
|
- public JPlagOptions(List<String> submissionDirectories, List<String> oldSubmissionDirectories, String languageIdentifier) {
|
|
|
- this.submissionDirectories = submissionDirectories;
|
|
|
- this.oldSubmissionDirectories = oldSubmissionDirectories;
|
|
|
- this.languageIdentifier = languageIdentifier;
|
|
|
- }
|
|
|
-
|
|
|
- public Optional<String> getBaseCodeSubmissionName() {
|
|
|
- return Optional.ofNullable(baseCodeSubmissionName);
|
|
|
- }
|
|
|
-
|
|
|
- public ComparisonMode getComparisonMode() {
|
|
|
- return comparisonMode;
|
|
|
- }
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(JPlag.class);
|
|
|
|
|
|
- public Set<String> getExcludedFiles() {
|
|
|
- return excludedFiles;
|
|
|
+ public JPlagOptions(Language language, List<String> submissionDirectories, List<String> oldSubmissionDirectories) {
|
|
|
+ this(language, null, submissionDirectories, oldSubmissionDirectories, null, null, null, null, DEFAULT_SIMILARITY_METRIC,
|
|
|
+ DEFAULT_SIMILARITY_THRESHOLD, DEFAULT_SHOWN_COMPARISONS, new ClusteringOptions(), DEFAULT_COMPARISON_MODE, null, false);
|
|
|
}
|
|
|
|
|
|
- public String getExclusionFileName() {
|
|
|
- return exclusionFileName;
|
|
|
- }
|
|
|
-
|
|
|
- public String[] getFileSuffixes() {
|
|
|
- return fileSuffixes;
|
|
|
- }
|
|
|
-
|
|
|
- public String getLanguageIdentifier() {
|
|
|
- return languageIdentifier;
|
|
|
- }
|
|
|
-
|
|
|
- public Language getLanguage() {
|
|
|
- return language;
|
|
|
+ public JPlagOptions(Language language, Integer minimumTokenMatch, List<String> submissionDirectories, List<String> oldSubmissionDirectories,
|
|
|
+ String baseCodeSubmissionName, String subdirectoryName, List<String> fileSuffixes, String exclusionFileName,
|
|
|
+ SimilarityMetric similarityMetric, double similarityThreshold, int maximumNumberOfComparisons, ClusteringOptions clusteringOptions,
|
|
|
+ ComparisonMode comparisonMode, Verbosity verbosity, boolean debugParser) {
|
|
|
+ this.language = language;
|
|
|
+ this.comparisonMode = comparisonMode;
|
|
|
+ this.debugParser = debugParser;
|
|
|
+ this.fileSuffixes = fileSuffixes == null || fileSuffixes.isEmpty() ? null : Collections.unmodifiableList(fileSuffixes);
|
|
|
+ this.similarityThreshold = normalizeSimilarityThreshold(similarityThreshold);
|
|
|
+ this.maximumNumberOfComparisons = normalizeMaximumNumberOfComparisons(maximumNumberOfComparisons);
|
|
|
+ this.similarityMetric = similarityMetric;
|
|
|
+ this.minimumTokenMatch = normalizeMinimumTokenMatch(minimumTokenMatch);
|
|
|
+ this.exclusionFileName = exclusionFileName;
|
|
|
+ this.submissionDirectories = submissionDirectories == null ? null : Collections.unmodifiableList(submissionDirectories);
|
|
|
+ this.oldSubmissionDirectories = oldSubmissionDirectories == null ? null : Collections.unmodifiableList(oldSubmissionDirectories);
|
|
|
+ this.baseCodeSubmissionName = (baseCodeSubmissionName == null || baseCodeSubmissionName.isBlank()) ? null : baseCodeSubmissionName;
|
|
|
+ this.subdirectoryName = subdirectoryName;
|
|
|
+ this.verbosity = verbosity;
|
|
|
+ this.clusteringOptions = clusteringOptions;
|
|
|
}
|
|
|
|
|
|
- public int getMaximumNumberOfComparisons() {
|
|
|
- return this.maximumNumberOfComparisons;
|
|
|
+ public JPlagOptions withLanguageOption(Language language) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public Integer getMinimumTokenMatch() {
|
|
|
- return minimumTokenMatch;
|
|
|
+ public JPlagOptions withComparisonMode(ComparisonMode comparisonMode) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public List<String> getSubmissionDirectories() {
|
|
|
- return submissionDirectories;
|
|
|
+ public JPlagOptions withDebugParser(boolean debugParser) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public List<String> getOldSubmissionDirectories() {
|
|
|
- return oldSubmissionDirectories;
|
|
|
+ public JPlagOptions withFileSuffixes(List<String> fileSuffixes) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public SimilarityMetric getSimilarityMetric() {
|
|
|
- return similarityMetric;
|
|
|
+ public JPlagOptions withSimilarityThreshold(double similarityThreshold) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public float getSimilarityThreshold() {
|
|
|
- return similarityThreshold;
|
|
|
+ public JPlagOptions withMaximumNumberOfComparisons(int maximumNumberOfComparisons) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public String getSubdirectoryName() {
|
|
|
- return subdirectoryName;
|
|
|
+ public JPlagOptions withSimilarityMetric(SimilarityMetric similarityMetric) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public Verbosity getVerbosity() {
|
|
|
- return verbosity;
|
|
|
+ public JPlagOptions withMinimumTokenMatch(Integer minimumTokenMatch) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public boolean hasBaseCode() {
|
|
|
- return this.baseCodeSubmissionName != null;
|
|
|
+ public JPlagOptions withExclusionFileName(String exclusionFileName) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public boolean isDebugParser() {
|
|
|
- return debugParser;
|
|
|
+ public JPlagOptions withSubmissionDirectories(List<String> submissionDirectories) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public ClusteringOptions getClusteringOptions() {
|
|
|
- return this.clusteringOptions;
|
|
|
+ public JPlagOptions withOldSubmissionDirectories(List<String> oldSubmissionDirectories) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public void setBaseCodeSubmissionName(String baseCodeSubmissionName) {
|
|
|
- if (baseCodeSubmissionName == null || baseCodeSubmissionName.isEmpty()) {
|
|
|
- this.baseCodeSubmissionName = null;
|
|
|
- } else {
|
|
|
- this.baseCodeSubmissionName = baseCodeSubmissionName;
|
|
|
- }
|
|
|
+ public JPlagOptions withBaseCodeSubmissionName(String baseCodeSubmissionName) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public void setComparisonMode(ComparisonMode comparisonMode) {
|
|
|
- this.comparisonMode = comparisonMode;
|
|
|
+ public JPlagOptions withSubdirectoryName(String subdirectoryName) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public void setDebugParser(boolean debugParser) {
|
|
|
- this.debugParser = debugParser;
|
|
|
+ public JPlagOptions withVerbosity(Verbosity verbosity) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public void setExcludedFiles(Set<String> excludedFiles) {
|
|
|
- this.excludedFiles = excludedFiles;
|
|
|
+ public JPlagOptions withClusteringOptions(ClusteringOptions clusteringOptions) {
|
|
|
+ return new JPlagOptions(language, minimumTokenMatch, submissionDirectories, oldSubmissionDirectories, baseCodeSubmissionName,
|
|
|
+ subdirectoryName, fileSuffixes, exclusionFileName, similarityMetric, similarityThreshold, maximumNumberOfComparisons,
|
|
|
+ clusteringOptions, comparisonMode, verbosity, debugParser);
|
|
|
}
|
|
|
|
|
|
- public void setExclusionFileName(String exclusionFileName) {
|
|
|
- this.exclusionFileName = exclusionFileName;
|
|
|
+ public boolean hasBaseCode() {
|
|
|
+ return baseCodeSubmissionName != null;
|
|
|
}
|
|
|
|
|
|
- public void setFileSuffixes(String[] fileSuffixes) {
|
|
|
- this.fileSuffixes = fileSuffixes;
|
|
|
+ public Set<String> excludedFiles() {
|
|
|
+ return Optional.ofNullable(exclusionFileName()).map(this::readExclusionFile).orElse(Collections.emptySet());
|
|
|
}
|
|
|
|
|
|
- public void setLanguage(Language language) {
|
|
|
- this.language = language;
|
|
|
+ @Override
|
|
|
+ public List<String> fileSuffixes() {
|
|
|
+ var language = language();
|
|
|
+ if ((fileSuffixes == null || fileSuffixes.isEmpty()) && language != null)
|
|
|
+ return Arrays.stream(language.suffixes()).toList();
|
|
|
+ return fileSuffixes == null ? null : Collections.unmodifiableList(fileSuffixes);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * After the selected language has been initialized, this method is called by JPlag to set default values for options
|
|
|
- * not set by the user.
|
|
|
- * @param language - initialized language instance
|
|
|
+ * Path name of the directory containing the base code.<br>
|
|
|
+ * For backwards compatibility it may also be a directory name inside the root directory. Condition for the latter is
|
|
|
+ * <ul>
|
|
|
+ * <li>Specified path does not exist.</li>
|
|
|
+ * <li>Name has not have a separator character after trimming them from both ends (leaving at least a one-character
|
|
|
+ * name).</li>
|
|
|
+ * <li>A submission with the specified name exists in the root directory.</li>
|
|
|
+ * </ul>
|
|
|
+ * It's an error if a string has been provided, but it is neither an existing path nor does it fulfill all the
|
|
|
+ * conditions of the compatibility fallback listed above.
|
|
|
*/
|
|
|
- public void setLanguageDefaults(Language language) {
|
|
|
- if (!hasMinimumTokenMatch()) {
|
|
|
- setMinimumTokenMatch(language.minimumTokenMatch());
|
|
|
- }
|
|
|
-
|
|
|
- if (!hasFileSuffixes()) {
|
|
|
- fileSuffixes = language.suffixes();
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public String baseCodeSubmissionName() {
|
|
|
+ return baseCodeSubmissionName;
|
|
|
}
|
|
|
|
|
|
- public void setMaximumNumberOfComparisons(int maximumNumberOfComparisons) {
|
|
|
- this.maximumNumberOfComparisons = Math.max(maximumNumberOfComparisons, -1);
|
|
|
+ @Override
|
|
|
+ public Integer minimumTokenMatch() {
|
|
|
+ var language = language();
|
|
|
+ if (minimumTokenMatch == null && language != null)
|
|
|
+ return language.minimumTokenMatch();
|
|
|
+ return minimumTokenMatch;
|
|
|
}
|
|
|
|
|
|
- public void setMinimumTokenMatch(Integer minimumTokenMatch) {
|
|
|
- if (minimumTokenMatch != null && minimumTokenMatch < 1) {
|
|
|
- this.minimumTokenMatch = 1;
|
|
|
- } else {
|
|
|
- this.minimumTokenMatch = minimumTokenMatch;
|
|
|
+ private Set<String> readExclusionFile(final String exclusionFileName) {
|
|
|
+ try (BufferedReader reader = new BufferedReader(new FileReader(exclusionFileName, JPlagOptions.CHARSET))) {
|
|
|
+ final var excludedFileNames = reader.lines().collect(Collectors.toSet());
|
|
|
+ if (verbosity() == LONG && logger.isInfoEnabled()) {
|
|
|
+ logger.info("Excluded files:\n{}", String.join("\n", excludedFileNames));
|
|
|
+ }
|
|
|
+ return excludedFileNames;
|
|
|
+ } catch (IOException e) {
|
|
|
+ logger.error("Could not read exclusion file: " + e.getMessage(), e);
|
|
|
+ return Collections.emptySet();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void setSubmissionDirectories(List<String> submissionDirectories) {
|
|
|
- this.submissionDirectories = submissionDirectories;
|
|
|
- }
|
|
|
-
|
|
|
- public void setOldSubmissionDirectories(List<String> oldSubmissionDirectories) {
|
|
|
- this.oldSubmissionDirectories = oldSubmissionDirectories;
|
|
|
- }
|
|
|
-
|
|
|
- public void setSimilarityMetric(SimilarityMetric similarityMetric) {
|
|
|
- this.similarityMetric = similarityMetric;
|
|
|
- }
|
|
|
-
|
|
|
- public void setSimilarityThreshold(float similarityThreshold) {
|
|
|
+ private static double normalizeSimilarityThreshold(double similarityThreshold) {
|
|
|
if (similarityThreshold > 100) {
|
|
|
logger.warn("Maximum threshold of 100 used instead of {}", similarityThreshold);
|
|
|
- this.similarityThreshold = 100;
|
|
|
+ return 100;
|
|
|
} else if (similarityThreshold < 0) {
|
|
|
logger.warn("Minimum threshold of 0 used instead of {}", similarityThreshold);
|
|
|
- this.similarityThreshold = 0;
|
|
|
+ return 0;
|
|
|
} else {
|
|
|
- this.similarityThreshold = similarityThreshold;
|
|
|
+ return similarityThreshold;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void setSubdirectoryName(String subdirectoryName) {
|
|
|
- // Trim problematic file separators.
|
|
|
- this.subdirectoryName = (subdirectoryName == null) ? null : subdirectoryName.replace(File.separator, "");
|
|
|
- }
|
|
|
-
|
|
|
- public void setVerbosity(Verbosity verbosity) {
|
|
|
- this.verbosity = verbosity;
|
|
|
- }
|
|
|
-
|
|
|
- public void setClusteringOptions(ClusteringOptions clusteringOptions) {
|
|
|
- this.clusteringOptions = clusteringOptions;
|
|
|
+ private Integer normalizeMaximumNumberOfComparisons(Integer maximumNumberOfComparisons) {
|
|
|
+ return Math.max(maximumNumberOfComparisons, SHOW_ALL_COMPARISONS);
|
|
|
}
|
|
|
|
|
|
- private boolean hasFileSuffixes() {
|
|
|
- return fileSuffixes != null && fileSuffixes.length > 0;
|
|
|
+ private Integer normalizeMinimumTokenMatch(Integer minimumTokenMatch) {
|
|
|
+ return (minimumTokenMatch != null && minimumTokenMatch < 1) ? Integer.valueOf(1) : minimumTokenMatch;
|
|
|
}
|
|
|
-
|
|
|
- private boolean hasMinimumTokenMatch() {
|
|
|
- return minimumTokenMatch != null;
|
|
|
- }
|
|
|
-
|
|
|
}
|