From 87287179c6aa3fa3e5441eeaf29aac29016e16e5 Mon Sep 17 00:00:00 2001 From: zontreck Date: Tue, 5 Dec 2023 11:31:58 -0700 Subject: [PATCH] Updates argument parser to be more complete --- .gitignore | 4 +- build.gradle | 8 ++ .../dev/zontreck/ariaslib/args/Argument.java | 31 ++++--- .../zontreck/ariaslib/args/ArgumentType.java | 25 ++++++ .../dev/zontreck/ariaslib/args/Arguments.java | 41 ++++++--- .../ariaslib/args/ArgumentsBuilder.java | 20 +++++ .../ariaslib/args/ArgumentsParser.java | 87 ++++++++++++++++--- .../ariaslib/args/BooleanArgument.java | 27 ++++++ .../ariaslib/args/IntegerArgument.java | 21 +++++ .../zontreck/ariaslib/args/LongArgument.java | 21 +++++ .../ariaslib/args/StringArgument.java | 22 +++++ .../ariaslib/args/ArgumentsParserTest.java | 53 +++++++++++ 12 files changed, 319 insertions(+), 41 deletions(-) create mode 100644 src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/LongArgument.java create mode 100644 src/main/java/dev/zontreck/ariaslib/args/StringArgument.java create mode 100644 src/test/java/dev/zontreck/ariaslib/args/ArgumentsParserTest.java diff --git a/.gitignore b/.gitignore index 6bd4682..45def42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ # Ignore Gradle project-specific cache directory .gradle +.idea # Ignore Gradle build output directory build bin # Visual Studio Code -.vscode \ No newline at end of file +.vscode +*.class \ No newline at end of file diff --git a/build.gradle b/build.gradle index c6bbe13..921036b 100644 --- a/build.gradle +++ b/build.gradle @@ -55,8 +55,12 @@ repositories { dependencies { + implementation "dev.zontreck:EventsBus:${Bus_API}.${Bus_Patch}" api "dev.zontreck:EventsBus:${Bus_API}.${Bus_Patch}:sources" + + testImplementation platform('org.junit:junit-bom:5.9.1') + testImplementation 'org.junit.jupiter:junit-jupiter' } def MAVEN_PASSWORD_PROPERTY = "AriasCreationsMavenPassword" @@ -82,3 +86,7 @@ publishing { } } } + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/src/main/java/dev/zontreck/ariaslib/args/Argument.java b/src/main/java/dev/zontreck/ariaslib/args/Argument.java index aed27bb..54a2bf3 100644 --- a/src/main/java/dev/zontreck/ariaslib/args/Argument.java +++ b/src/main/java/dev/zontreck/ariaslib/args/Argument.java @@ -1,10 +1,9 @@ package dev.zontreck.ariaslib.args; -public class Argument { - public boolean isSet = false; +public abstract class Argument { public boolean hasValue = false; public String name; - private String value; + /** * Initializes a boolean only command line toggle @@ -12,24 +11,24 @@ public class Argument { * @param name The option name */ public Argument(String name) { - this(name, ""); + this.name = name; } /** - * Initializes the argument with a value + * Retrieves the current argument's type * - * @param name The name of the command line option - * @param value The value + * @return The argument type! */ - public Argument(String name, String value) { - if (value != "") hasValue = true; - isSet = true; - this.name = name; - this.value = value; - } + public abstract ArgumentType getType(); + - public String getValue() { - if (hasValue) return value; - else throw new IllegalArgumentException("No value"); + /** + * Retrieves the value. + * + * @return The value + * @throws IllegalArgumentException When there is no value + */ + public T getValue() throws IllegalArgumentException { + throw new IllegalArgumentException("No value"); } } diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java new file mode 100644 index 0000000..82c310b --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentType.java @@ -0,0 +1,25 @@ +package dev.zontreck.ariaslib.args; + +public enum ArgumentType { + /** + * This indicates a string. It may possibly have a default value + */ + STRING, + /** + * This indicates a boolean + *

+ * This may have a default value, which initiates a BooleanArgument + */ + BOOLEAN, + + /** + * This indicates a data type of integer + * The type of integer arg is determined by the length of the integer. + */ + INTEGER, + + /** + * This is a long value, which can hold larger values than a integer. The type of integer arg is determined by the length of the integer. + */ + LONG +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/Arguments.java b/src/main/java/dev/zontreck/ariaslib/args/Arguments.java index 0bcc00b..5bab9bc 100644 --- a/src/main/java/dev/zontreck/ariaslib/args/Arguments.java +++ b/src/main/java/dev/zontreck/ariaslib/args/Arguments.java @@ -10,21 +10,38 @@ public class Arguments { args.put(arg.name, arg); } - public String getArg(String argumentName, String defaultValue) { - if (!args.containsKey(argumentName)) { - return defaultValue; - } - - Argument arg = args.get(argumentName); - if (arg.hasValue) { - return arg.getValue(); - } else { - return defaultValue; - } - + /** + * Checks for and returns the argument + * + * @param argName The argument's name + * @return The argument instance, or null if not found + */ + public Argument getArg(String argName) { + if (hasArg(argName)) + return args.get(argName); + else return null; } + /** + * Checks if the argument is set. + * + * @param argName The argument's name to check for + * @return True if the argument is present. This does not indicate if the argument has a value + */ public boolean hasArg(String argName) { return args.containsKey(argName); } + + /** + * Checks the argument (if it exists), for whether a value is set + * + * @param argName This is the argument name + * @return True if a value is set + * @throws IllegalArgumentException If there is no such argument + */ + public boolean argHasValue(String argName) throws IllegalArgumentException { + if (hasArg(argName)) { + return getArg(argName).hasValue; + } else throw new IllegalArgumentException(("No such argument")); + } } diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java new file mode 100644 index 0000000..cf414bd --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsBuilder.java @@ -0,0 +1,20 @@ +package dev.zontreck.ariaslib.args; + +public class ArgumentsBuilder { + private Arguments args = new Arguments(); + + public static ArgumentsBuilder builder() { + return new ArgumentsBuilder(); + } + + public ArgumentsBuilder withArgument(Argument arg) { + args.setArg(arg); + return this; + } + + public Arguments build() + { + return args; + } + +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java index 5b19a37..18c8c16 100644 --- a/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java +++ b/src/main/java/dev/zontreck/ariaslib/args/ArgumentsParser.java @@ -2,33 +2,96 @@ package dev.zontreck.ariaslib.args; public class ArgumentsParser { - public static Arguments parseArguments(String[] args) { + public static Arguments parseArguments(String[] args, Arguments defaults) { Arguments arguments = new Arguments(); for (int i = 0; i < args.length; i++) { Argument arg = parseArgument(args[i]); if (arg != null) { - if (arg.hasValue && i + 1 < args.length) { - arguments.setArg(arg); - i++; // Skip next value as it's the argument's value - } else { - arguments.setArg(arg); // Argument without value, default to empty string + Argument defaultArg = null; + if (defaults.hasArg(arg.name)) { + defaultArg = defaults.getArg(arg.name); } + + if (i + 1 < args.length) { + i++; + } + + if (!arg.hasValue) { + if (defaultArg != null) { + arg = defaultArg; + } + } + + arguments.setArg(arg); } } return arguments; } + /** + * Parses and returns an argument with a type set + * @param arg The argument to parse with double tack + * @return Typed Argument + * @throws IllegalArgumentException when no type matches and the input is malformed in some way + */ public static Argument parseArgument(String arg) { if (arg.startsWith("--")) { - String[] parts = arg.split("=", 1); + String[] parts = arg.split("="); + String name = getNamePart(parts[0]); if (parts.length == 1) { - return new Argument(parts[0].substring(2)); - } else { - return new Argument(parts[0].substring(2), parts[1]); - } + return new BooleanArgument(name); + + } else if (parts.length == 2) { + String value = getValuePart(parts[1]); + ArgumentType typeOfArg = getArgumentType(value); + switch(typeOfArg) + { + case INTEGER: + { + return new IntegerArgument(name, Integer.parseInt(value)); + } + case LONG: + { + return new LongArgument(name, Long.parseLong(value)); + } + case BOOLEAN: + { + return new BooleanArgument(name); + } + default: + { + return new StringArgument(name, value); + } + } + } else throw new IllegalArgumentException("The argument is malformed. Remember to use --arg=val, or --toggle"); } else { - return null; // Not a valid argument format + throw new IllegalArgumentException("Not a valid argument format"); } } + + protected static String getNamePart(String entry) { + return entry.substring(2); + } + + protected static String getValuePart(String entry) { + return entry; + } + + protected static ArgumentType getArgumentType(String input) { + try { + Integer.parseInt(input); + return ArgumentType.INTEGER; + }catch(Exception e){} + try{ + Long.parseLong(input); + return ArgumentType.LONG; + }catch(Exception E){ + + } + + if(input.isEmpty()) + return ArgumentType.BOOLEAN; + else return ArgumentType.STRING; + } } diff --git a/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java b/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java new file mode 100644 index 0000000..de29fdd --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/BooleanArgument.java @@ -0,0 +1,27 @@ +package dev.zontreck.ariaslib.args; + +public class BooleanArgument extends Argument { + private boolean value; + + /** + * Initializes a boolean only command line toggle + * + * @param name The option name + */ + public BooleanArgument(String name) { + super(name); + + this.hasValue = true; + this.value = value; + } + + @Override + public Boolean getValue() { + return value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.BOOLEAN; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java b/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java new file mode 100644 index 0000000..bf8eb49 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/IntegerArgument.java @@ -0,0 +1,21 @@ +package dev.zontreck.ariaslib.args; + +public class IntegerArgument extends Argument { + private int value; + + public IntegerArgument(String name, int value) { + super(name); + this.hasValue = true; + this.value = value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.INTEGER; + } + + @Override + public Integer getValue() { + return value; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java b/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java new file mode 100644 index 0000000..c8a4c03 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/LongArgument.java @@ -0,0 +1,21 @@ +package dev.zontreck.ariaslib.args; + +public class LongArgument extends Argument { + private long value; + + public LongArgument(String name, long value) { + super(name); + this.hasValue = true; + this.value = value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.LONG; + } + + @Override + public Long getValue() { + return value; + } +} diff --git a/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java b/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java new file mode 100644 index 0000000..3575486 --- /dev/null +++ b/src/main/java/dev/zontreck/ariaslib/args/StringArgument.java @@ -0,0 +1,22 @@ +package dev.zontreck.ariaslib.args; + +public class StringArgument extends Argument { + + private String value; + + public StringArgument(String name, String value) { + super(name); + this.value = value; + this.hasValue = true; + } + + @Override + public String getValue() { + return value; + } + + @Override + public ArgumentType getType() { + return ArgumentType.STRING; + } +} diff --git a/src/test/java/dev/zontreck/ariaslib/args/ArgumentsParserTest.java b/src/test/java/dev/zontreck/ariaslib/args/ArgumentsParserTest.java new file mode 100644 index 0000000..3ead7e8 --- /dev/null +++ b/src/test/java/dev/zontreck/ariaslib/args/ArgumentsParserTest.java @@ -0,0 +1,53 @@ +package dev.zontreck.ariaslib.args; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.junit.jupiter.api.Assertions.*; + +public class ArgumentsParserTest { + + @ParameterizedTest + @ValueSource(strings = {"--test", "--arg", "--testing2"}) + void testGetNamePart(String entry) { + String arg = ArgumentsParser.getNamePart(entry); + assertFalse(arg.startsWith("--")); + assertFalse(arg.isEmpty()); + } + + @ParameterizedTest + @CsvSource(value = {"test", "test2", "281", "true"}) + void testGetValuePart(String entry) { + assertFalse(entry.isEmpty()); + } + + @ParameterizedTest + @ValueSource(strings = {"test", "1", "922337203685477580", ""}) + void testGetArgumentType(String input) + { + ArgumentType test = ArgumentsParser.getArgumentType(input); + System.out.println("Testing: " + input + "; Type: " + test); + if(input.startsWith("t")) + { + assertTrue(test == ArgumentType.STRING); + }else if(input.startsWith("1")) + { + assertTrue(test == ArgumentType.INTEGER); + } else if(input.startsWith("9")) + { + assertTrue(test == ArgumentType.LONG); + }else assertTrue(test == ArgumentType.BOOLEAN); + } + + @ParameterizedTest + @CsvSource(value = {"--test=1", "--enable", "--set=84375488888444", "--file=test.dat"}) + void testParseArgument(String arg) + { + Argument args = ArgumentsParser.parseArgument(arg); + assertFalse(args.name.isEmpty()); + assertTrue(args.hasValue); + + } + +}