Added default values, SystemCommandBuilder
Additionally removed sending of SystemCommands as messages and added sorting of recommendations by relevance.
This commit is contained in:
		@@ -1,52 +0,0 @@
 | 
				
			|||||||
package envoy.client.data.commands;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.function.Function;
 | 
					 | 
				
			||||||
import java.util.function.Supplier;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import envoy.client.event.InterruptEvent;
 | 
					 | 
				
			||||||
import envoy.event.EventBus;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This is a Envoy-specific subclass that allows
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Project: <strong>envoy-client</strong><br>
 | 
					 | 
				
			||||||
 * File: <strong>InterruptingSystemCommand.java</strong><br>
 | 
					 | 
				
			||||||
 * Created: <strong>23.07.2020</strong><br>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author Leon Hofmeister
 | 
					 | 
				
			||||||
 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class InterruptingSystemCommand extends SystemCommand {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private static final EventBus eventBus = EventBus.getInstance();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * The reason why an {@link InterruptEvent} will be dispatched from this class.
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public static final String interruptionReason = "command executed";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Constructs a new {@code SystemCommand}.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @param action            the action that should be performed
 | 
					 | 
				
			||||||
	 * @param numberOfArguments the amount of arguments that need to be parsed for
 | 
					 | 
				
			||||||
	 *                          the underlying function
 | 
					 | 
				
			||||||
	 * @param description       the description of this {@code SystemCommand}
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public InterruptingSystemCommand(Function<String[], Void> action, int numberOfArguments, String description) {
 | 
					 | 
				
			||||||
		super(action, numberOfArguments, description);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	public void onCall() {
 | 
					 | 
				
			||||||
		super.onCall();
 | 
					 | 
				
			||||||
		eventBus.dispatch(new InterruptEvent(interruptionReason));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	@Override
 | 
					 | 
				
			||||||
	public void onCall(Supplier<Void> consumer) {
 | 
					 | 
				
			||||||
		super.onCall(consumer);
 | 
					 | 
				
			||||||
		eventBus.dispatch(new InterruptEvent(interruptionReason));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,6 +1,9 @@
 | 
				
			|||||||
package envoy.client.data.commands;
 | 
					package envoy.client.data.commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.function.Function;
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.Objects;
 | 
				
			||||||
 | 
					import java.util.function.Consumer;
 | 
				
			||||||
import java.util.function.Supplier;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -8,7 +11,7 @@ import java.util.function.Supplier;
 | 
				
			|||||||
 * action and a number of arguments that should be used as input for this
 | 
					 * action and a number of arguments that should be used as input for this
 | 
				
			||||||
 * function.
 | 
					 * function.
 | 
				
			||||||
 * No {@code SystemCommand} can return anything.
 | 
					 * No {@code SystemCommand} can return anything.
 | 
				
			||||||
 * Every {@code SystemCommand} must have as argument type {@code String[]} so
 | 
					 * Every {@code SystemCommand} must have as argument type {@code List<String>} so
 | 
				
			||||||
 * that the words following the indicator String can be used as input of the
 | 
					 * that the words following the indicator String can be used as input of the
 | 
				
			||||||
 * function. This approach has one limitation:<br>
 | 
					 * function. This approach has one limitation:<br>
 | 
				
			||||||
 * <b>Order matters!</b> Changing the order of arguments will likely result in
 | 
					 * <b>Order matters!</b> Changing the order of arguments will likely result in
 | 
				
			||||||
@@ -23,35 +26,39 @@ import java.util.function.Supplier;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public class SystemCommand implements OnCall {
 | 
					public class SystemCommand implements OnCall {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected int relevance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * The argument count of the command.
 | 
						 * The argument count of the command.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected final int numberOfArguments;
 | 
						protected final int numberOfArguments;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * This function takes a {@code String[]} as argument because automatically
 | 
						 * This function takes a {@code List<String>} as argument because automatically
 | 
				
			||||||
	 * {@code SystemCommand#numberOfArguments} words following the necessary command
 | 
						 * {@code SystemCommand#numberOfArguments} words following the necessary command
 | 
				
			||||||
	 * will be put into this array.
 | 
						 * will be put into this list.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @see String#split(String)
 | 
						 * @see String#split(String)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	protected final Function<String[], Void> action;
 | 
						protected final Consumer<List<String>> action;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected final String description;
 | 
						protected final String description;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	protected int relevance;
 | 
						protected final List<String> defaults;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Constructs a new {@code SystemCommand}.
 | 
						 * Constructs a new {@code SystemCommand}.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param action            the action performed by the command
 | 
						 * @param action            the action performed by the command
 | 
				
			||||||
	 * @param numberOfArguments the argument count accepted by the action
 | 
						 * @param numberOfArguments the argument count accepted by the action
 | 
				
			||||||
 | 
						 * @param defaults          the default values for the corresponding arguments
 | 
				
			||||||
	 * @param description       the description of this {@code SystemCommand}
 | 
						 * @param description       the description of this {@code SystemCommand}
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public SystemCommand(Function<String[], Void> action, int numberOfArguments, String description) {
 | 
						public SystemCommand(Consumer<List<String>> action, int numberOfArguments, List<String> defaults, String description) {
 | 
				
			||||||
		this.numberOfArguments	= numberOfArguments;
 | 
							this.numberOfArguments	= numberOfArguments;
 | 
				
			||||||
		this.action				= action;
 | 
							this.action				= action;
 | 
				
			||||||
 | 
							this.defaults			= defaults == null ? new ArrayList<>() : defaults;
 | 
				
			||||||
		this.description		= description;
 | 
							this.description		= description;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,7 +66,7 @@ public class SystemCommand implements OnCall {
 | 
				
			|||||||
	 * @return the action that should be performed
 | 
						 * @return the action that should be performed
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Function<String[], Void> getAction() { return action; }
 | 
						public Consumer<List<String>> getAction() { return action; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return the argument count of the command
 | 
						 * @return the argument count of the command
 | 
				
			||||||
@@ -85,12 +92,44 @@ public class SystemCommand implements OnCall {
 | 
				
			|||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void setRelevance(int relevance) { this.relevance = relevance; }
 | 
						public void setRelevance(int relevance) { this.relevance = relevance; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Increments the relevance of this {@code SystemCommand}.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void onCall() { relevance++; }
 | 
						public void onCall() { relevance++; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Increments the relevance of this {@code SystemCommand} and executes the
 | 
				
			||||||
 | 
						 * supplier.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public void onCall(Supplier<Void> consumer) {
 | 
						public void onCall(Supplier<Void> consumer) {
 | 
				
			||||||
		onCall();
 | 
							onCall();
 | 
				
			||||||
		consumer.get();
 | 
							consumer.get();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @return the defaults
 | 
				
			||||||
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public List<String> getDefaults() { return defaults; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public int hashCode() { return Objects.hash(action); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public boolean equals(Object obj) {
 | 
				
			||||||
 | 
							if (this == obj) return true;
 | 
				
			||||||
 | 
							if (obj == null) return false;
 | 
				
			||||||
 | 
							if (getClass() != obj.getClass()) return false;
 | 
				
			||||||
 | 
							final SystemCommand other = (SystemCommand) obj;
 | 
				
			||||||
 | 
							return Objects.equals(action, other.action);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@Override
 | 
				
			||||||
 | 
						public String toString() {
 | 
				
			||||||
 | 
							return "SystemCommand [relevance=" + relevance + ", numberOfArguments=" + numberOfArguments + ", "
 | 
				
			||||||
 | 
									+ (action != null ? "action=" + action + ", " : "") + (description != null ? "description=" + description + ", " : "")
 | 
				
			||||||
 | 
									+ (defaults != null ? "defaults=" + defaults : "") + "]";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,144 @@
 | 
				
			|||||||
 | 
					package envoy.client.data.commands;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					import java.util.function.Consumer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This class acts as a builder for {@link SystemCommand}s.
 | 
				
			||||||
 | 
					 * <p>
 | 
				
			||||||
 | 
					 * Project: <strong>envoy-client</strong><br>
 | 
				
			||||||
 | 
					 * File: <strong>SystemCommandBuilder.java</strong><br>
 | 
				
			||||||
 | 
					 * Created: <strong>23.07.2020</strong><br>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @author Leon Hofmeister
 | 
				
			||||||
 | 
					 * @since Envoy Client v0.2-beta
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class SystemCommandBuilder {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private int						numberOfArguments;
 | 
				
			||||||
 | 
						private Consumer<List<String>>	action;
 | 
				
			||||||
 | 
						private List<String>			defaults;
 | 
				
			||||||
 | 
						private String					description;
 | 
				
			||||||
 | 
						private int						relevance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param numberOfArguments the numberOfArguments to set
 | 
				
			||||||
 | 
						 * @return this {@code SystemCommandBuilder}
 | 
				
			||||||
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public SystemCommandBuilder setNumberOfArguments(int numberOfArguments) {
 | 
				
			||||||
 | 
							this.numberOfArguments = numberOfArguments;
 | 
				
			||||||
 | 
							return this;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * @param action the action to set
 | 
				
			||||||
 | 
						 * @return this {@code SystemCommandBuilder}
 | 
				
			||||||
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						public SystemCommandBuilder setAction(Consumer<List<String>> 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.<br>
 | 
				
			||||||
 | 
						 * {@code SystemCommand#numberOfArguments} will be set to 0, regardless of the
 | 
				
			||||||
 | 
						 * previous value.<br>
 | 
				
			||||||
 | 
						 * 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.<br>
 | 
				
			||||||
 | 
						 * {@code SystemCommand#numberOfArguments} will be set to use the rest of the
 | 
				
			||||||
 | 
						 * string as argument, regardless of the previous value.<br>
 | 
				
			||||||
 | 
						 * 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.<br>
 | 
				
			||||||
 | 
						 * At the end, this {@code SystemCommandBuilder} <b>can</b> be reset but must
 | 
				
			||||||
 | 
						 * not be.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @param reset whether this {@code SystemCommandBuilder} should be reset
 | 
				
			||||||
 | 
						 *              afterwards.<br>
 | 
				
			||||||
 | 
						 *              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;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -21,200 +21,46 @@ import envoy.util.EnvoyLog;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public final class SystemCommandsMap {
 | 
					public final class SystemCommandsMap {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final HashMap<String, SystemCommand> systemCommands = new HashMap<>();
 | 
						private final Map<String, SystemCommand> systemCommands = new HashMap<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private final Pattern commandBounds = Pattern.compile("^[a-zA-Z0-9_:!\\(\\)\\?\\.\\,\\;\\-]+$");
 | 
						private final Pattern commandPattern = Pattern.compile("^[a-zA-Z0-9_:!\\(\\)\\?\\.\\,\\;\\-]+$");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private static final Logger logger = EnvoyLog.getLogger(SystemCommandsMap.class);
 | 
						private static final Logger logger = EnvoyLog.getLogger(SystemCommandsMap.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private boolean commandExecuted;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Adds a new command to the map if the command name is valid.
 | 
						 * Adds a new command to the map if the command name is valid.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param command           the string that must be inputted to execute the
 | 
						 * @param command       the input string to execute the
 | 
				
			||||||
	 *                          given action
 | 
						 *                      given action
 | 
				
			||||||
	 * @param action            the action that should be performed
 | 
						 * @param systemCommand the command to add - can be built using
 | 
				
			||||||
	 * @param numberOfArguments the amount of arguments that need to be parsed for
 | 
						 *                      {@link SystemCommandBuilder}
 | 
				
			||||||
	 *                          the underlying function
 | 
					 | 
				
			||||||
	 * @see SystemCommandsMap#isValidKey(String)
 | 
						 * @see SystemCommandsMap#isValidKey(String)
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void addCommand(String command, Function<String[], Void> action, int numberOfArguments) {
 | 
						public void add(String command, SystemCommand systemCommand) { if (isValidKey(command)) systemCommands.put(command, systemCommand); }
 | 
				
			||||||
		if (isValidKey(command)) systemCommands.put(command, new SystemCommand(action, numberOfArguments, ""));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Adds a command with according action, the number of arguments that should be
 | 
					 | 
				
			||||||
	 * parsed and a description of the system command, 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
 | 
					 | 
				
			||||||
	 * @param numberOfArguments the amount of arguments that need to be parsed for
 | 
					 | 
				
			||||||
	 *                          the underlying function
 | 
					 | 
				
			||||||
	 * @param description       the description of this {@link SystemCommand}
 | 
					 | 
				
			||||||
	 * @see SystemCommandsMap#isValidKey(String)
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void addCommand(String command, Function<String[], Void> action, int numberOfArguments, String description) {
 | 
					 | 
				
			||||||
		if (isValidKey(command)) systemCommands.put(command, new SystemCommand(action, numberOfArguments, description));
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Adds a command with according action that does not depend on arguments, 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}
 | 
					 | 
				
			||||||
	 * @see SystemCommandsMap#isValidKey(String)
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void addNoArgCommand(String command, Function<String[], Void> action) { addCommand(command, action, 0); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Adds a command with according action that does not depend on arguments and a
 | 
					 | 
				
			||||||
	 * description of that action, 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 description the description of this {@link SystemCommand}
 | 
					 | 
				
			||||||
	 * @see SystemCommandsMap#isValidKey(String)
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public void addNoArgCommand(String command, Function<String[], Void> action, String description) { addCommand(command, action, 0); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Convenience method that does the same as
 | 
					 | 
				
			||||||
	 * {@link SystemCommandsMap#addCommand(String, Function, int)}.
 | 
					 | 
				
			||||||
	 * <p>
 | 
					 | 
				
			||||||
	 * 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<String[], Void> action, int numberOfArguments) { addCommand(command, action, numberOfArguments); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Examines whether a key can be put in the map and logs it with
 | 
					 | 
				
			||||||
	 * {@code Level.WARNING} if that key violates API constrictions <br>
 | 
					 | 
				
			||||||
	 * (allowed chars are <b>a-zA-Z0-9_:!()?.,;-</b>)
 | 
					 | 
				
			||||||
	 * <p>
 | 
					 | 
				
			||||||
	 * 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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * This method checks if the input String is a key in the map and returns the
 | 
						 * This method checks if the input String is a key in the map and returns the
 | 
				
			||||||
	 * wrapped System command if present.
 | 
						 * 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
 | 
						 * 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
 | 
						 * the map, which is a valid case (i.e. input="3/4" and "4" is not a key in the
 | 
				
			||||||
	 * map).
 | 
						 * map).
 | 
				
			||||||
	 * <p>
 | 
						 * <p>
 | 
				
			||||||
	 * Usage example:<br>
 | 
						 * Usage example:<br>
 | 
				
			||||||
	 * {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}<br>
 | 
						 * {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}<br>
 | 
				
			||||||
	 * {@code systemCommands.add("example", Function.identity, 1);}<br>
 | 
						 * {@code Button button = new  Button();}
 | 
				
			||||||
 | 
						 * {@code systemCommands.add("example", text -> button.setText(text.get(0), 1);}<br>
 | 
				
			||||||
	 * {@code ....}<br>
 | 
						 * {@code ....}<br>
 | 
				
			||||||
	 * user input: {@code "/example xyz ..."}<br>
 | 
						 * user input: {@code "/example xyz ..."}<br>
 | 
				
			||||||
	 * {@code systemCommands.checkPresent("example xyz ...")}
 | 
						 * {@code systemCommands.get("example xyz ...")} or
 | 
				
			||||||
	 * result: {@code SystemCommand[action=Function.identity, numberOfArguments=1]}
 | 
						 * {@code systemCommands.get("/example xyz ...")}
 | 
				
			||||||
 | 
						 * result: {@code Optional<SystemCommand>}
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param input the input string given by the user, <b>excluding the "/"</b>
 | 
						 * @param input the input string given by the user
 | 
				
			||||||
	 * @return the wrapped system command, if present
 | 
						 * @return the wrapped system command, if present
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public Optional<SystemCommand> checkPresent(String input) { return Optional.ofNullable(systemCommands.get(getCommand(input))); }
 | 
						public Optional<SystemCommand> get(String input) { return Optional.ofNullable(systemCommands.get(getCommand(input))); }
 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Takes a 'raw' string (the whole input) and checks if a command is present
 | 
					 | 
				
			||||||
	 * after a "/". If that is the case, it will be executed.
 | 
					 | 
				
			||||||
	 * <p>
 | 
					 | 
				
			||||||
	 * 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.
 | 
					 | 
				
			||||||
	 * <p>
 | 
					 | 
				
			||||||
	 * 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.<br>
 | 
					 | 
				
			||||||
	 * It returns the command as (most likely) entered as key in the map starting
 | 
					 | 
				
			||||||
	 * from {@code fromIndex}.<br>
 | 
					 | 
				
			||||||
	 * 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);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * This method ensures that the "/" of a {@link SystemCommand} is stripped.<br>
 | 
						 * This method ensures that the "/" of a {@link SystemCommand} is stripped.<br>
 | 
				
			||||||
@@ -229,7 +75,52 @@ public final class SystemCommandsMap {
 | 
				
			|||||||
	 *          whatever is entered after the slash is not a system command. Only
 | 
						 *          whatever is entered after the slash is not a system command. Only
 | 
				
			||||||
	 *          exception: for recommendation purposes.
 | 
						 *          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.<br>
 | 
				
			||||||
 | 
						 * (allowed chars are <b>a-zA-Z0-9_:!()?.,;-</b>)
 | 
				
			||||||
 | 
						 * <p>
 | 
				
			||||||
 | 
						 * 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.
 | 
				
			||||||
 | 
						 * <p>
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @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
 | 
						 * 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:<br>
 | 
						 * Usage example:<br>
 | 
				
			||||||
	 * {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}<br>
 | 
						 * {@code SystemCommandsMap systemCommands = new SystemCommandsMap();}<br>
 | 
				
			||||||
	 * {@code Button button = new Button();}<br>
 | 
						 * {@code Button button = new Button();}<br>
 | 
				
			||||||
	 * {@code systemCommands.add("example", (words)-> button.setText(words[0]), 1);}<br>
 | 
						 * {@code systemCommands.add("example", (words)-> button.setText(words.get(0), 1);}<br>
 | 
				
			||||||
	 * {@code ....}<br>
 | 
						 * {@code ....}<br>
 | 
				
			||||||
	 * user input: {@code "/example xyz ..."}<br>
 | 
						 * user input: {@code "/example xyz ..."}<br>
 | 
				
			||||||
	 * {@code systemCommands.executeIfPresent("example xyz ...")}
 | 
						 * {@code systemCommands.executeIfPresent("example xyz ...")}
 | 
				
			||||||
	 * result: {@code button.getText()=="xyz"}
 | 
						 * result: {@code button.getText()=="xyz"}
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param input the input string given by the user, <b>excluding the "/"</b>
 | 
						 * @param input the input string given by the user
 | 
				
			||||||
 | 
						 * @return whether a command could be found
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void executeIfPresent(String input) {
 | 
						public boolean executeIfPresent(String input) {
 | 
				
			||||||
		checkPresent(input).ifPresent(systemCommand -> {
 | 
							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
 | 
								// 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
 | 
								// removed and only as many following words as allowed by the system command
 | 
				
			||||||
			// persist
 | 
								// persist
 | 
				
			||||||
			final var remainingString = input.substring(input.indexOf(" ") + 1);
 | 
								final var arguments = extractArguments(input, systemCommand);
 | 
				
			||||||
			// 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());
 | 
					 | 
				
			||||||
			// Executing the function
 | 
								// Executing the function
 | 
				
			||||||
			try {
 | 
								try {
 | 
				
			||||||
				systemCommand.getAction().apply(arguments);
 | 
									systemCommand.getAction().accept(arguments);
 | 
				
			||||||
				commandExecuted = true;
 | 
					 | 
				
			||||||
				systemCommand.onCall();
 | 
									systemCommand.onCall();
 | 
				
			||||||
			} catch (final Exception e) {
 | 
								} 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<String> extractArguments(String input, SystemCommand systemCommand) {
 | 
				
			||||||
 | 
							// no more arguments follow after the command (e.g. text = "/DABR")
 | 
				
			||||||
 | 
							final var indexOfSpace = input.indexOf(" ");
 | 
				
			||||||
 | 
							if (indexOfSpace < 0) return supplementDefaults(new String[] {}, systemCommand);
 | 
				
			||||||
 | 
							// the arguments behind a system command
 | 
				
			||||||
 | 
							final var	remainingString		= input.substring(indexOfSpace + 1);
 | 
				
			||||||
 | 
							final var	numberOfArguments	= systemCommand.getNumberOfArguments();
 | 
				
			||||||
 | 
							// splitting those arguments and supplying default values
 | 
				
			||||||
 | 
							final var	textArguments		= remainingString.split(" ", -1);
 | 
				
			||||||
 | 
							final var	originalArguments	= numberOfArguments >= 0 ? Arrays.copyOfRange(textArguments, 0, numberOfArguments) : textArguments;
 | 
				
			||||||
 | 
							final var	arguments			= supplementDefaults(originalArguments, systemCommand);
 | 
				
			||||||
 | 
							return arguments;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@@ -278,28 +191,13 @@ public final class SystemCommandsMap {
 | 
				
			|||||||
	 * If none are present, nothing will be done.<br>
 | 
						 * If none are present, nothing will be done.<br>
 | 
				
			||||||
	 * Otherwise the given function will be executed on the recommendations.<br>
 | 
						 * Otherwise the given function will be executed on the recommendations.<br>
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @param input  the input
 | 
						 * @param input  the input string
 | 
				
			||||||
	 * @param action the action that should be taken for the recommendations, if any
 | 
						 * @param action the action that should be taken for the recommendations, if any
 | 
				
			||||||
	 *               are present
 | 
						 *               are present
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public void requestRecommendations(String input, Function<Set<String>, Void> action) { requestRecommendations(input, 0, action); }
 | 
						public void requestRecommendations(String input, Function<Set<String>, Void> action) {
 | 
				
			||||||
 | 
							final var partialCommand = getCommand(input);
 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Retrieves the recommendations based on the current input entered.<br>
 | 
					 | 
				
			||||||
	 * The word beginning at {@code fromIndex} is used for the recommendations and
 | 
					 | 
				
			||||||
	 * it does not matter if the "/" is at its beginning or not.<br>
 | 
					 | 
				
			||||||
	 * If none are present, nothing will be done.<br>
 | 
					 | 
				
			||||||
	 * Otherwise the given function will be executed on the recommendations.<br>
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @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<Set<String>, Void> action) {
 | 
					 | 
				
			||||||
		final var partialCommand = getCommand(input, fromIndex);
 | 
					 | 
				
			||||||
		// Get the expected commands
 | 
							// Get the expected commands
 | 
				
			||||||
		final var recommendations = recommendCommands(partialCommand);
 | 
							final var recommendations = recommendCommands(partialCommand);
 | 
				
			||||||
		if (recommendations.isEmpty()) return;
 | 
							if (recommendations.isEmpty()) return;
 | 
				
			||||||
@@ -319,12 +217,47 @@ public final class SystemCommandsMap {
 | 
				
			|||||||
	private Set<String> recommendCommands(String partialCommand) {
 | 
						private Set<String> recommendCommands(String partialCommand) {
 | 
				
			||||||
		// current implementation only looks if input is contained within a command,
 | 
							// current implementation only looks if input is contained within a command,
 | 
				
			||||||
		// might be updated
 | 
							// might be updated
 | 
				
			||||||
		return systemCommands.keySet().stream().filter(command -> command.contains(partialCommand)).collect(Collectors.toSet());
 | 
							return systemCommands.keySet()
 | 
				
			||||||
 | 
								.stream()
 | 
				
			||||||
 | 
								.filter(command -> command.contains(partialCommand))
 | 
				
			||||||
 | 
								.sorted((command1, command2) -> Integer.compare(systemCommands.get(command1).getRelevance(), systemCommands.get(command2).getRelevance()))
 | 
				
			||||||
 | 
								.collect(Collectors.toSet());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * Supplies the default values for arguments if none are present in the text for
 | 
				
			||||||
 | 
						 * any argument. <br>
 | 
				
			||||||
 | 
						 * 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<String> supplementDefaults(String[] textArguments, SystemCommand toEvaluate) {
 | 
				
			||||||
 | 
							final var			defaults			= toEvaluate.getDefaults();
 | 
				
			||||||
 | 
							final var			numberOfArguments	= toEvaluate.getNumberOfArguments();
 | 
				
			||||||
 | 
							final List<String>	result				= new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (toEvaluate.getNumberOfArguments() > 0) for (int index = 0; index < numberOfArguments; index++) {
 | 
				
			||||||
 | 
								String textArg = null;
 | 
				
			||||||
 | 
								if (index < textArguments.length) textArg = textArguments[index];
 | 
				
			||||||
 | 
								// Set the argument at position index to the current argument of the text, if it
 | 
				
			||||||
 | 
								// is present. Otherwise the default for that argument will be taken if present.
 | 
				
			||||||
 | 
								// In the worst case, an empty String will be used.
 | 
				
			||||||
 | 
								result.add(!(textArg == null) && !textArg.isBlank() ? textArg : index < defaults.size() ? defaults.get(index) : "");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return result;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * @return all {@link SystemCommand}s used with the underlying command as key
 | 
						 * @return all {@link SystemCommand}s used with the underlying command as key
 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	public HashMap<String, SystemCommand> getSystemCommands() { return systemCommands; }
 | 
						public Map<String, SystemCommand> getSystemCommands() { return systemCommands; }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,28 +0,0 @@
 | 
				
			|||||||
package envoy.client.event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import envoy.event.Event;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * This event serves the purpose of interrupting something so that it will not
 | 
					 | 
				
			||||||
 * be finished.
 | 
					 | 
				
			||||||
 * <p>
 | 
					 | 
				
			||||||
 * Project: <strong>envoy-client</strong><br>
 | 
					 | 
				
			||||||
 * File: <strong>InterruptEvent.java</strong><br>
 | 
					 | 
				
			||||||
 * Created: <strong>23.07.2020</strong><br>
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @author Leon Hofmeister
 | 
					 | 
				
			||||||
 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
public class InterruptEvent extends Event<String> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	private static final long serialVersionUID = 1L;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/**
 | 
					 | 
				
			||||||
	 * Creates a new {@link InterruptEvent}.
 | 
					 | 
				
			||||||
	 *
 | 
					 | 
				
			||||||
	 * @param reason the reason why this event exists -> allows finer sieving
 | 
					 | 
				
			||||||
	 * @since Envoy Client v0.2-beta
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	public InterruptEvent(String reason) { super(reason); }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -30,6 +30,7 @@ import javafx.util.Duration;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import envoy.client.data.*;
 | 
					import envoy.client.data.*;
 | 
				
			||||||
import envoy.client.data.audio.AudioRecorder;
 | 
					import envoy.client.data.audio.AudioRecorder;
 | 
				
			||||||
 | 
					import envoy.client.data.commands.SystemCommandBuilder;
 | 
				
			||||||
import envoy.client.data.commands.SystemCommandsMap;
 | 
					import envoy.client.data.commands.SystemCommandsMap;
 | 
				
			||||||
import envoy.client.event.MessageCreationEvent;
 | 
					import envoy.client.event.MessageCreationEvent;
 | 
				
			||||||
import envoy.client.net.Client;
 | 
					import envoy.client.net.Client;
 | 
				
			||||||
@@ -129,8 +130,6 @@ public final class ChatScene implements Restorable {
 | 
				
			|||||||
		// Initialize message and user rendering
 | 
							// Initialize message and user rendering
 | 
				
			||||||
		messageList.setCellFactory(new ListCellFactory<>(MessageControl::new));
 | 
							messageList.setCellFactory(new ListCellFactory<>(MessageControl::new));
 | 
				
			||||||
		chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
 | 
							chatList.setCellFactory(new ListCellFactory<>(ChatControl::new));
 | 
				
			||||||
		messageTextAreaCommands.addNoArgCommand("DABR", text -> { doABarrelRoll(); return null; });
 | 
					 | 
				
			||||||
		messageTextAreaCommands.addNoArgCommand("DoABarrelRoll", text -> { doABarrelRoll(); return null; });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
 | 
							settingsButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("settings", DEFAULT_ICON_SIZE)));
 | 
				
			||||||
		voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
 | 
							voiceButton.setGraphic(new ImageView(IconUtil.loadIconThemeSensitive("microphone", DEFAULT_ICON_SIZE)));
 | 
				
			||||||
@@ -208,6 +207,22 @@ public final class ChatScene implements Restorable {
 | 
				
			|||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/**
 | 
				
			||||||
 | 
						 * Initializes all {@code SystemCommands} used in {@code ChatScene}.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * @since Envoy Client v0.2-beta
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						private void initializeSystemCommandsMap() {
 | 
				
			||||||
 | 
							final var builder = new SystemCommandBuilder();
 | 
				
			||||||
 | 
							// Do A Barrel roll initialization
 | 
				
			||||||
 | 
							final var random = new Random();
 | 
				
			||||||
 | 
							builder.setAction(text -> doABarrelRoll(Integer.parseInt(text.get(0)), Double.parseDouble(text.get(1))))
 | 
				
			||||||
 | 
								.setDefaults(Integer.toString(random.nextInt(3) + 1), Double.toString(random.nextDouble() * 3 + 1))
 | 
				
			||||||
 | 
								.setDescription("See for yourself :)")
 | 
				
			||||||
 | 
								.setNumberOfArguments(2);
 | 
				
			||||||
 | 
							messageTextAreaCommands.add("DABR", builder.build());
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Initializes all necessary data via dependency injection-
 | 
						 * Initializes all necessary data via dependency injection-
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
@@ -230,6 +245,7 @@ public final class ChatScene implements Restorable {
 | 
				
			|||||||
		if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
 | 
							if (!client.isOnline()) updateInfoLabel("You are offline", "infoLabel-info");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		recorder = new AudioRecorder();
 | 
							recorder = new AudioRecorder();
 | 
				
			||||||
 | 
							initializeSystemCommandsMap();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
@@ -381,7 +397,8 @@ public final class ChatScene implements Restorable {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Rotates every element in our application by 360° in at most 2.75s.
 | 
						 * Rotates every element in our application by (at most 4 *) 360° in at most
 | 
				
			||||||
 | 
						 * 2.75s.
 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * @since Envoy Client v0.1-beta
 | 
						 * @since Envoy Client v0.1-beta
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
@@ -498,9 +515,9 @@ public final class ChatScene implements Restorable {
 | 
				
			|||||||
			updateInfoLabel("You need to go online to send more messages", "infoLabel-error");
 | 
								updateInfoLabel("You need to go online to send more messages", "infoLabel-error");
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		final var text = messageTextArea.getText().strip();
 | 
							final var	text					= messageTextArea.getText().strip();
 | 
				
			||||||
		messageTextAreaCommands.checkForCommands(text);
 | 
							final var	systemCommandPresent	= messageTextAreaCommands.executeIfAnyPresent(text);
 | 
				
			||||||
		try {
 | 
							if (systemCommandPresent) {} else try {
 | 
				
			||||||
			// Creating the message and its metadata
 | 
								// Creating the message and its metadata
 | 
				
			||||||
			final var builder = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
 | 
								final var builder = new MessageBuilder(localDB.getUser().getID(), currentChat.getRecipient().getID(), localDB.getIDGenerator())
 | 
				
			||||||
				.setText(text);
 | 
									.setText(text);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user