Browse Source

Move argument parsing into the explicit CLI API and use more compact syntax.

Timur Sağlam 5 years ago
parent
commit
fc19bf7555

+ 14 - 40
jplag/src/main/java/jplag/CLI.java

@@ -12,6 +12,7 @@ import static jplag.CommandLineArgument.STORED_MATCHES;
 import static jplag.CommandLineArgument.SUBDIRECTORY;
 import static jplag.CommandLineArgument.SUFFIXES;
 import static jplag.CommandLineArgument.VERBOSITY;
+import static jplag.CommandLineArgument.RESULT_FOLDER;
 
 import java.io.File;
 import java.util.Random;
@@ -52,7 +53,7 @@ public class CLI {
             JPlag program = new JPlag(options);
             System.out.println("JPlag initialized");
             JPlagResult result = program.run();
-            File reportDir = new File(arguments.getString("r"));
+            File reportDir = new File(arguments.getString(RESULT_FOLDER.flag()));
             Report report = new Report(reportDir);
             report.writeResult(result);
         } catch (ExitException exception) {
@@ -92,51 +93,24 @@ public class CLI {
      * @return the newly built options.F
      */
     public JPlagOptions buildOptionsFromArguments(Namespace namespace) {
-        String fileSuffixString = namespace.getString(SUFFIXES.flag());
+        String fileSuffixString = SUFFIXES.getFrom(namespace);
         String[] fileSuffixes = new String[] {};
         if (fileSuffixString != null) {
             fileSuffixes = fileSuffixString.replaceAll("\\s+", "").split(",");
         }
-        LanguageOption language = LanguageOption.fromDisplayName(namespace.getString(LANGUAGE.flag()));
-        JPlagOptions options = new JPlagOptions(namespace.getString(ROOT_DIRECTORY.flag()), language);
-        options.setBaseCodeSubmissionName(namespace.getString(BASE_CODE.flag()));
-        options.setVerbosity(Verbosity.fromOption(namespace.getString(VERBOSITY.flag())));
-        options.setDebugParser(namespace.getBoolean(DEBUG.flag()));
-        options.setSubdirectoryName(namespace.getString(SUBDIRECTORY.flag()));
+        LanguageOption language = LanguageOption.fromDisplayName(LANGUAGE.getFrom(namespace));
+        JPlagOptions options = new JPlagOptions(ROOT_DIRECTORY.getFrom(namespace), language);
+        options.setBaseCodeSubmissionName(BASE_CODE.getFrom(namespace));
+        options.setVerbosity(Verbosity.fromOption(VERBOSITY.getFrom(namespace)));
+        options.setDebugParser(DEBUG.getFrom(namespace));
+        options.setSubdirectoryName(SUBDIRECTORY.getFrom(namespace));
         options.setFileSuffixes(fileSuffixes);
-        options.setExclusionFileName(namespace.getString(EXCLUDE_FILE.flag()));
-        ComparisonMode.fromName(namespace.getString(COMPARISON_MODE.flag())).ifPresentOrElse(it -> options.setComparisonMode(it),
+        options.setExclusionFileName(EXCLUDE_FILE.getFrom(namespace));
+        options.setMinTokenMatch(MIN_TOKEN_MATCH.getFrom(namespace));
+        options.setSimilarityThreshold(SIMILARITY_THRESHOLD.getFrom(namespace));
+        options.setMaxNumberOfMatches(STORED_MATCHES.getFrom(namespace));
+        ComparisonMode.fromName(COMPARISON_MODE.getFrom(namespace)).ifPresentOrElse(it -> options.setComparisonMode(it),
                 () -> System.out.println("Unknown comparison mode, using default mode!"));
-
-        String minTokenMatch = namespace.getString(MIN_TOKEN_MATCH.flag());
-        if (minTokenMatch != null) {
-            try {
-                options.setMinTokenMatch(Integer.parseInt(minTokenMatch));
-            } catch (NumberFormatException e) {
-                System.out.println("Illegal comparison sensitivity. Ignoring input and taking language default value.");
-            }
-        }
-
-        String similarityThreshold = namespace.getString(SIMILARITY_THRESHOLD.flag());
-        if (similarityThreshold != null) {
-            try {
-                options.setSimilarityThreshold(Float.parseFloat(similarityThreshold));
-            } catch (NumberFormatException e) {
-                System.out.println("Illegal similarity threshold. Taking 0 as default value.");
-                options.setSimilarityThreshold(0); // TODO SH: Remove code duplication
-            }
-        }
-
-        String maxNumberOfMatches = namespace.getString(STORED_MATCHES.flag());
-        if (maxNumberOfMatches != null) {
-            try {
-                options.setMaxNumberOfMatches(Integer.parseInt(maxNumberOfMatches));
-            } catch (NumberFormatException e) {
-                System.out.println("Illegal maximum number of matches. Taking 30 as default value.");
-                options.setMaxNumberOfMatches(30); // TODO SH: Remove code duplication
-            }
-        }
-
         return options;
     }
 

+ 38 - 29
jplag/src/main/java/jplag/CommandLineArgument.java

@@ -10,57 +10,52 @@ import java.util.Optional;
 import jplag.options.LanguageOption;
 import jplag.strategy.ComparisonMode;
 import net.sourceforge.argparse4j.inf.Argument;
-import net.sourceforge.argparse4j.inf.ArgumentAction;
 import net.sourceforge.argparse4j.inf.ArgumentParser;
+import net.sourceforge.argparse4j.inf.Namespace;
 
 /**
  * Command line arguments for the JPlag CLI. Each argument is defined through an enuemral.
  * @author Timur Saglam
  */
 public enum CommandLineArgument {
-    ROOT_DIRECTORY("rootDir", "The root-directory that contains all submissions"),
-    LANGUAGE("-l", "Select the language to parse the submissions", LanguageOption.getDefault().getDisplayName(), LanguageOption.getAllDisplayNames()),
-    BASE_CODE("-bc", "Name of the directory which contains the base code (common framework used in all submissions)"),
-    VERBOSITY("-v", "Verbosity", "quiet", List.of("parser", "quiet", "long", "details")), // TODO SH: Replace verbosity when integrating a real logging library
-    DEBUG("-d", "(Debug) parser. Non-parsable files will be stored", storeTrue()),
-    SUBDIRECTORY("-S", "Look in directories <root-dir>/*/<dir> for programs"),
-    SUFFIXES("-p", "comma-separated list of all filename suffixes that are included"),
-    EXCLUDE_FILE("-x", "All files named in this file will be ignored in the comparison (line-separated list)"),
-    MIN_TOKEN_MATCH("-t", "Tune the sensitivity of the comparison. A smaller <n> increases the sensitivity"),
-    SIMILARITY_THRESHOLD("-m", "Match similarity threshold [0-100]: All matches above this threshold will be saved", 0f), // TODO TS deduplicate default values
-    STORED_MATCHES("-n", "Maximum number of matches that will be saved. If set to -1 all matches will be saved", 30), 
-    RESULT_FOLDER("-r", "Name of directory in which the comparison results will be stored", "result"),
-    COMPARISON_MODE("-c", "Comparison mode used to compare the programs", NORMAL.getName(), ComparisonMode.allNames());
+    ROOT_DIRECTORY("rootDir", String.class, "The root-directory that contains all submissions"),
+    LANGUAGE("-l", String.class, "Select the language to parse the submissions", LanguageOption.getDefault().getDisplayName(), LanguageOption.getAllDisplayNames()),
+    BASE_CODE("-bc", String.class, "Name of the directory which contains the base code (common framework used in all submissions)"),
+    VERBOSITY("-v", String.class, "Verbosity", "quiet", List.of("parser", "quiet", "long", "details")), // TODO SH: Replace verbosity when integrating  a real logging library
+    DEBUG("-d", Boolean.class, "(Debug) parser. Non-parsable files will be stored"),
+    SUBDIRECTORY("-S", String.class, "Look in directories <root-dir>/*/<dir> for programs"),
+    SUFFIXES("-p", String.class, "comma-separated list of all filename suffixes that are included"),
+    EXCLUDE_FILE("-x", String.class, "All files named in this file will be ignored in the comparison (line-separated list)"),
+    MIN_TOKEN_MATCH("-t", Integer.class, "Tune the sensitivity of the comparison. A smaller <n> increases the sensitivity"),
+    SIMILARITY_THRESHOLD("-m", Float.class, "Match similarity threshold [0-100]: All matches above this threshold will be saved", 0f), // TODO TS deduplicate default values
+    STORED_MATCHES("-n", Integer.class, "Maximum number of matches that will be saved. If set to -1 all matches will be saved", 30),
+    RESULT_FOLDER("-r", String.class, "Name of directory in which the comparison results will be stored", "result"),
+    COMPARISON_MODE("-c", String.class, "Comparison mode used to compare the programs", NORMAL.getName(), ComparisonMode.allNames());
 
     private final String flag;
     private final String helptext;
     private final Optional<Object> defaultValue;
     private final Optional<Collection<String>> choices;
-    private final Optional<ArgumentAction> action;
+    private final Class<?> type;
 
-    private CommandLineArgument(String flag, String helpText, Optional<Object> defaultValue, Optional<Collection<String>> choices,
-            Optional<ArgumentAction> action) {
+    private CommandLineArgument(String flag, Class<?> type, String helpText, Optional<Object> defaultValue, Optional<Collection<String>> choices) {
         this.flag = flag;
         this.helptext = helpText;
+        this.type = type;
         this.defaultValue = defaultValue;
         this.choices = choices;
-        this.action = action;
     }
 
-    private CommandLineArgument(String flag, String helpText, Object defaultValue, Collection<String> choices) {
-        this(flag, helpText, Optional.of(defaultValue), Optional.of(choices), Optional.empty());
+    private CommandLineArgument(String flag, Class<?> type, String helpText, Object defaultValue, Collection<String> choices) {
+        this(flag, type, helpText, Optional.of(defaultValue), Optional.of(choices));
     }
 
-    private CommandLineArgument(String flag, String helpText, Object defaultValue) {
-        this(flag, helpText, Optional.of(defaultValue), Optional.empty(), Optional.empty());
+    private CommandLineArgument(String flag, Class<?> type, String helpText, Object defaultValue) {
+        this(flag, type, helpText, Optional.of(defaultValue), Optional.empty());
     }
 
-    private CommandLineArgument(String flag, String helpText) {
-        this(flag, helpText, Optional.empty(), Optional.empty(), Optional.empty());
-    }
-
-    private CommandLineArgument(String flag, String helpText, ArgumentAction action) {
-        this(flag, helpText, Optional.empty(), Optional.empty(), Optional.of(action));
+    private CommandLineArgument(String flag, Class<?> type, String helpText) {
+        this(flag, type, helpText, Optional.empty(), Optional.empty());
     }
 
     /**
@@ -71,7 +66,21 @@ public enum CommandLineArgument {
         Argument argument = parser.addArgument(flag).help(helptext);
         choices.ifPresent(it -> argument.choices(it));
         defaultValue.ifPresent(it -> argument.setDefault(it));
-        action.ifPresent(it -> argument.action(it));
+        argument.type(type);
+        if (type == Boolean.class) {
+            argument.action(storeTrue());
+        }
+    }
+
+    /**
+     * Returns the value of this argument. Convenience method for {@link Namespace#get(String)} and
+     * {@link CommandLineArgument#flag()}.
+     * @param <T> is the argument type.
+     * @param namespace stores a value for the argument.
+     * @return the argument value.
+     */
+    public <T> T getFrom(Namespace namespace) {
+        return namespace.get(flag());
     }
 
     /**

+ 3 - 1
jplag/src/main/java/jplag/options/JPlagOptions.java

@@ -236,8 +236,10 @@ public class JPlagOptions {
 
     public void setSimilarityThreshold(float similarityThreshold) {
         if (similarityThreshold > 100) {
+            System.out.println("Maximum threshold of 100 used instead of " + similarityThreshold);
             this.similarityThreshold = 100;
         } else if (similarityThreshold < 0) {
+            System.out.println("Minimum threshold of 0 used instead of " + similarityThreshold);
             this.similarityThreshold = 0;
         } else {
             this.similarityThreshold = similarityThreshold;
@@ -245,7 +247,7 @@ public class JPlagOptions {
     }
 
     public void setMaxNumberOfMatches(int maxNumberOfMatches) {
-        if(maxNumberOfMatches < -1) {
+        if (maxNumberOfMatches < -1) {
             this.maxNumberOfMatches = -1;
         } else {
             this.maxNumberOfMatches = maxNumberOfMatches;