+ * Project: envoy-client
- * Adds a command with according action and the number of arguments that should
- * be parsed if the command does not violate API constrictions to the map.
- *
- * @param command the string that must be inputted to execute the
- * given action
- * @param action the action that should be performed. To see why this
- * Function takes a {@code String[]}, see
- * {@link SystemCommand}
- * @param numberOfArguments the amount of arguments that need to be parsed for
- * the underlying function
- * @see SystemCommandsMap#isValidKey(String)
- * @since Envoy Client v0.2-beta
- */
- public void add(String command, Function
- * The approach to not throw an exception was taken so that an ugly try-catch
- * block for every addition to the system commands map could be avoided, an
- * error that
- * should only occur during implementation and not in production.
- *
- * @param command the key to examine
- * @return whether this key can be used in the map
- * @since Envoy Client v0.2-beta
- */
- public boolean isValidKey(String command) {
- final boolean valid = commandBounds.matcher(command).matches();
- if (!valid) logger
- .log(Level.WARNING,
- "The command \"" + command
- + "\" is not valid. As it will cause problems in execution, it will not be entered into the map. Only the characters "
- + commandBounds + "are allowed");
- return valid;
- }
+ public void add(String command, SystemCommand systemCommand) { if (isValidKey(command)) systemCommands.put(command, systemCommand); }
/**
* This method checks if the input String is a key in the map and returns the
* wrapped System command if present.
- * Its intended usage is after a "/" has been detected in the input String.
* It will return an empty optional if the value after the slash is not a key in
* the map, which is a valid case (i.e. input="3/4" and "4" is not a key in the
* map).
*
* Usage example:
- * Only one system command can be present, afterwards checking will not be
- * continued.
- *
- * @param raw the raw input string
- * @since Envoy Client v0.2-beta
- */
- public void checkForCommands(String raw) { checkForCommands(raw, 0); }
-
- /**
- * Takes a 'raw' string (the whole input) and checks from {@code fromIndex} on
- * if a command is present
- * after a "/". If that is the case, it will be executed.
- *
- * Only one system command can be present, afterwards checking will not be
- * continued.
- *
- * @param raw the raw input string
- * @param fromIndex the index to start checking on
- * @since Envoy Client v0.2-beta
- */
- public void checkForCommands(String raw, int fromIndex) {
- // The minimum length of a command is "/" + a letter, hence raw.length()-2 is
- // the highest index needed
- for (int i = fromIndex; i < raw.length() - 2; i++)
- // possibly a command was detected
- if (raw.charAt(i) == '/') {
- executeIfPresent(getCommand(raw, i));
- // the command was executed successfully - no further checking needed
- if (commandExecuted) {
- commandExecuted = false;
- logger.log(Level.FINE, "executed system command " + getCommand(raw, i));
- break;
- }
- }
- }
-
- /**
- * This method ensures that the "/" of a {@link SystemCommand} is stripped.
+ * The approach to not throw an exception was taken so that an ugly try-catch
+ * block for every addition to the system commands map could be avoided, an
+ * error that should only occur during implementation and not in production.
+ *
+ * @param command the key to examine
+ * @return whether this key can be used in the map
+ * @since Envoy Client v0.2-beta
+ */
+ public boolean isValidKey(String command) {
+ final boolean valid = commandPattern.matcher(command).matches();
+ if (!valid) logger.log(Level.WARNING,
+ "The command \"" + command
+ + "\" is not valid. As it will cause problems in execution, it will not be entered into the map. Only the characters "
+ + commandPattern + "are allowed");
+ return valid;
+ }
+
+ /**
+ * Takes a 'raw' string (the whole input) and checks if "/" is the first visible
+ * character and then checks if a command is present after that "/". If that is
+ * the case, it will be executed.
+ *
+ *
+ * @param raw the raw input string
+ * @return whether a command could be found
+ * @since Envoy Client v0.2-beta
+ */
+ public boolean executeIfAnyPresent(String raw) {
+ // possibly a command was detected and could be executed
+ final var raw2 = raw.stripLeading();
+ final var commandFound = raw2.startsWith("/") ? executeIfPresent(raw2) : false;
+ // the command was executed successfully - no further checking needed
+ if (commandFound) logger.log(Level.FINE, "executed system command " + getCommand(raw2));
+ return commandFound;
+ }
/**
* This method checks if the input String is a key in the map and executes the
@@ -242,33 +133,55 @@ public final class SystemCommandsMap {
* Usage example:
- * Project: envoy-client
+ * File: SystemCommandBuilder.java
+ * Created: 23.07.2020
+ *
+ * @author Leon Hofmeister
+ * @since Envoy Client v0.2-beta
+ */
+public class SystemCommandBuilder {
+
+ private int numberOfArguments;
+ private Consumer> action;
+ private List
> action) {
+ this.action = action;
+ return this;
+ }
+
+ /**
+ * @param description the description to set
+ * @return this {@code SystemCommandBuilder}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommandBuilder setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * @param relevance the relevance to set
+ * @return this {@code SystemCommandBuilder}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommandBuilder setRelevance(int relevance) {
+ this.relevance = relevance;
+ return this;
+ }
+
+ /**
+ * @param defaults the defaults to set
+ * @return this {@code SystemCommandBuilder}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommandBuilder setDefaults(String... defaults) {
+ this.defaults = List.of(defaults);
+ return this;
+ }
+
+ /**
+ * Resets all values stored.
+ *
+ * @return this {@code SystemCommandBuilder}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommandBuilder reset() {
+ numberOfArguments = 0;
+ action = null;
+ defaults = new ArrayList<>();
+ description = "";
+ relevance = 0;
+ return this;
+ }
+
+ /**
+ * Builds a {@code SystemCommand} based upon the previously entered data.
+ *
+ * @return the built {@code SystemCommand}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommand build() { return build(true); }
+
+ /**
+ * Builds a {@code SystemCommand} based upon the previously entered data.
+ * {@code SystemCommand#numberOfArguments} will be set to 0, regardless of the
+ * previous value.
+ * At the end, this {@code SystemCommandBuilder} will be reset.
+ *
+ * @return the built {@code SystemCommand}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommand buildNoArg() {
+ numberOfArguments = 0;
+ return build(true);
+ }
+
+ /**
+ * Builds a {@code SystemCommand} based upon the previously entered data.
+ * {@code SystemCommand#numberOfArguments} will be set to use the rest of the
+ * string as argument, regardless of the previous value.
+ * At the end, this {@code SystemCommandBuilder} will be reset.
+ *
+ * @return the built {@code SystemCommand}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommand buildRemainingArg() {
+ numberOfArguments = -1;
+ return build(true);
+ }
+
+ /**
+ * Builds a {@code SystemCommand} based upon the previously entered data.
+ * At the end, this {@code SystemCommandBuilder} can be reset but must
+ * not be.
+ *
+ * @param reset whether this {@code SystemCommandBuilder} should be reset
+ * afterwards.
+ * This can be useful if another command wants to execute something
+ * similar
+ * @return the built {@code SystemCommand}
+ * @since Envoy Client v0.2-beta
+ */
+ public SystemCommand build(boolean reset) {
+ final var sc = new SystemCommand(action, numberOfArguments, defaults, description);
+ sc.setRelevance(relevance);
+ if (reset) reset();
+ return sc;
+ }
+}
diff --git a/client/src/main/java/envoy/client/data/commands/SystemCommandsMap.java b/client/src/main/java/envoy/client/data/commands/SystemCommandsMap.java
index 4ba6dfb..cfcb0a4 100644
--- a/client/src/main/java/envoy/client/data/commands/SystemCommandsMap.java
+++ b/client/src/main/java/envoy/client/data/commands/SystemCommandsMap.java
@@ -21,200 +21,46 @@ import envoy.util.EnvoyLog;
*/
public final class SystemCommandsMap {
- private final HashMap
- * (allowed chars are a-zA-Z0-9_:!()?.,;-)
- *
* {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}
- * {@code systemCommands.add("example", Function.identity, 1);}
+ * {@code Button button = new Button();}
+ * {@code systemCommands.add("example", text -> button.setText(text.get(0), 1);}
* {@code ....}
* user input: {@code "/example xyz ..."}
- * {@code systemCommands.checkPresent("example xyz ...")}
- * result: {@code SystemCommand[action=Function.identity, numberOfArguments=1]}
+ * {@code systemCommands.get("example xyz ...")} or
+ * {@code systemCommands.get("/example xyz ...")}
+ * result: {@code Optional
- * It returns the command as (most likely) entered as key in the map starting
- * from {@code fromIndex}.
- * It should only be called on strings that contain a "/" .
- *
- * @param raw the input
- * @param fromIndex the index from which to expect the system command -
- * regardless of whether the slash is still present at this
- * index
- * @return the command as entered in the map
- * @since Envoy Client v0.2-beta
- * @apiNote this method will (most likely) not return anything useful if
- * whatever is entered after the slash is not a system command. Only
- * exception: for recommendation purposes.
- */
- public String getCommand(String raw, int fromIndex) {
- final var index = raw.indexOf(' ');
- return raw.substring(fromIndex + raw.charAt(0) == '/' ? 1 : 0, index < 1 ? raw.length() : index);
- }
+ public Optional
@@ -229,7 +75,52 @@ public final class SystemCommandsMap {
* whatever is entered after the slash is not a system command. Only
* exception: for recommendation purposes.
*/
- public String getCommand(String raw) { return getCommand(raw, 0); }
+ public String getCommand(String raw) {
+ final var trimmed = raw.stripLeading();
+ final var index = trimmed.indexOf(' ');
+ return trimmed.substring(trimmed.charAt(0) == '/' ? 1 : 0, index < 1 ? trimmed.length() : index);
+ }
+
+ /**
+ * Examines whether a key can be put in the map and logs it with
+ * {@code Level.WARNING} if that key violates API constrictions.
+ * (allowed chars are a-zA-Z0-9_:!()?.,;-)
+ *
* {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}
* {@code Button button = new Button();}
- * {@code systemCommands.add("example", (words)-> button.setText(words[0]), 1);}
+ * {@code systemCommands.add("example", (words)-> button.setText(words.get(0), 1);}
* {@code ....}
* user input: {@code "/example xyz ..."}
* {@code systemCommands.executeIfPresent("example xyz ...")}
* result: {@code button.getText()=="xyz"}
*
- * @param input the input string given by the user, excluding the "/"
+ * @param input the input string given by the user
+ * @return whether a command could be found
* @since Envoy Client v0.2-beta
*/
- public void executeIfPresent(String input) {
- checkPresent(input).ifPresent(systemCommand -> {
+ public boolean executeIfPresent(String input) {
+ final var command = getCommand(input);
+ final var value = get(command);
+ value.ifPresent(systemCommand -> {
// Splitting the String so that the leading command including the first " " is
// removed and only as many following words as allowed by the system command
// persist
- final var remainingString = input.substring(input.indexOf(" ") + 1);
- // TODO: Current implementation will fail in certain cases, i.e. two spaces
- // behind each other (" "), not enough words, ...
- final var arguments = Arrays.copyOfRange(remainingString.split(" "), 0, systemCommand.getNumberOfArguments());
+ final var arguments = extractArguments(input, systemCommand);
// Executing the function
try {
- systemCommand.getAction().apply(arguments);
- commandExecuted = true;
+ systemCommand.getAction().accept(arguments);
systemCommand.onCall();
} catch (final Exception e) {
- logger.log(Level.WARNING, "The system command " + getCommand(input) + " threw an exception: ", e);
+ logger.log(Level.WARNING, "The system command " + command + " threw an exception: ", e);
}
});
+ return value.isPresent();
+ }
+
+ /**
+ * Supplies missing values with default values.
+ *
+ * @param input the input String
+ * @param systemCommand the command that is expected
+ * @return the list of arguments that can be used to parse the systemCommand
+ * @since Envoy Client v0.2-beta
+ */
+ private List
* Otherwise the given function will be executed on the recommendations.
*
- * @param input the input
+ * @param input the input string
* @param action the action that should be taken for the recommendations, if any
* are present
* @since Envoy Client v0.2-beta
*/
- public void requestRecommendations(String input, Function
- * The word beginning at {@code fromIndex} is used for the recommendations and
- * it does not matter if the "/" is at its beginning or not.
- * If none are present, nothing will be done.
- * Otherwise the given function will be executed on the recommendations.
- *
- * @param input the input
- * @param fromIndex the index to start checking on
- * @param action the action that should be taken for the recommendations, if
- * any are present
- * @since Envoy Client v0.2-beta
- */
- private void requestRecommendations(String input, int fromIndex, Function
+ * Will only work for {@code SystemCommand}s whose argument counter is bigger
+ * than 1.
+ *
+ * @param textArguments the arguments that were parsed from the text
+ * @param toEvaluate the system command whose default values should be used
+ * @return the final argument list
+ * @since Envoy Client v0.2-beta
+ * @apiNote this method will insert an empty String if the size of the list
+ * given to the {@code SystemCommand} is smaller than its argument
+ * counter and no more text arguments could be found.
+ */
+ private List
- * File: InterruptEvent.java
- * Created: 23.07.2020
- *
- * @author Leon Hofmeister
- * @since Envoy Client v0.2-beta
- */
-public class InterruptEvent extends Event