summaryrefslogtreecommitdiff
path: root/dicore3
diff options
context:
space:
mode:
Diffstat (limited to 'dicore3')
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java240
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/Command.java316
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java864
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/CommandException.java56
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/EMessageType.java38
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/EOverridePolicy.java24
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java770
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java128
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java410
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ICommandDispatcher.java292
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/IContextFilter.java402
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/InheritingContextFilter.java128
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/LambdaCommand.java70
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java624
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java272
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java14
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/Validate.java104
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/BigRange.java104
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/Cmd.java32
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/CmdParamType.java54
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/CommandAnnotationUtils.java70
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/Desc.java54
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/Flag.java32
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/GenerateCommands.java28
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/GroupMatchedCommands.java136
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/NamedArg.java28
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java34
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/Range.java134
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireConsole.java22
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireParameters.java28
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePermissions.java66
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePlayer.java22
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatHandler.java188
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/ChatHandlers.java40
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/IChatHandler.java120
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java184
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java48
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpComponent.java18
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java46
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBorder.java14
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBuilder.java26
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageLayout.java40
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/PageBorders.java152
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/SimpleHelpComponent.java54
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java230
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageLayout.java80
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java90
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java118
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java184
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/EInsertionStage.java58
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java86
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertion.java14
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertionFunction.java28
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java62
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java590
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java354
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java2
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java82
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java296
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java92
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/IParameterTypeSelector.java88
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/MapBasedParameterTypeSelector.java228
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterConfig.java160
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java298
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/SimpleParameterType.java62
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java112
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommand.java152
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/predef/PredefinedCommand.java100
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/predef/SyntaxCommand.java72
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/BukkitCommand.java244
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/CommandMap.java118
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/CommandParseException.java54
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java72
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java10
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCallFlags.java186
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java74
-rw-r--r--dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java59
-rw-r--r--dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt21
-rw-r--r--dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java146
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/BitModifier.java364
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/Formatting.java588
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java346
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/InventoryEventUtil.java240
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/Logging.java232
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/Reflection.java1560
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/SetBasedWhitelist.java118
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/SpigotUtil.java816
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/StringUtil.java946
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/Whitelist.java182
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/ChainedListener.java92
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandle.java110
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandles.java126
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/ChainedListeners.java112
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/HandlerList.java182
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/Listener.java34
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/ListenerHandle.java18
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/event/SimpleListener.java14
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/ExceptionHandler.java406
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiConsumer.java138
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiFunction.java152
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedConsumer.java134
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunction.java148
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunctionalObject.java170
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedRunnable.java124
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedSupplier.java140
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/task/BaseTask.java216
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/task/IteratorTask.java240
-rw-r--r--dicore3/core/src/main/java/io/dico/dicore/task/VoidTask.java38
108 files changed, 9652 insertions, 9482 deletions
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
index 9a26f61..72bc303 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ChildCommandAddress.java
@@ -1,120 +1,120 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.predef.DefaultGroupCommand;
-import io.dico.dicore.command.predef.HelpCommand;
-
-import java.util.*;
-
-public class ChildCommandAddress extends ModifiableCommandAddress {
- ModifiableCommandAddress parent;
- final List<String> namesModifiable = new ArrayList<>(4);
- List<String> names = namesModifiable;
- Command command;
- boolean isCommandTrailing;
-
- public ChildCommandAddress() {
- }
-
- public ChildCommandAddress(Command command) {
- this.command = command;
- }
-
- public ChildCommandAddress(Command command, String name, String... aliases) {
- this(command);
- addNameAndAliases(name, aliases);
- }
-
- public static ChildCommandAddress newPlaceHolderCommand(String name, String... aliases) {
- ChildCommandAddress rv = new ChildCommandAddress();
- rv.setupAsPlaceholder(name, aliases);
- return rv;
- }
-
- public void setupAsPlaceholder(String name, String... aliases) {
- if (!hasCommand()) {
- setCommand(DefaultGroupCommand.getInstance());
- }
-
- addNameAndAliases(name, aliases);
- HelpCommand.registerAsChild(this);
- }
-
- @Override
- public boolean isRoot() {
- return false;
- }
-
- @Override
- public ModifiableCommandAddress getParent() {
- return parent;
- }
-
- @Override
- public Command getCommand() {
- return command;
- }
-
- @Override
- public void setCommand(Command command) {
- if (hasUserDeclaredCommand()) {
- throw new IllegalStateException("Command is already set at address \"" + getAddress() + "\"");
- }
- this.command = command;
- }
-
- @Override
- public List<String> getNames() {
- return names;
- }
-
- public void addNameAndAliases(String name, String... aliases) {
- names.add(name);
- names.addAll(Arrays.asList(aliases));
- }
-
- @Override
- public String getMainKey() {
- return namesModifiable.isEmpty() ? null : namesModifiable.get(0);
- }
-
- @Override
- public String getAddress() {
- ICommandAddress address = this;
- int depth = getDepth();
- String[] keys = new String[depth];
- for (int i = depth - 1; i >= 0; i--) {
- keys[i] = address.getMainKey();
- address = address.getParent();
- }
- return String.join(" ", keys);
- }
-
- public void finalizeNames() {
- if (names == namesModifiable) {
- names = Collections.unmodifiableList(namesModifiable);
- }
- }
-
- Iterator<String> modifiableNamesIterator() {
- return namesModifiable.iterator();
- }
-
- void setParent(ModifiableCommandAddress parent) {
- finalizeNames();
- this.parent = parent;
- }
-
- @Override
- public boolean isCommandTrailing() {
- return isCommandTrailing;
- }
-
- @Override
- public void setCommandTrailing(boolean trailing) {
- if (hasChildren()) {
- throw new IllegalStateException("Address already has children, this property can't be modified");
- }
- isCommandTrailing = trailing;
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.predef.DefaultGroupCommand;
+import io.dico.dicore.command.predef.HelpCommand;
+
+import java.util.*;
+
+public class ChildCommandAddress extends ModifiableCommandAddress {
+ ModifiableCommandAddress parent;
+ final List<String> namesModifiable = new ArrayList<>(4);
+ List<String> names = namesModifiable;
+ Command command;
+ boolean isCommandTrailing;
+
+ public ChildCommandAddress() {
+ }
+
+ public ChildCommandAddress(Command command) {
+ this.command = command;
+ }
+
+ public ChildCommandAddress(Command command, String name, String... aliases) {
+ this(command);
+ addNameAndAliases(name, aliases);
+ }
+
+ public static ChildCommandAddress newPlaceHolderCommand(String name, String... aliases) {
+ ChildCommandAddress rv = new ChildCommandAddress();
+ rv.setupAsPlaceholder(name, aliases);
+ return rv;
+ }
+
+ public void setupAsPlaceholder(String name, String... aliases) {
+ if (!hasCommand()) {
+ setCommand(DefaultGroupCommand.getInstance());
+ }
+
+ addNameAndAliases(name, aliases);
+ HelpCommand.registerAsChild(this);
+ }
+
+ @Override
+ public boolean isRoot() {
+ return false;
+ }
+
+ @Override
+ public ModifiableCommandAddress getParent() {
+ return parent;
+ }
+
+ @Override
+ public Command getCommand() {
+ return command;
+ }
+
+ @Override
+ public void setCommand(Command command) {
+ if (hasUserDeclaredCommand()) {
+ throw new IllegalStateException("Command is already set at address \"" + getAddress() + "\"");
+ }
+ this.command = command;
+ }
+
+ @Override
+ public List<String> getNames() {
+ return names;
+ }
+
+ public void addNameAndAliases(String name, String... aliases) {
+ names.add(name);
+ names.addAll(Arrays.asList(aliases));
+ }
+
+ @Override
+ public String getMainKey() {
+ return namesModifiable.isEmpty() ? null : namesModifiable.get(0);
+ }
+
+ @Override
+ public String getAddress() {
+ ICommandAddress address = this;
+ int depth = getDepth();
+ String[] keys = new String[depth];
+ for (int i = depth - 1; i >= 0; i--) {
+ keys[i] = address.getMainKey();
+ address = address.getParent();
+ }
+ return String.join(" ", keys);
+ }
+
+ public void finalizeNames() {
+ if (names == namesModifiable) {
+ names = Collections.unmodifiableList(namesModifiable);
+ }
+ }
+
+ Iterator<String> modifiableNamesIterator() {
+ return namesModifiable.iterator();
+ }
+
+ void setParent(ModifiableCommandAddress parent) {
+ finalizeNames();
+ this.parent = parent;
+ }
+
+ @Override
+ public boolean isCommandTrailing() {
+ return isCommandTrailing;
+ }
+
+ @Override
+ public void setCommandTrailing(boolean trailing) {
+ if (hasChildren()) {
+ throw new IllegalStateException("Address already has children, this property can't be modified");
+ }
+ isCommandTrailing = trailing;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
index 894e74e..97f4b78 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/Command.java
@@ -1,158 +1,158 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.IContextFilter.Priority;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.IArgumentPreProcessor;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.ParameterList;
-import io.dico.dicore.command.parameter.type.ParameterType;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-public abstract class Command {
- private static final String[] EMPTY_DESCRIPTION = new String[0];
- private final ParameterList parameterList = new ParameterList();
- private final List<IContextFilter> contextFilters = new ArrayList<>(3);
- private String[] description = EMPTY_DESCRIPTION;
- private String shortDescription;
-
- public Command addParameter(Parameter<?, ?> parameter) {
- parameterList.addParameter(parameter);
- return this;
- }
-
- public <TType> Command addParameter(String name, String description, ParameterType<TType, Void> type) {
- return addParameter(new Parameter<>(name, description, type, null, false, null));
- }
-
- public <TType, TParamInfo> Command addParameter(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
- return addParameter(new Parameter<>(name, description, type, paramInfo, false, null));
- }
-
- public <TType> Command addFlag(String name, String description, ParameterType<TType, Void> type) {
- return addParameter(new Parameter<>('-' + name, description, type, null, true, null));
- }
-
- public <TType, TParamInfo> Command addFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
- return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, null));
- }
-
- public <TType> Command addAuthorizedFlag(String name, String description, ParameterType<TType, Void> type, String permission) {
- return addParameter(new Parameter<>('-' + name, description, type, null, true, permission));
- }
-
- public <TType, TParamInfo> Command addAuthorizedFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo, String permission) {
- return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, permission));
- }
-
- public Command requiredParameters(int requiredParameters) {
- parameterList.setRequiredCount(requiredParameters);
- return this;
- }
-
- public Command repeatFinalParameter() {
- parameterList.setRepeatFinalParameter(true);
- return this;
- }
-
- public Command setDescription(String... description) {
- this.description = Objects.requireNonNull(description);
- return this;
- }
-
- public Command setShortDescription(String shortDescription) {
- this.shortDescription = shortDescription;
- return this;
- }
-
- /*
- public Command preprocessArguments(IArgumentPreProcessor processor) {
- parameterList.setArgumentPreProcessor(processor);
- return this;
- }*/
-
- public final ParameterList getParameterList() {
- return parameterList;
- }
-
- public final String[] getDescription() {
- return description.length == 0 ? description : description.clone();
- }
-
- public String getShortDescription() {
- return shortDescription;
- }
-
- /**
- * ---- CONTEXT FILTERS ----
- * Filter the contexts. For example, if the sender must be a player but it's the console,
- * throw a CommandException describing the problem.
- */
- private transient int postParameterFilterCount = 0;
-
- public Command addContextFilter(IContextFilter contextFilter) {
- Objects.requireNonNull(contextFilter);
- if (!contextFilters.contains(contextFilter)) {
- contextFilters.add(contextFilter);
- contextFilters.sort(null);
-
- if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
- postParameterFilterCount++;
- }
- }
- return this;
- }
-
- public List<IContextFilter> getContextFilters() {
- return Collections.unmodifiableList(contextFilters);
- }
-
- public Command removeContextFilter(IContextFilter contextFilter) {
- boolean ret = contextFilters.remove(contextFilter);
- if (ret) {
- if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
- postParameterFilterCount--;
- }
- }
- return this;
- }
-
- // ---- CONTROL FLOW IN COMMAND TREES ----
-
- public boolean isVisibleTo(CommandSender sender) {
- return true;
- }
-
- public boolean takePrecedenceOverSubcommand(String subCommand, ArgumentBuffer buffer) {
- return false;
- }
-
- // ---- EXECUTION ----
-
- public void initializeAndFilterContext(ExecutionContext context) throws CommandException {
- int i, n;
- for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
- contextFilters.get(i).filterContext(context);
- }
-
- context.parse(parameterList);
-
- if (!context.isTabComplete()) {
- for (n = contextFilters.size(); i < n; i++) {
- contextFilters.get(i).filterContext(context);
- }
- }
- }
-
- public abstract String execute(CommandSender sender, ExecutionContext context) throws CommandException;
-
- public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
- return context.getSuggestedCompletions(location);
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.IContextFilter.Priority;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.IArgumentPreProcessor;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.ParameterList;
+import io.dico.dicore.command.parameter.type.ParameterType;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+public abstract class Command {
+ private static final String[] EMPTY_DESCRIPTION = new String[0];
+ private final ParameterList parameterList = new ParameterList();
+ private final List<IContextFilter> contextFilters = new ArrayList<>(3);
+ private String[] description = EMPTY_DESCRIPTION;
+ private String shortDescription;
+
+ public Command addParameter(Parameter<?, ?> parameter) {
+ parameterList.addParameter(parameter);
+ return this;
+ }
+
+ public <TType> Command addParameter(String name, String description, ParameterType<TType, Void> type) {
+ return addParameter(new Parameter<>(name, description, type, null, false, null));
+ }
+
+ public <TType, TParamInfo> Command addParameter(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
+ return addParameter(new Parameter<>(name, description, type, paramInfo, false, null));
+ }
+
+ public <TType> Command addFlag(String name, String description, ParameterType<TType, Void> type) {
+ return addParameter(new Parameter<>('-' + name, description, type, null, true, null));
+ }
+
+ public <TType, TParamInfo> Command addFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo) {
+ return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, null));
+ }
+
+ public <TType> Command addAuthorizedFlag(String name, String description, ParameterType<TType, Void> type, String permission) {
+ return addParameter(new Parameter<>('-' + name, description, type, null, true, permission));
+ }
+
+ public <TType, TParamInfo> Command addAuthorizedFlag(String name, String description, ParameterType<TType, TParamInfo> type, TParamInfo paramInfo, String permission) {
+ return addParameter(new Parameter<>('-' + name, description, type, paramInfo, true, permission));
+ }
+
+ public Command requiredParameters(int requiredParameters) {
+ parameterList.setRequiredCount(requiredParameters);
+ return this;
+ }
+
+ public Command repeatFinalParameter() {
+ parameterList.setRepeatFinalParameter(true);
+ return this;
+ }
+
+ public Command setDescription(String... description) {
+ this.description = Objects.requireNonNull(description);
+ return this;
+ }
+
+ public Command setShortDescription(String shortDescription) {
+ this.shortDescription = shortDescription;
+ return this;
+ }
+
+ /*
+ public Command preprocessArguments(IArgumentPreProcessor processor) {
+ parameterList.setArgumentPreProcessor(processor);
+ return this;
+ }*/
+
+ public final ParameterList getParameterList() {
+ return parameterList;
+ }
+
+ public final String[] getDescription() {
+ return description.length == 0 ? description : description.clone();
+ }
+
+ public String getShortDescription() {
+ return shortDescription;
+ }
+
+ /**
+ * ---- CONTEXT FILTERS ----
+ * Filter the contexts. For example, if the sender must be a player but it's the console,
+ * throw a CommandException describing the problem.
+ */
+ private transient int postParameterFilterCount = 0;
+
+ public Command addContextFilter(IContextFilter contextFilter) {
+ Objects.requireNonNull(contextFilter);
+ if (!contextFilters.contains(contextFilter)) {
+ contextFilters.add(contextFilter);
+ contextFilters.sort(null);
+
+ if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
+ postParameterFilterCount++;
+ }
+ }
+ return this;
+ }
+
+ public List<IContextFilter> getContextFilters() {
+ return Collections.unmodifiableList(contextFilters);
+ }
+
+ public Command removeContextFilter(IContextFilter contextFilter) {
+ boolean ret = contextFilters.remove(contextFilter);
+ if (ret) {
+ if (contextFilter.getPriority().compareTo(Priority.POST_PARAMETERS) >= 0) {
+ postParameterFilterCount--;
+ }
+ }
+ return this;
+ }
+
+ // ---- CONTROL FLOW IN COMMAND TREES ----
+
+ public boolean isVisibleTo(CommandSender sender) {
+ return true;
+ }
+
+ public boolean takePrecedenceOverSubcommand(String subCommand, ArgumentBuffer buffer) {
+ return false;
+ }
+
+ // ---- EXECUTION ----
+
+ public void initializeAndFilterContext(ExecutionContext context) throws CommandException {
+ int i, n;
+ for (i = 0, n = contextFilters.size() - postParameterFilterCount; i < n; i++) {
+ contextFilters.get(i).filterContext(context);
+ }
+
+ context.parse(parameterList);
+
+ if (!context.isTabComplete()) {
+ for (n = contextFilters.size(); i < n; i++) {
+ contextFilters.get(i).filterContext(context);
+ }
+ }
+ }
+
+ public abstract String execute(CommandSender sender, ExecutionContext context) throws CommandException;
+
+ public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
+ return context.getSuggestedCompletions(location);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
index e527f27..118dd0f 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/CommandBuilder.java
@@ -1,432 +1,432 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.chat.IChatHandler;
-import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
-import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
-import io.dico.dicore.command.parameter.type.ParameterType;
-import io.dico.dicore.command.predef.HelpCommand;
-import io.dico.dicore.command.predef.PredefinedCommand;
-import io.dico.dicore.command.predef.SyntaxCommand;
-import io.dico.dicore.command.registration.reflect.ReflectiveRegistration;
-
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-/**
- * Mimic of WorldEdit's CommandGraph
- */
-public final class CommandBuilder {
- private final RootCommandAddress root;
- private ModifiableCommandAddress cur;
- private IParameterTypeSelector selector;
-
- /**
- * Instantiate a new CommandBuilder with a new command root system
- * Commands registered to this command builder might interfere with
- * commands registered to other commands builders or by other plugins.
- */
- public CommandBuilder() {
- this(new RootCommandAddress());
- }
-
- /**
- * Instantiate a new CommandBuilder with a specified root address.
- * If the root address is identical to that of another command builder,
- * they will modify the same tree.
- *
- * @param root the root address
- */
- public CommandBuilder(RootCommandAddress root) {
- this.root = Objects.requireNonNull(root);
- this.cur = root;
- this.selector = new MapBasedParameterTypeSelector(true);
- }
-
- /**
- * Add a sub command at the current address
- * The current address can be inspected using {@link #getAddress()}
- *
- * @param name the name of the command
- * @param command the command executor
- * @param aliases any aliases
- * @return this
- */
- public CommandBuilder addSubCommand(String name, Command command, String... aliases) {
- ChildCommandAddress address = new ChildCommandAddress(command);
- address.addNameAndAliases(name, aliases);
- return addSubCommand(address);
- }
-
- /**
- * Add a subcommand as an address at the current address
- * The result of this call is the same as
- * {@code addSubCommand(address.getMainKey(), address.getCommand(), address.getNames().sublist(1).toArray(new String[0]))}
- *
- * @param address the address
- * @return this
- * @throws IllegalArgumentException if {@code address.isRoot()}
- */
- public CommandBuilder addSubCommand(ICommandAddress address) {
- cur.addChild(address);
- return this;
- }
-
- /**
- * Search the given class for any (static) methods using command annotations
- * The class gets a localized parameter type selector if it defines parameter types.
- * Any commands found are registered as sub commands to the current address.
- *
- * @param clazz the clazz
- * @return this
- * @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
- * @see #registerCommands(Class, Object)
- */
- public CommandBuilder registerCommands(Class<?> clazz) {
- return registerCommands(clazz, null);
- }
-
- /**
- * Search the given object's class for methods using command annotations.
- * If the object is null, only static methods are checked. Otherwise, instance methods are also checked.
- * The class gets a localized parameter type selector if it defines parameter types.
- * Any commands found are registered as sub commands to the current address.
- *
- * @param object the object
- * @return this
- * @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
- * @see #registerCommands(Class, Object)
- */
- public CommandBuilder registerCommands(Object object) {
- return registerCommands(object.getClass(), object);
- }
-
- /**
- * Search the given class for methods using command annotations.
- * The class gets a localized parameter type selector if it defines parameter types.
- * Any commands found are registered as sub commands to the current address.
- * The instance is used to invoke non-static methods.
- *
- * @param clazz the class
- * @param instance the instance, null if only static methods
- * @return this
- * @throws IllegalArgumentException if instance is not null and it's not an instance of the class
- * @throws IllegalArgumentException if another exception occurs while parsing the methods of this class
- */
- public CommandBuilder registerCommands(Class<?> clazz, Object instance) {
- try {
- ReflectiveRegistration.parseCommandGroup(cur, selector, clazz, instance);
- return this;
- } catch (Exception ex) {
- throw new IllegalArgumentException(ex);
- }
- }
-
- /**
- * register the {@link HelpCommand} as a sub command at the current address
- *
- * @return this
- */
- public CommandBuilder registerHelpCommand() {
- HelpCommand.registerAsChild(cur);
- return this;
- }
-
- /**
- * register the {@link SyntaxCommand} as a sub command a the current address
- *
- * @return this
- */
- public CommandBuilder registerSyntaxCommand() {
- SyntaxCommand.registerAsChild(cur);
- return this;
- }
-
- /**
- * Generate the predefined commands.
- * These are presets.
- * Examples include {@code help} and {@code syntax}.
- * <p>
- * Predefined commands can be registered through {@link PredefinedCommand#registerPredefinedCommandGenerator(String, Consumer)}
- *
- * @param commands the commands
- * @return this
- */
- public CommandBuilder generatePredefinedCommands(String... commands) {
- ReflectiveRegistration.generateCommands(cur, commands);
- return this;
- }
-
- /**
- * Unregister any childs present at the given keys.
- * <p>
- * This method can be used to remove unwanted keys, that might have been added
- * outside of your control. For example, because you didn't want all commands
- * registered by {@link #registerCommands(Class, Object)}, or because you didn't
- * want the help command registered by {@link #group(String, String...)}
- *
- * @param removeAliases true if any aliases of the children present at the keys should be removed
- * @param keys a varargs array containing the keys
- * @return this
- * @throws IllegalArgumentException if keys array is empty
- */
- public CommandBuilder unregisterCommands(boolean removeAliases, String... keys) {
- cur.removeChildren(removeAliases, keys);
- return this;
- }
-
- /**
- * Jump to the sub-address with the given name as main key.
- * If an address with the exact name as main key exists,
- * that address becomes the current address.
- * <p>
- * Otherwise, a new addresses is registered with the name and aliases.
- * New addresses registered by this command have a HelpCommand added by default.
- * <p>
- * After this call, any registered commands are registered as a sub command
- * to the new address. To restore the previous state, a call to {@link #parent()}
- * should be made.
- * <p>
- * If the address is the target of a command, it will provide information about its sub commands
- * using the HelpCommand.
- *
- * @param name the main key
- * @param aliases the aliases
- * @return this
- */
- public CommandBuilder group(String name, String... aliases) {
- ChildCommandAddress address = cur.getChild(name);
- if (address == null || !name.equals(address.getMainKey())) {
- address = new ChildCommandAddress();
- address.setupAsPlaceholder(name, aliases);
- cur.addChild(address);
- }
- cur = address;
- return this;
- }
-
- /**
- * Similar to {@link #group(String, String[])} but this will force overwrite any present group,
- * using the address passed. The address MUST be an instance of {@link ChildCommandAddress}.
- *
- * <p>The address must not have a parent or any keys</p>
- *
- * @param address the address object to use
- * @param name the main key
- * @param aliases any aliases
- * @return this
- * @throws IllegalArgumentException if any of the requirements set out above aren't met
- */
- public CommandBuilder group(ICommandAddress address, String name, String... aliases) {
- if (address.hasParent() || address.getMainKey() != null || !(address instanceof ChildCommandAddress)) {
- throw new IllegalArgumentException();
- }
-
- ChildCommandAddress asChild = (ChildCommandAddress) address;
- asChild.setupAsPlaceholder(name, aliases);
- cur.addChild(address);
- cur = asChild;
- return this;
- }
-
- /**
- * Sets the description of a group created by {@link #group(String, String...)}
- * Can be called subsequently to making a call to {@link #group(String, String...)}
- *
- * @param shortDescription a short description
- * @param description the lines of a full description.
- * @return this
- * @throws IllegalStateException if the current group has no command
- */
- public CommandBuilder setGroupDescription(String shortDescription, String... description) {
- Command command = cur.getCommand();
- if (command == null) throw new IllegalStateException();
- cur.setCommand(command
- .setShortDescription(shortDescription)
- .setDescription(description));
- return this;
- }
-
- /**
- * Add a context filter to the command of the current group
- * @return this
- * @throws IllegalStateException if the current group has no command
- */
- public CommandBuilder addContextFilter(IContextFilter contextFilter) {
- Command command = cur.getCommand();
- if (command == null) throw new IllegalStateException();
- cur.setCommand(command
- .addContextFilter(contextFilter));
- return this;
- }
-
- /**
- * Add a required permission to the command of the current group
- * @return this
- * @throws IllegalStateException if the current group has no command
- */
- public CommandBuilder addPermission(String permission) {
- return addContextFilter(IContextFilter.permission(permission));
- }
-
- /**
- * Add a required permission to the command of the current group, which can be inherited
- * @return this
- * @throws IllegalStateException if the current group has no command
- */
- public CommandBuilder addInheritablePermission(String permission) {
- return addContextFilter(IContextFilter.inheritablePermission(permission));
- }
-
- /**
- * Jump up a level in the address
- *
- * @return this
- * @throws IllegalStateException if the address is empty
- * // has a depth of 0 // is at level 0
- */
- public CommandBuilder parent() {
- if (cur.hasParent()) {
- cur = cur.getParent();
- return this;
- }
- throw new IllegalStateException("No parent exists at this address");
- }
-
- /**
- * Jump to the root (empty) address,
- * such that a subsequent call to {@link #parent()}
- * will throw a {@link IllegalStateException}
- *
- * @return this
- */
- public CommandBuilder root() {
- cur = root;
- return this;
- }
-
- /**
- * Get the current address, as a space-separated string
- *
- * @return the current address
- */
- public String getAddress() {
- return cur.getAddress();
- }
-
- /**
- * Get the depth of the current address.
- * This is equivalent to {@code getAddress().split(" ").length}.
- * If the address is empty, the depth is 0.
- *
- * @return the depth
- */
- public int getDepth() {
- return cur.getDepth();
- }
-
- /**
- * Set the command at the current group. The command is set
- * a level higher than it would be if this were a call to {@link #addSubCommand(String, Command, String...)}
- * <p>
- * If a call to {@link #setGroupDescription(String, String...)} was made at the same address before,
- * the description is copied to the given executor.
- *
- * @param command the executor
- * @return this
- * @throws IllegalArgumentException if the command at the address is present and declared by the user,
- * in other words, it's not a {@link PredefinedCommand}
- */
- public CommandBuilder setCommand(Command command) {
- Command current = cur.getCommand();
- if (current instanceof HelpCommand && current != HelpCommand.INSTANCE) {
- command.setShortDescription(current.getShortDescription());
- command.setDescription(current.getDescription());
- }
-
- cur.setCommand(command);
- return this;
- }
-
- /**
- * Configure the chat handler at this address. The chat handler
- * is used for all children down the tree if they don't explicitly have
- * their own chat handler configured. If this isn't configured,
- * {@code ChatHandlers.defaultChat()} is used.
- *
- * @param chatHandler the chat handler
- * @return this
- */
- public CommandBuilder setChatHandler(IChatHandler chatHandler) {
- cur.setChatHandler(chatHandler);
- return this;
- }
-
- /**
- * Add the parameter type to this builder's selector.
- *
- * @param type the type
- * @param <T> the return type of the parameter type
- * @return this
- */
- public <T> CommandBuilder addParameterType(ParameterType<T, Void> type) {
- selector.addType(false, type);
- return this;
- }
-
- /**
- * Add the parameter type to this builder's selector.
- *
- * @param infolessAlias whether to also register the type with an infoless alias.
- * this increases the priority assigned to the type if no info object is present.
- * @param type the type
- * @param <T> the return type of the parameter type
- * @param <C> the parameter config type (info object)
- * @return this
- */
-
- public <T, C> CommandBuilder addParameterType(boolean infolessAlias, ParameterType<T, C> type) {
- selector.addType(infolessAlias, type);
- return this;
- }
-
- /**
- * Get the dispatcher for the root address.
- * The dispatcher should be used to finally register all commands,
- * after they are all declared.
- *
- * @return the dispatcher
- */
- public ICommandDispatcher getDispatcher() {
- return root;
- }
-
- /**
- * Print debugging information about the current addresses and commands in this builder
- * A StackTraceElement indicating where this was called from is also included
- *
- * @return this
- */
- public CommandBuilder printDebugInformation() {
- String address = cur == root ? "<root>" : cur.getAddress();
- StackTraceElement caller = getCallsite();
-
- StringBuilder message = new StringBuilder("### CommandBuilder dump ###");
- message.append("\nCalled from ").append(caller);
- message.append("\nPosition: ").append(address);
- cur.appendDebugInformation(message, "", new HashSet<>());
-
- System.out.println(message);
- return this;
- }
-
- private static StackTraceElement getCallsite() {
- // [0] Thread.currentThread()
- // [1] CommandBuilder.getCallsite()
- // [2] Calling method
- // [3] Method calling the calling method
- StackTraceElement[] trace = Thread.currentThread().getStackTrace();
- return trace.length > 3 ? trace[3] : null;
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.chat.IChatHandler;
+import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
+import io.dico.dicore.command.parameter.type.MapBasedParameterTypeSelector;
+import io.dico.dicore.command.parameter.type.ParameterType;
+import io.dico.dicore.command.predef.HelpCommand;
+import io.dico.dicore.command.predef.PredefinedCommand;
+import io.dico.dicore.command.predef.SyntaxCommand;
+import io.dico.dicore.command.registration.reflect.ReflectiveRegistration;
+
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * Mimic of WorldEdit's CommandGraph
+ */
+public final class CommandBuilder {
+ private final RootCommandAddress root;
+ private ModifiableCommandAddress cur;
+ private IParameterTypeSelector selector;
+
+ /**
+ * Instantiate a new CommandBuilder with a new command root system
+ * Commands registered to this command builder might interfere with
+ * commands registered to other commands builders or by other plugins.
+ */
+ public CommandBuilder() {
+ this(new RootCommandAddress());
+ }
+
+ /**
+ * Instantiate a new CommandBuilder with a specified root address.
+ * If the root address is identical to that of another command builder,
+ * they will modify the same tree.
+ *
+ * @param root the root address
+ */
+ public CommandBuilder(RootCommandAddress root) {
+ this.root = Objects.requireNonNull(root);
+ this.cur = root;
+ this.selector = new MapBasedParameterTypeSelector(true);
+ }
+
+ /**
+ * Add a sub command at the current address
+ * The current address can be inspected using {@link #getAddress()}
+ *
+ * @param name the name of the command
+ * @param command the command executor
+ * @param aliases any aliases
+ * @return this
+ */
+ public CommandBuilder addSubCommand(String name, Command command, String... aliases) {
+ ChildCommandAddress address = new ChildCommandAddress(command);
+ address.addNameAndAliases(name, aliases);
+ return addSubCommand(address);
+ }
+
+ /**
+ * Add a subcommand as an address at the current address
+ * The result of this call is the same as
+ * {@code addSubCommand(address.getMainKey(), address.getCommand(), address.getNames().sublist(1).toArray(new String[0]))}
+ *
+ * @param address the address
+ * @return this
+ * @throws IllegalArgumentException if {@code address.isRoot()}
+ */
+ public CommandBuilder addSubCommand(ICommandAddress address) {
+ cur.addChild(address);
+ return this;
+ }
+
+ /**
+ * Search the given class for any (static) methods using command annotations
+ * The class gets a localized parameter type selector if it defines parameter types.
+ * Any commands found are registered as sub commands to the current address.
+ *
+ * @param clazz the clazz
+ * @return this
+ * @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
+ * @see #registerCommands(Class, Object)
+ */
+ public CommandBuilder registerCommands(Class<?> clazz) {
+ return registerCommands(clazz, null);
+ }
+
+ /**
+ * Search the given object's class for methods using command annotations.
+ * If the object is null, only static methods are checked. Otherwise, instance methods are also checked.
+ * The class gets a localized parameter type selector if it defines parameter types.
+ * Any commands found are registered as sub commands to the current address.
+ *
+ * @param object the object
+ * @return this
+ * @throws IllegalArgumentException if an exception occurs while parsing the methods of this class
+ * @see #registerCommands(Class, Object)
+ */
+ public CommandBuilder registerCommands(Object object) {
+ return registerCommands(object.getClass(), object);
+ }
+
+ /**
+ * Search the given class for methods using command annotations.
+ * The class gets a localized parameter type selector if it defines parameter types.
+ * Any commands found are registered as sub commands to the current address.
+ * The instance is used to invoke non-static methods.
+ *
+ * @param clazz the class
+ * @param instance the instance, null if only static methods
+ * @return this
+ * @throws IllegalArgumentException if instance is not null and it's not an instance of the class
+ * @throws IllegalArgumentException if another exception occurs while parsing the methods of this class
+ */
+ public CommandBuilder registerCommands(Class<?> clazz, Object instance) {
+ try {
+ ReflectiveRegistration.parseCommandGroup(cur, selector, clazz, instance);
+ return this;
+ } catch (Exception ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ }
+
+ /**
+ * register the {@link HelpCommand} as a sub command at the current address
+ *
+ * @return this
+ */
+ public CommandBuilder registerHelpCommand() {
+ HelpCommand.registerAsChild(cur);
+ return this;
+ }
+
+ /**
+ * register the {@link SyntaxCommand} as a sub command a the current address
+ *
+ * @return this
+ */
+ public CommandBuilder registerSyntaxCommand() {
+ SyntaxCommand.registerAsChild(cur);
+ return this;
+ }
+
+ /**
+ * Generate the predefined commands.
+ * These are presets.
+ * Examples include {@code help} and {@code syntax}.
+ * <p>
+ * Predefined commands can be registered through {@link PredefinedCommand#registerPredefinedCommandGenerator(String, Consumer)}
+ *
+ * @param commands the commands
+ * @return this
+ */
+ public CommandBuilder generatePredefinedCommands(String... commands) {
+ ReflectiveRegistration.generateCommands(cur, commands);
+ return this;
+ }
+
+ /**
+ * Unregister any childs present at the given keys.
+ * <p>
+ * This method can be used to remove unwanted keys, that might have been added
+ * outside of your control. For example, because you didn't want all commands
+ * registered by {@link #registerCommands(Class, Object)}, or because you didn't
+ * want the help command registered by {@link #group(String, String...)}
+ *
+ * @param removeAliases true if any aliases of the children present at the keys should be removed
+ * @param keys a varargs array containing the keys
+ * @return this
+ * @throws IllegalArgumentException if keys array is empty
+ */
+ public CommandBuilder unregisterCommands(boolean removeAliases, String... keys) {
+ cur.removeChildren(removeAliases, keys);
+ return this;
+ }
+
+ /**
+ * Jump to the sub-address with the given name as main key.
+ * If an address with the exact name as main key exists,
+ * that address becomes the current address.
+ * <p>
+ * Otherwise, a new addresses is registered with the name and aliases.
+ * New addresses registered by this command have a HelpCommand added by default.
+ * <p>
+ * After this call, any registered commands are registered as a sub command
+ * to the new address. To restore the previous state, a call to {@link #parent()}
+ * should be made.
+ * <p>
+ * If the address is the target of a command, it will provide information about its sub commands
+ * using the HelpCommand.
+ *
+ * @param name the main key
+ * @param aliases the aliases
+ * @return this
+ */
+ public CommandBuilder group(String name, String... aliases) {
+ ChildCommandAddress address = cur.getChild(name);
+ if (address == null || !name.equals(address.getMainKey())) {
+ address = new ChildCommandAddress();
+ address.setupAsPlaceholder(name, aliases);
+ cur.addChild(address);
+ }
+ cur = address;
+ return this;
+ }
+
+ /**
+ * Similar to {@link #group(String, String[])} but this will force overwrite any present group,
+ * using the address passed. The address MUST be an instance of {@link ChildCommandAddress}.
+ *
+ * <p>The address must not have a parent or any keys</p>
+ *
+ * @param address the address object to use
+ * @param name the main key
+ * @param aliases any aliases
+ * @return this
+ * @throws IllegalArgumentException if any of the requirements set out above aren't met
+ */
+ public CommandBuilder group(ICommandAddress address, String name, String... aliases) {
+ if (address.hasParent() || address.getMainKey() != null || !(address instanceof ChildCommandAddress)) {
+ throw new IllegalArgumentException();
+ }
+
+ ChildCommandAddress asChild = (ChildCommandAddress) address;
+ asChild.setupAsPlaceholder(name, aliases);
+ cur.addChild(address);
+ cur = asChild;
+ return this;
+ }
+
+ /**
+ * Sets the description of a group created by {@link #group(String, String...)}
+ * Can be called subsequently to making a call to {@link #group(String, String...)}
+ *
+ * @param shortDescription a short description
+ * @param description the lines of a full description.
+ * @return this
+ * @throws IllegalStateException if the current group has no command
+ */
+ public CommandBuilder setGroupDescription(String shortDescription, String... description) {
+ Command command = cur.getCommand();
+ if (command == null) throw new IllegalStateException();
+ cur.setCommand(command
+ .setShortDescription(shortDescription)
+ .setDescription(description));
+ return this;
+ }
+
+ /**
+ * Add a context filter to the command of the current group
+ * @return this
+ * @throws IllegalStateException if the current group has no command
+ */
+ public CommandBuilder addContextFilter(IContextFilter contextFilter) {
+ Command command = cur.getCommand();
+ if (command == null) throw new IllegalStateException();
+ cur.setCommand(command
+ .addContextFilter(contextFilter));
+ return this;
+ }
+
+ /**
+ * Add a required permission to the command of the current group
+ * @return this
+ * @throws IllegalStateException if the current group has no command
+ */
+ public CommandBuilder addPermission(String permission) {
+ return addContextFilter(IContextFilter.permission(permission));
+ }
+
+ /**
+ * Add a required permission to the command of the current group, which can be inherited
+ * @return this
+ * @throws IllegalStateException if the current group has no command
+ */
+ public CommandBuilder addInheritablePermission(String permission) {
+ return addContextFilter(IContextFilter.inheritablePermission(permission));
+ }
+
+ /**
+ * Jump up a level in the address
+ *
+ * @return this
+ * @throws IllegalStateException if the address is empty
+ * // has a depth of 0 // is at level 0
+ */
+ public CommandBuilder parent() {
+ if (cur.hasParent()) {
+ cur = cur.getParent();
+ return this;
+ }
+ throw new IllegalStateException("No parent exists at this address");
+ }
+
+ /**
+ * Jump to the root (empty) address,
+ * such that a subsequent call to {@link #parent()}
+ * will throw a {@link IllegalStateException}
+ *
+ * @return this
+ */
+ public CommandBuilder root() {
+ cur = root;
+ return this;
+ }
+
+ /**
+ * Get the current address, as a space-separated string
+ *
+ * @return the current address
+ */
+ public String getAddress() {
+ return cur.getAddress();
+ }
+
+ /**
+ * Get the depth of the current address.
+ * This is equivalent to {@code getAddress().split(" ").length}.
+ * If the address is empty, the depth is 0.
+ *
+ * @return the depth
+ */
+ public int getDepth() {
+ return cur.getDepth();
+ }
+
+ /**
+ * Set the command at the current group. The command is set
+ * a level higher than it would be if this were a call to {@link #addSubCommand(String, Command, String...)}
+ * <p>
+ * If a call to {@link #setGroupDescription(String, String...)} was made at the same address before,
+ * the description is copied to the given executor.
+ *
+ * @param command the executor
+ * @return this
+ * @throws IllegalArgumentException if the command at the address is present and declared by the user,
+ * in other words, it's not a {@link PredefinedCommand}
+ */
+ public CommandBuilder setCommand(Command command) {
+ Command current = cur.getCommand();
+ if (current instanceof HelpCommand && current != HelpCommand.INSTANCE) {
+ command.setShortDescription(current.getShortDescription());
+ command.setDescription(current.getDescription());
+ }
+
+ cur.setCommand(command);
+ return this;
+ }
+
+ /**
+ * Configure the chat handler at this address. The chat handler
+ * is used for all children down the tree if they don't explicitly have
+ * their own chat handler configured. If this isn't configured,
+ * {@code ChatHandlers.defaultChat()} is used.
+ *
+ * @param chatHandler the chat handler
+ * @return this
+ */
+ public CommandBuilder setChatHandler(IChatHandler chatHandler) {
+ cur.setChatHandler(chatHandler);
+ return this;
+ }
+
+ /**
+ * Add the parameter type to this builder's selector.
+ *
+ * @param type the type
+ * @param <T> the return type of the parameter type
+ * @return this
+ */
+ public <T> CommandBuilder addParameterType(ParameterType<T, Void> type) {
+ selector.addType(false, type);
+ return this;
+ }
+
+ /**
+ * Add the parameter type to this builder's selector.
+ *
+ * @param infolessAlias whether to also register the type with an infoless alias.
+ * this increases the priority assigned to the type if no info object is present.
+ * @param type the type
+ * @param <T> the return type of the parameter type
+ * @param <C> the parameter config type (info object)
+ * @return this
+ */
+
+ public <T, C> CommandBuilder addParameterType(boolean infolessAlias, ParameterType<T, C> type) {
+ selector.addType(infolessAlias, type);
+ return this;
+ }
+
+ /**
+ * Get the dispatcher for the root address.
+ * The dispatcher should be used to finally register all commands,
+ * after they are all declared.
+ *
+ * @return the dispatcher
+ */
+ public ICommandDispatcher getDispatcher() {
+ return root;
+ }
+
+ /**
+ * Print debugging information about the current addresses and commands in this builder
+ * A StackTraceElement indicating where this was called from is also included
+ *
+ * @return this
+ */
+ public CommandBuilder printDebugInformation() {
+ String address = cur == root ? "<root>" : cur.getAddress();
+ StackTraceElement caller = getCallsite();
+
+ StringBuilder message = new StringBuilder("### CommandBuilder dump ###");
+ message.append("\nCalled from ").append(caller);
+ message.append("\nPosition: ").append(address);
+ cur.appendDebugInformation(message, "", new HashSet<>());
+
+ System.out.println(message);
+ return this;
+ }
+
+ private static StackTraceElement getCallsite() {
+ // [0] Thread.currentThread()
+ // [1] CommandBuilder.getCallsite()
+ // [2] Calling method
+ // [3] Method calling the calling method
+ StackTraceElement[] trace = Thread.currentThread().getStackTrace();
+ return trace.length > 3 ? trace[3] : null;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/CommandException.java b/dicore3/command/src/main/java/io/dico/dicore/command/CommandException.java
index b859952..adf66de 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/CommandException.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/CommandException.java
@@ -1,28 +1,28 @@
-package io.dico.dicore.command;
-
-public class CommandException extends Exception {
-
- public CommandException() {
- }
-
- public CommandException(String message) {
- super(message);
- }
-
- public CommandException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public CommandException(Throwable cause) {
- super(cause);
- }
-
- public static CommandException missingArgument(String parameterName) {
- return new CommandException("Missing argument for " + parameterName);
- }
-
- public static CommandException invalidArgument(String parameterName, String syntaxHelp) {
- return new CommandException("Invalid input for " + parameterName + ", should be " + syntaxHelp);
- }
-
-}
+package io.dico.dicore.command;
+
+public class CommandException extends Exception {
+
+ public CommandException() {
+ }
+
+ public CommandException(String message) {
+ super(message);
+ }
+
+ public CommandException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CommandException(Throwable cause) {
+ super(cause);
+ }
+
+ public static CommandException missingArgument(String parameterName) {
+ return new CommandException("Missing argument for " + parameterName);
+ }
+
+ public static CommandException invalidArgument(String parameterName, String syntaxHelp) {
+ return new CommandException("Invalid input for " + parameterName + ", should be " + syntaxHelp);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/EMessageType.java b/dicore3/command/src/main/java/io/dico/dicore/command/EMessageType.java
index fba8780..0b02459 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/EMessageType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/EMessageType.java
@@ -1,19 +1,19 @@
-package io.dico.dicore.command;
-
-public enum EMessageType {
- GOOD_NEWS,
- BAD_NEWS,
- NEUTRAL,
- INFORMATIVE,
- WARNING,
- INSTRUCTION,
- EXCEPTION,
- RESULT,
- CUSTOM,
-
- DESCRIPTION,
- SYNTAX,
- HIGHLIGHT,
- SUBCOMMAND,
- NUMBER,
-}
+package io.dico.dicore.command;
+
+public enum EMessageType {
+ GOOD_NEWS,
+ BAD_NEWS,
+ NEUTRAL,
+ INFORMATIVE,
+ WARNING,
+ INSTRUCTION,
+ EXCEPTION,
+ RESULT,
+ CUSTOM,
+
+ DESCRIPTION,
+ SYNTAX,
+ HIGHLIGHT,
+ SUBCOMMAND,
+ NUMBER,
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/EOverridePolicy.java b/dicore3/command/src/main/java/io/dico/dicore/command/EOverridePolicy.java
index 83b0151..980477a 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/EOverridePolicy.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/EOverridePolicy.java
@@ -1,12 +1,12 @@
-package io.dico.dicore.command;
-
-/**
- * Override policies for registering to the command map
- */
-public enum EOverridePolicy {
- OVERRIDE_ALL,
- MAIN_KEY_ONLY,
- MAIN_AND_FALLBACK,
- FALLBACK_ONLY,
- OVERRIDE_NONE
-}
+package io.dico.dicore.command;
+
+/**
+ * Override policies for registering to the command map
+ */
+public enum EOverridePolicy {
+ OVERRIDE_ALL,
+ MAIN_KEY_ONLY,
+ MAIN_AND_FALLBACK,
+ FALLBACK_ONLY,
+ OVERRIDE_NONE
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java b/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
index a329f40..af42650 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ExecutionContext.java
@@ -1,385 +1,385 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.ContextParser;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.ParameterList;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.*;
-
-/**
- * The context of execution.
- * <p>
- * This class is responsible for the control flow of parameter parsing, as well as caching and providing the parsed parameter values.
- * It is also responsible for keeping track of the parameter to complete in the case of a tab completion.
- */
-public class ExecutionContext {
- // Sender of the command
- private final CommandSender sender;
- // Address while parsing parameters with ContextParser
- private ICommandAddress address;
- // Command to execute
- private Command command;
- // if this flag is set, this execution is only for completion purposes.
- private boolean tabComplete;
-
- private final ArgumentBuffer buffer;
- // private ArgumentBuffer processedBuffer;
-
- // caches the buffer's cursor before parsing. This is needed to provide the original input of the player.
- private int cursorStart;
-
- // when the context starts parsing parameters, this flag is set, and any subsequent calls to #parseParameters() throw an IllegalStateException.
- //private boolean attemptedToParse;
-
-
- // The parsed parameter values, mapped by parameter name.
- // This also includes default values. All parameters from the parameter list are present if parsing was successful.
- private Map<String, Object> parameterValueMap = new HashMap<>();
- // this set contains the names of the parameters that were present in the command, and not given a default value.
- private Set<String> parsedParameters = new HashSet<>();
-
-
- // these fields store information required to provide completions.
- // the parameter to complete is the parameter that threw an exception when it was parsing.
- // the exception's message was discarded because it is a completion.
- private Parameter<?, ?> parameterToComplete;
- // this is the cursor that the ArgumentBuffer is reset to when suggested completions are requested.
- private int parameterToCompleteCursor = -1;
-
- // if this flag is set, any messages sent through the sendMessage methods are discarded.
- private boolean muted;
-
- public ExecutionContext(CommandSender sender, ArgumentBuffer buffer, boolean tabComplete) {
- this.sender = Objects.requireNonNull(sender);
- this.buffer = Objects.requireNonNull(buffer);
- this.muted = tabComplete;
- this.tabComplete = tabComplete;
-
- // If its tab completing, keep the empty element that might be at the end of the buffer
- // due to a space at the end of the command.
- // This allows the parser to correctly identify the parameter to be completed in this case.
- if (!tabComplete) {
- buffer.dropTrailingEmptyElements();
- }
- }
-
- /**
- * Construct an execution context that is ready to parse the parameter values.
- *
- * @param sender the sender
- * @param address the address
- * @param command the command
- * @param buffer the arguments
- * @param tabComplete true if this execution is a tab-completion
- */
- public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
- this(sender, buffer, tabComplete);
- setAddress(address);
- setCommand(command);
- }
-
- /**
- * Sender of the command
- *
- * @return the sender of the command
- */
- public CommandSender getSender() {
- return sender;
- }
-
- /**
- * @return the buffer of arguments
- */
- public ArgumentBuffer getBuffer() {
- return buffer;
- }
-
- /**
- * Command's address
- *
- * @return the command's address
- */
- public ICommandAddress getAddress() {
- return address;
- }
-
- /**
- * Set the address
- *
- * @param address the new address
- */
- public void setAddress(ICommandAddress address) {
- this.address = address;
- }
-
- /**
- * The command
- *
- * @return the command
- */
- public Command getCommand() {
- return command;
- }
-
- /**
- * Set the command
- *
- * @param command the new command
- */
- public void setCommand(Command command) {
- this.command = command;
- }
-
- /**
- * @return true if this context is for a tab completion.
- */
- public boolean isTabComplete() {
- return tabComplete;
- }
-
- /**
- * @return true if this context is muted.
- */
- public boolean isMuted() {
- return muted;
- }
-
- /**
- * Parse parameters from the given parameter list,
- * adding their values to the cache of this context.
- *
- * @param parameterList the parameterList
- * @throws CommandException if the arguments are not valid
- */
- public void parse(ParameterList parameterList) throws CommandException {
- cursorStart = buffer.getCursor();
-
- ContextParser parser = new ContextParser(this, parameterList, parameterValueMap, parsedParameters);
-
- try {
- parser.parse();
- } finally {
- if (tabComplete) {
- parameterToComplete = parser.getCompletionTarget();
- parameterToCompleteCursor = parser.getCompletionCursor();
- }
- }
-
- }
-
- /**
- * The command's parameter definition.
- *
- * @return the parameter list
- */
- @Deprecated
- public ParameterList getParameterList() {
- return null;//command.getParameterList();
- }
-
- /**
- * Get the buffer as it was before preprocessing the arguments.
- *
- * @return the original buffer
- */
- @Deprecated
- public ArgumentBuffer getOriginalBuffer() {
- return buffer;
- }
-
- /**
- * The arguments
- *
- * @return the argument buffer
- */
- @Deprecated
- public ArgumentBuffer getProcessedBuffer() {
- return buffer;
- }
-
- /**
- * The cursor start, in other words, the buffer's cursor before parameters were parsed.
- *
- * @return the cursor start
- */
- public int getCursorStart() {
- return cursorStart;
- }
-
- /**
- * The original arguments.
- *
- * @return original arguments.
- */
- public String[] getOriginal() {
- return buffer.getArrayFromIndex(cursorStart);
- }
-
- /**
- * The path used to access this address.
- *
- * @return the path used to access this address.
- */
- public String[] getRoute() {
- return Arrays.copyOf(buffer.toArray(), address.getDepth());
- }
-
- public Formatting getFormat(EMessageType type) {
- return address.getChatHandler().getChatFormatForType(type);
- }
-
- /**
- * The full command as cached by the buffer. Might be incomplete depending on how it was dispatched.
- *
- * @return the full command
- */
- public String getRawInput() {
- return buffer.getRawInput();
- }
-
- /**
- * Get the value of the parameter with the given name
- *
- * @param name the parameter's name
- * @param <T> expected type
- * @return the parsed value or the default value
- */
- @SuppressWarnings("unchecked")
- public <T> T get(String name) {
- if (!parameterValueMap.containsKey(name)) {
- throw new IllegalArgumentException();
- }
-
- try {
- return (T) parameterValueMap.get(name);
- } catch (ClassCastException ex) {
- throw new IllegalArgumentException("Invalid type parameter requested for parameter " + name, ex);
- }
- }
-
- /**
- * Get the value of the flag with the given name
- *
- * @param flag the flag's name, without preceding "-"
- * @param <T> expected type
- * @return the parsed value or the default value
- */
- public <T> T getFlag(String flag) {
- return get("-" + flag);
- }
-
- @SuppressWarnings("unchecked")
- @Deprecated
- public <T> T get(int index) {
- return null;//get(getParameterList().getIndexedParameterName(index));
- }
-
- /**
- * Checks if the parameter by the name was provided in the command's arguments.
- *
- * @param name the parameter name
- * @return true if it was provided
- */
- public boolean isProvided(String name) {
- return parsedParameters.contains(name);
- }
-
- /**
- * Checks if the parameter by the index was provided in the command's arguments.
- *
- * @param index the parameter index
- * @return true if it was provided
- */
- @Deprecated
- public boolean isProvided(int index) {
- return false;//isProvided(getParameterList().getIndexedParameterName(index));
- }
-
- /**
- * The parameter to complete.
- * This parameter is requested suggestions
- *
- * @return the parameter to complete.
- */
- public Parameter<?, ?> getParameterToComplete() {
- return parameterToComplete;
- }
-
- /**
- * Get suggested completions.
- *
- * @param location The location as passed to {link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}, or null if requested in another way.
- * @return completions.
- */
- public List<String> getSuggestedCompletions(Location location) {
- if (parameterToComplete != null) {
- return parameterToComplete.complete(this, location, buffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
- }
-
- List<String> result = new ArrayList<>();
- for (String name : parameterValueMap.keySet()) {
- if (name.startsWith("-") && !parsedParameters.contains(name)) {
- result.add(name);
- }
- }
- return result;
- }
-
- /*
- Chat handling
- */
-
- public void sendMessage(String message) {
- sendMessage(true, message);
- }
-
- public void sendMessage(EMessageType messageType, String message) {
- sendMessage(messageType, true, message);
- }
-
- public void sendMessage(boolean translateColours, String message) {
- sendMessage(EMessageType.NEUTRAL, translateColours, message);
- }
-
- public void sendMessage(EMessageType messageType, boolean translateColours, String message) {
- if (!muted) {
- if (translateColours) {
- message = Formatting.translateChars('&', message);
- }
- address.getChatHandler().sendMessage(this, messageType, message);
- }
- }
-
- public void sendMessage(String messageFormat, Object... args) {
- sendMessage(true, messageFormat, args);
- }
-
- public void sendMessage(EMessageType messageType, String messageFormat, Object... args) {
- sendMessage(messageType, true, messageFormat, args);
- }
-
- public void sendMessage(boolean translateColours, String messageFormat, Object... args) {
- sendMessage(EMessageType.NEUTRAL, translateColours, messageFormat, args);
- }
-
- public void sendMessage(EMessageType messageType, boolean translateColours, String messageFormat, Object... args) {
- sendMessage(messageType, translateColours, String.format(messageFormat, args));
- }
-
- public void sendHelpMessage(int page) {
- if (!muted) {
- address.getChatHandler().sendHelpMessage(sender, this, address, page);
- }
- }
-
- public void sendSyntaxMessage() {
- if (!muted) {
- address.getChatHandler().sendSyntaxMessage(sender, this, address);
- }
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.ContextParser;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.ParameterList;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.*;
+
+/**
+ * The context of execution.
+ * <p>
+ * This class is responsible for the control flow of parameter parsing, as well as caching and providing the parsed parameter values.
+ * It is also responsible for keeping track of the parameter to complete in the case of a tab completion.
+ */
+public class ExecutionContext {
+ // Sender of the command
+ private final CommandSender sender;
+ // Address while parsing parameters with ContextParser
+ private ICommandAddress address;
+ // Command to execute
+ private Command command;
+ // if this flag is set, this execution is only for completion purposes.
+ private boolean tabComplete;
+
+ private final ArgumentBuffer buffer;
+ // private ArgumentBuffer processedBuffer;
+
+ // caches the buffer's cursor before parsing. This is needed to provide the original input of the player.
+ private int cursorStart;
+
+ // when the context starts parsing parameters, this flag is set, and any subsequent calls to #parseParameters() throw an IllegalStateException.
+ //private boolean attemptedToParse;
+
+
+ // The parsed parameter values, mapped by parameter name.
+ // This also includes default values. All parameters from the parameter list are present if parsing was successful.
+ private Map<String, Object> parameterValueMap = new HashMap<>();
+ // this set contains the names of the parameters that were present in the command, and not given a default value.
+ private Set<String> parsedParameters = new HashSet<>();
+
+
+ // these fields store information required to provide completions.
+ // the parameter to complete is the parameter that threw an exception when it was parsing.
+ // the exception's message was discarded because it is a completion.
+ private Parameter<?, ?> parameterToComplete;
+ // this is the cursor that the ArgumentBuffer is reset to when suggested completions are requested.
+ private int parameterToCompleteCursor = -1;
+
+ // if this flag is set, any messages sent through the sendMessage methods are discarded.
+ private boolean muted;
+
+ public ExecutionContext(CommandSender sender, ArgumentBuffer buffer, boolean tabComplete) {
+ this.sender = Objects.requireNonNull(sender);
+ this.buffer = Objects.requireNonNull(buffer);
+ this.muted = tabComplete;
+ this.tabComplete = tabComplete;
+
+ // If its tab completing, keep the empty element that might be at the end of the buffer
+ // due to a space at the end of the command.
+ // This allows the parser to correctly identify the parameter to be completed in this case.
+ if (!tabComplete) {
+ buffer.dropTrailingEmptyElements();
+ }
+ }
+
+ /**
+ * Construct an execution context that is ready to parse the parameter values.
+ *
+ * @param sender the sender
+ * @param address the address
+ * @param command the command
+ * @param buffer the arguments
+ * @param tabComplete true if this execution is a tab-completion
+ */
+ public ExecutionContext(CommandSender sender, ICommandAddress address, Command command, ArgumentBuffer buffer, boolean tabComplete) {
+ this(sender, buffer, tabComplete);
+ setAddress(address);
+ setCommand(command);
+ }
+
+ /**
+ * Sender of the command
+ *
+ * @return the sender of the command
+ */
+ public CommandSender getSender() {
+ return sender;
+ }
+
+ /**
+ * @return the buffer of arguments
+ */
+ public ArgumentBuffer getBuffer() {
+ return buffer;
+ }
+
+ /**
+ * Command's address
+ *
+ * @return the command's address
+ */
+ public ICommandAddress getAddress() {
+ return address;
+ }
+
+ /**
+ * Set the address
+ *
+ * @param address the new address
+ */
+ public void setAddress(ICommandAddress address) {
+ this.address = address;
+ }
+
+ /**
+ * The command
+ *
+ * @return the command
+ */
+ public Command getCommand() {
+ return command;
+ }
+
+ /**
+ * Set the command
+ *
+ * @param command the new command
+ */
+ public void setCommand(Command command) {
+ this.command = command;
+ }
+
+ /**
+ * @return true if this context is for a tab completion.
+ */
+ public boolean isTabComplete() {
+ return tabComplete;
+ }
+
+ /**
+ * @return true if this context is muted.
+ */
+ public boolean isMuted() {
+ return muted;
+ }
+
+ /**
+ * Parse parameters from the given parameter list,
+ * adding their values to the cache of this context.
+ *
+ * @param parameterList the parameterList
+ * @throws CommandException if the arguments are not valid
+ */
+ public void parse(ParameterList parameterList) throws CommandException {
+ cursorStart = buffer.getCursor();
+
+ ContextParser parser = new ContextParser(this, parameterList, parameterValueMap, parsedParameters);
+
+ try {
+ parser.parse();
+ } finally {
+ if (tabComplete) {
+ parameterToComplete = parser.getCompletionTarget();
+ parameterToCompleteCursor = parser.getCompletionCursor();
+ }
+ }
+
+ }
+
+ /**
+ * The command's parameter definition.
+ *
+ * @return the parameter list
+ */
+ @Deprecated
+ public ParameterList getParameterList() {
+ return null;//command.getParameterList();
+ }
+
+ /**
+ * Get the buffer as it was before preprocessing the arguments.
+ *
+ * @return the original buffer
+ */
+ @Deprecated
+ public ArgumentBuffer getOriginalBuffer() {
+ return buffer;
+ }
+
+ /**
+ * The arguments
+ *
+ * @return the argument buffer
+ */
+ @Deprecated
+ public ArgumentBuffer getProcessedBuffer() {
+ return buffer;
+ }
+
+ /**
+ * The cursor start, in other words, the buffer's cursor before parameters were parsed.
+ *
+ * @return the cursor start
+ */
+ public int getCursorStart() {
+ return cursorStart;
+ }
+
+ /**
+ * The original arguments.
+ *
+ * @return original arguments.
+ */
+ public String[] getOriginal() {
+ return buffer.getArrayFromIndex(cursorStart);
+ }
+
+ /**
+ * The path used to access this address.
+ *
+ * @return the path used to access this address.
+ */
+ public String[] getRoute() {
+ return Arrays.copyOf(buffer.toArray(), address.getDepth());
+ }
+
+ public Formatting getFormat(EMessageType type) {
+ return address.getChatHandler().getChatFormatForType(type);
+ }
+
+ /**
+ * The full command as cached by the buffer. Might be incomplete depending on how it was dispatched.
+ *
+ * @return the full command
+ */
+ public String getRawInput() {
+ return buffer.getRawInput();
+ }
+
+ /**
+ * Get the value of the parameter with the given name
+ *
+ * @param name the parameter's name
+ * @param <T> expected type
+ * @return the parsed value or the default value
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T get(String name) {
+ if (!parameterValueMap.containsKey(name)) {
+ throw new IllegalArgumentException();
+ }
+
+ try {
+ return (T) parameterValueMap.get(name);
+ } catch (ClassCastException ex) {
+ throw new IllegalArgumentException("Invalid type parameter requested for parameter " + name, ex);
+ }
+ }
+
+ /**
+ * Get the value of the flag with the given name
+ *
+ * @param flag the flag's name, without preceding "-"
+ * @param <T> expected type
+ * @return the parsed value or the default value
+ */
+ public <T> T getFlag(String flag) {
+ return get("-" + flag);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Deprecated
+ public <T> T get(int index) {
+ return null;//get(getParameterList().getIndexedParameterName(index));
+ }
+
+ /**
+ * Checks if the parameter by the name was provided in the command's arguments.
+ *
+ * @param name the parameter name
+ * @return true if it was provided
+ */
+ public boolean isProvided(String name) {
+ return parsedParameters.contains(name);
+ }
+
+ /**
+ * Checks if the parameter by the index was provided in the command's arguments.
+ *
+ * @param index the parameter index
+ * @return true if it was provided
+ */
+ @Deprecated
+ public boolean isProvided(int index) {
+ return false;//isProvided(getParameterList().getIndexedParameterName(index));
+ }
+
+ /**
+ * The parameter to complete.
+ * This parameter is requested suggestions
+ *
+ * @return the parameter to complete.
+ */
+ public Parameter<?, ?> getParameterToComplete() {
+ return parameterToComplete;
+ }
+
+ /**
+ * Get suggested completions.
+ *
+ * @param location The location as passed to {link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}, or null if requested in another way.
+ * @return completions.
+ */
+ public List<String> getSuggestedCompletions(Location location) {
+ if (parameterToComplete != null) {
+ return parameterToComplete.complete(this, location, buffer.getUnaffectingCopy().setCursor(parameterToCompleteCursor));
+ }
+
+ List<String> result = new ArrayList<>();
+ for (String name : parameterValueMap.keySet()) {
+ if (name.startsWith("-") && !parsedParameters.contains(name)) {
+ result.add(name);
+ }
+ }
+ return result;
+ }
+
+ /*
+ Chat handling
+ */
+
+ public void sendMessage(String message) {
+ sendMessage(true, message);
+ }
+
+ public void sendMessage(EMessageType messageType, String message) {
+ sendMessage(messageType, true, message);
+ }
+
+ public void sendMessage(boolean translateColours, String message) {
+ sendMessage(EMessageType.NEUTRAL, translateColours, message);
+ }
+
+ public void sendMessage(EMessageType messageType, boolean translateColours, String message) {
+ if (!muted) {
+ if (translateColours) {
+ message = Formatting.translateChars('&', message);
+ }
+ address.getChatHandler().sendMessage(this, messageType, message);
+ }
+ }
+
+ public void sendMessage(String messageFormat, Object... args) {
+ sendMessage(true, messageFormat, args);
+ }
+
+ public void sendMessage(EMessageType messageType, String messageFormat, Object... args) {
+ sendMessage(messageType, true, messageFormat, args);
+ }
+
+ public void sendMessage(boolean translateColours, String messageFormat, Object... args) {
+ sendMessage(EMessageType.NEUTRAL, translateColours, messageFormat, args);
+ }
+
+ public void sendMessage(EMessageType messageType, boolean translateColours, String messageFormat, Object... args) {
+ sendMessage(messageType, translateColours, String.format(messageFormat, args));
+ }
+
+ public void sendHelpMessage(int page) {
+ if (!muted) {
+ address.getChatHandler().sendHelpMessage(sender, this, address, page);
+ }
+ }
+
+ public void sendSyntaxMessage() {
+ if (!muted) {
+ address.getChatHandler().sendSyntaxMessage(sender, this, address);
+ }
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
index 47c2aca..eb93b30 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ExtendedCommand.java
@@ -1,64 +1,64 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.parameter.IArgumentPreProcessor;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.type.ParameterType;
-
-@SuppressWarnings("unchecked")
-public abstract class ExtendedCommand<T extends ExtendedCommand<T>> extends Command {
- protected boolean modifiable;
-
- public ExtendedCommand() {
- this(true);
- }
-
- public ExtendedCommand(boolean modifiable) {
- this.modifiable = modifiable;
- }
-
- protected T newModifiableInstance() {
- return (T) this;
- }
-
- @Override
- public T addParameter(Parameter<?, ?> parameter) {
- return modifiable ? (T) super.addParameter(parameter) : newModifiableInstance().addParameter(parameter);
- }
-
- @Override
- public T addContextFilter(IContextFilter contextFilter) {
- return modifiable ? (T) super.addContextFilter(contextFilter) : newModifiableInstance().addContextFilter(contextFilter);
- }
-
- @Override
- public T removeContextFilter(IContextFilter contextFilter) {
- return modifiable ? (T) super.removeContextFilter(contextFilter) : newModifiableInstance().removeContextFilter(contextFilter);
- }
-
- @Override
- public T requiredParameters(int requiredParameters) {
- return modifiable ? (T) super.requiredParameters(requiredParameters) : newModifiableInstance().requiredParameters(requiredParameters);
- }
-
- @Override
- public T repeatFinalParameter() {
- return modifiable ? (T) super.repeatFinalParameter() : newModifiableInstance().repeatFinalParameter();
- }
-
- @Override
- public T setDescription(String... description) {
- return modifiable ? (T) super.setDescription(description) : newModifiableInstance().setDescription(description);
- }
-
- @Override
- public T setShortDescription(String shortDescription) {
- return modifiable ? (T) super.setShortDescription(shortDescription) : newModifiableInstance().setShortDescription(shortDescription);
- }
-
- /*
- @Override
- public T preprocessArguments(IArgumentPreProcessor processor) {
- return modifiable ? (T) super.preprocessArguments(processor) : newModifiableInstance().preprocessArguments(processor);
- }*/
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.parameter.IArgumentPreProcessor;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.type.ParameterType;
+
+@SuppressWarnings("unchecked")
+public abstract class ExtendedCommand<T extends ExtendedCommand<T>> extends Command {
+ protected boolean modifiable;
+
+ public ExtendedCommand() {
+ this(true);
+ }
+
+ public ExtendedCommand(boolean modifiable) {
+ this.modifiable = modifiable;
+ }
+
+ protected T newModifiableInstance() {
+ return (T) this;
+ }
+
+ @Override
+ public T addParameter(Parameter<?, ?> parameter) {
+ return modifiable ? (T) super.addParameter(parameter) : newModifiableInstance().addParameter(parameter);
+ }
+
+ @Override
+ public T addContextFilter(IContextFilter contextFilter) {
+ return modifiable ? (T) super.addContextFilter(contextFilter) : newModifiableInstance().addContextFilter(contextFilter);
+ }
+
+ @Override
+ public T removeContextFilter(IContextFilter contextFilter) {
+ return modifiable ? (T) super.removeContextFilter(contextFilter) : newModifiableInstance().removeContextFilter(contextFilter);
+ }
+
+ @Override
+ public T requiredParameters(int requiredParameters) {
+ return modifiable ? (T) super.requiredParameters(requiredParameters) : newModifiableInstance().requiredParameters(requiredParameters);
+ }
+
+ @Override
+ public T repeatFinalParameter() {
+ return modifiable ? (T) super.repeatFinalParameter() : newModifiableInstance().repeatFinalParameter();
+ }
+
+ @Override
+ public T setDescription(String... description) {
+ return modifiable ? (T) super.setDescription(description) : newModifiableInstance().setDescription(description);
+ }
+
+ @Override
+ public T setShortDescription(String shortDescription) {
+ return modifiable ? (T) super.setShortDescription(shortDescription) : newModifiableInstance().setShortDescription(shortDescription);
+ }
+
+ /*
+ @Override
+ public T preprocessArguments(IArgumentPreProcessor processor) {
+ return modifiable ? (T) super.preprocessArguments(processor) : newModifiableInstance().preprocessArguments(processor);
+ }*/
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
index 158b1f0..f900139 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandAddress.java
@@ -1,205 +1,205 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.chat.IChatHandler;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.ParameterList;
-import io.dico.dicore.command.predef.PredefinedCommand;
-import org.bukkit.command.CommandSender;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Interface for an address of a command.
- * <p>
- * The address holds what the name and aliases of a command are.
- * The address also (optionally) holds a reference to a {@link Command}
- * <p>
- * One instance of {@link Command} can be held by multiple addresses,
- * because the address decides what the command's name and aliases are.
- * <p>
- * The address holds children by key in a map. This map's keys include aliases for its children.
- * This creates a tree of addresses. If a command is dispatches, the tree is traversed untill a command is found
- * and no children deeper down match the command (there are exceptions to the later as defined by
- * {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
- * and {@link Command#isVisibleTo(CommandSender)}
- */
-public interface ICommandAddress {
-
- /**
- * @return true if this address has a parent.
- */
- boolean hasParent();
-
- /**
- * Get the parent of this address
- *
- * @return the parent of this address, or null if none exists.
- */
- ICommandAddress getParent();
-
- /**
- * @return true if this address has a command.
- */
- boolean hasCommand();
-
- /**
- * @return true if this address has a command that is not an instance of {@link PredefinedCommand}
- */
- boolean hasUserDeclaredCommand();
-
- /**
- * @return Get the command of this address, or null if none exists.
- */
- Command getCommand();
-
- /**
- * @return true if this address is an instance of {@link RootCommandAddress}
- */
- boolean isRoot();
-
- /**
- * @return the root address of the tree which this address resides in.
- */
- ICommandAddress getRoot();
-
- /**
- * A list of the names of this address, at the current level.
- * The first entry is the main key, the subsequent ones are aliases.
- * <p>
- * Untill an address is assigned a parent, this list is mutable.
- * <p>
- * If {@link #isRoot()}, this returns an immutable, empty list.
- *
- * @return the list of names.
- */
- List<String> getNames();
-
- /**
- * A list of the aliases of this address. That is, {@link #getNames()}
- * without the first entry.
- *
- * @return a list of aliases
- */
- List<String> getAliases();
-
- /**
- * @return The first element of {@link #getNames()}
- */
- String getMainKey();
-
- /**
- * Get the address of this command.
- * That is, the main keys of all commands leading up to this address, and this address itself, separated by a space.
- * In other words, the command without the / that is required to target the command at this address.
- *
- * @return the address of this command.
- */
- String getAddress();
-
- /**
- * Get the amount of addresses that separate this address from the root of the tree, + 1.
- * The root of the tree has a depth of 0. Each subsequent child has its depth incremented by 1.
- *
- * @return The depth of this address
- */
- int getDepth();
-
- /**
- * @return true if the depth of this address is larger than the argument.
- */
- boolean isDepthLargerThan(int depth);
-
- /**
- * @return true if this address has any children.
- */
- boolean hasChildren();
-
- /**
- * @return total number of children, not considering any aliases
- */
- int getNumberOfRealChildren();
-
- /**
- * Get an unmodifiable view of all main keys of the children of this address.
- *
- * @return the main keys
- */
- Collection<String> getChildrenMainKeys();
-
- /**
- * Get an unmodifiable view of the children of this address.
- * Values might be duplicated for aliases.
- *
- * <p>
- * To iterate children without duplicates, you can do something like this:
- * <pre>{@code
- * for (String key : address.getChildrenMainKeys()) {
- * ICommandAddress child = address.getChild(key);
- * // do stuff with child
- * }
- * }</pre>
- * </p>
- *
- * @return the children of this address.
- */
- Map<String, ? extends ICommandAddress> getChildren();
-
- /**
- * Query for a child at the given key.
- *
- * @param key the key. The name or alias of a command.
- * @return the child, or null if it's not found
- */
- ICommandAddress getChild(String key);
-
- /**
- * Query for a child using the given buffer, with the given context for reference.
- * Can be used to override behaviour of the address tree.
- * <p>
- * The default implementation is as follows:
- * <pre>{@code
- * return buffer.hasNext() ? getChild(buffer.next()) : null;
- * }</pre>
- *
- * @param context context of a command being executed
- * @param buffer the buffer. The name or alias of a command.
- * @return the child, or null if it's not found, altered freely by the implementation
- */
- ICommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
-
- /**
- * Get the command dispatcher for this tree
- *
- * @return the command dispatcher
- */
- ICommandDispatcher getDispatcherForTree();
-
- /**
- * @return The desired chathandler for use by commands at this address and any sub-addresses, if they define no explicit chat handler.
- */
- IChatHandler getChatHandler();
-
- /**
- * Returns if the command attached to this address should be treated as trailing.
- * A trailing command is executed whenever the address is scanned for children.
- * Its parameters are parsed and added to the context.
- *
- * @return true if the command attached to this address should be treated as trailing.
- */
- boolean isCommandTrailing();
-
- static ICommandAddress newChild() {
- return new ChildCommandAddress();
- }
-
- static ICommandAddress newChild(Command command) {
- return new ChildCommandAddress(command);
- }
-
- static ICommandAddress newRoot() {
- return new RootCommandAddress();
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.chat.IChatHandler;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.ParameterList;
+import io.dico.dicore.command.predef.PredefinedCommand;
+import org.bukkit.command.CommandSender;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interface for an address of a command.
+ * <p>
+ * The address holds what the name and aliases of a command are.
+ * The address also (optionally) holds a reference to a {@link Command}
+ * <p>
+ * One instance of {@link Command} can be held by multiple addresses,
+ * because the address decides what the command's name and aliases are.
+ * <p>
+ * The address holds children by key in a map. This map's keys include aliases for its children.
+ * This creates a tree of addresses. If a command is dispatches, the tree is traversed untill a command is found
+ * and no children deeper down match the command (there are exceptions to the later as defined by
+ * {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
+ * and {@link Command#isVisibleTo(CommandSender)}
+ */
+public interface ICommandAddress {
+
+ /**
+ * @return true if this address has a parent.
+ */
+ boolean hasParent();
+
+ /**
+ * Get the parent of this address
+ *
+ * @return the parent of this address, or null if none exists.
+ */
+ ICommandAddress getParent();
+
+ /**
+ * @return true if this address has a command.
+ */
+ boolean hasCommand();
+
+ /**
+ * @return true if this address has a command that is not an instance of {@link PredefinedCommand}
+ */
+ boolean hasUserDeclaredCommand();
+
+ /**
+ * @return Get the command of this address, or null if none exists.
+ */
+ Command getCommand();
+
+ /**
+ * @return true if this address is an instance of {@link RootCommandAddress}
+ */
+ boolean isRoot();
+
+ /**
+ * @return the root address of the tree which this address resides in.
+ */
+ ICommandAddress getRoot();
+
+ /**
+ * A list of the names of this address, at the current level.
+ * The first entry is the main key, the subsequent ones are aliases.
+ * <p>
+ * Untill an address is assigned a parent, this list is mutable.
+ * <p>
+ * If {@link #isRoot()}, this returns an immutable, empty list.
+ *
+ * @return the list of names.
+ */
+ List<String> getNames();
+
+ /**
+ * A list of the aliases of this address. That is, {@link #getNames()}
+ * without the first entry.
+ *
+ * @return a list of aliases
+ */
+ List<String> getAliases();
+
+ /**
+ * @return The first element of {@link #getNames()}
+ */
+ String getMainKey();
+
+ /**
+ * Get the address of this command.
+ * That is, the main keys of all commands leading up to this address, and this address itself, separated by a space.
+ * In other words, the command without the / that is required to target the command at this address.
+ *
+ * @return the address of this command.
+ */
+ String getAddress();
+
+ /**
+ * Get the amount of addresses that separate this address from the root of the tree, + 1.
+ * The root of the tree has a depth of 0. Each subsequent child has its depth incremented by 1.
+ *
+ * @return The depth of this address
+ */
+ int getDepth();
+
+ /**
+ * @return true if the depth of this address is larger than the argument.
+ */
+ boolean isDepthLargerThan(int depth);
+
+ /**
+ * @return true if this address has any children.
+ */
+ boolean hasChildren();
+
+ /**
+ * @return total number of children, not considering any aliases
+ */
+ int getNumberOfRealChildren();
+
+ /**
+ * Get an unmodifiable view of all main keys of the children of this address.
+ *
+ * @return the main keys
+ */
+ Collection<String> getChildrenMainKeys();
+
+ /**
+ * Get an unmodifiable view of the children of this address.
+ * Values might be duplicated for aliases.
+ *
+ * <p>
+ * To iterate children without duplicates, you can do something like this:
+ * <pre>{@code
+ * for (String key : address.getChildrenMainKeys()) {
+ * ICommandAddress child = address.getChild(key);
+ * // do stuff with child
+ * }
+ * }</pre>
+ * </p>
+ *
+ * @return the children of this address.
+ */
+ Map<String, ? extends ICommandAddress> getChildren();
+
+ /**
+ * Query for a child at the given key.
+ *
+ * @param key the key. The name or alias of a command.
+ * @return the child, or null if it's not found
+ */
+ ICommandAddress getChild(String key);
+
+ /**
+ * Query for a child using the given buffer, with the given context for reference.
+ * Can be used to override behaviour of the address tree.
+ * <p>
+ * The default implementation is as follows:
+ * <pre>{@code
+ * return buffer.hasNext() ? getChild(buffer.next()) : null;
+ * }</pre>
+ *
+ * @param context context of a command being executed
+ * @param buffer the buffer. The name or alias of a command.
+ * @return the child, or null if it's not found, altered freely by the implementation
+ */
+ ICommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
+
+ /**
+ * Get the command dispatcher for this tree
+ *
+ * @return the command dispatcher
+ */
+ ICommandDispatcher getDispatcherForTree();
+
+ /**
+ * @return The desired chathandler for use by commands at this address and any sub-addresses, if they define no explicit chat handler.
+ */
+ IChatHandler getChatHandler();
+
+ /**
+ * Returns if the command attached to this address should be treated as trailing.
+ * A trailing command is executed whenever the address is scanned for children.
+ * Its parameters are parsed and added to the context.
+ *
+ * @return true if the command attached to this address should be treated as trailing.
+ */
+ boolean isCommandTrailing();
+
+ static ICommandAddress newChild() {
+ return new ChildCommandAddress();
+ }
+
+ static ICommandAddress newChild(Command command) {
+ return new ChildCommandAddress(command);
+ }
+
+ static ICommandAddress newRoot() {
+ return new RootCommandAddress();
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandDispatcher.java b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandDispatcher.java
index 055171d..4f3ffc6 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ICommandDispatcher.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ICommandDispatcher.java
@@ -1,146 +1,146 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.registration.CommandMap;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.List;
-import java.util.Map;
-
-public interface ICommandDispatcher {
-
- /**
- * Get a potentially indirect child of the root of this dispatcher
- *
- * @param buffer the argument buffer with the subsequent keys to traverse. Any keys beyond the first that isn't found are ignored.
- * @return the child, or this same instance of no child is found.
- */
- ICommandAddress getDeepChild(ArgumentBuffer buffer);
-
- /**
- * Similar to {@link #getDeepChild(ArgumentBuffer)},
- * but this method incorporates checks on the command of traversed children:
- * {@link Command#isVisibleTo(CommandSender)}
- * and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
- * <p>
- * The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
- *
- * @param sender the sender of the command
- * @param buffer the command itself as a buffer.
- * @return the address that is the target of the command.
- */
- @Deprecated
- ICommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer);
-
- /**
- * Similar to {@link #getDeepChild(ArgumentBuffer)},
- * but this method incorporates checks on the command of traversed children:
- * {@link Command#isVisibleTo(CommandSender)}
- * and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
- * <p>
- * The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
- *
- * @param context the context of the command. The context must not have its address set.
- * @param buffer the command itself as a buffer.
- * @return the address that is the target of the command.
- */
- ICommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
-
- /**
- * dispatch the command
- *
- * @param sender the sender
- * @param command the command
- * @return true if a command has executed
- */
- boolean dispatchCommand(CommandSender sender, String[] command);
-
- /**
- * dispatch the command
- *
- * @param sender the sender
- * @param usedLabel the label (word after the /)
- * @param args the arguments
- * @return true if a command has executed
- */
- boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args);
-
- /**
- * dispatch the command
- *
- * @param sender the sender
- * @param buffer the command
- * @return true if a command has executed
- */
- boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer);
-
- /**
- * suggest tab completions
- *
- * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * args must be sanitized such that it contains no empty elements, particularly at the last index.
- * @return tab completions
- */
- List<String> getTabCompletions(CommandSender sender, Location location, String[] args);
-
- /**
- * suggest tab completions
- *
- * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param usedLabel the label as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @return tab completions
- */
- List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args);
-
- /**
- * suggest tab completions
- *
- * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
- * @param buffer the arguments as a buffer
- * @return tab completions
- */
- List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer);
-
- /**
- * Register this dispatcher's commands to the command map
- *
- * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
- */
- default void registerToCommandMap() {
- registerToCommandMap(null, CommandMap.getCommandMap(), EOverridePolicy.OVERRIDE_ALL);
- }
-
- /**
- * Register this dispatcher's commands to the command map
- *
- * @param fallbackPrefix the fallback prefix to use, null if none
- * @param overridePolicy the override policy
- * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
- */
- default void registerToCommandMap(String fallbackPrefix, EOverridePolicy overridePolicy) {
- registerToCommandMap(fallbackPrefix, CommandMap.getCommandMap(), overridePolicy);
- }
-
- /**
- * Register this dispatcher's commands to the command map
- *
- * @param fallbackPrefix the fallback prefix to use, null if none
- * @param map the command map
- * @param overridePolicy the override policy
- * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
- */
- void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy);
-
- default void unregisterFromCommandMap() {
- unregisterFromCommandMap(CommandMap.getCommandMap());
- }
-
- void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map);
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.registration.CommandMap;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+import java.util.Map;
+
+public interface ICommandDispatcher {
+
+ /**
+ * Get a potentially indirect child of the root of this dispatcher
+ *
+ * @param buffer the argument buffer with the subsequent keys to traverse. Any keys beyond the first that isn't found are ignored.
+ * @return the child, or this same instance of no child is found.
+ */
+ ICommandAddress getDeepChild(ArgumentBuffer buffer);
+
+ /**
+ * Similar to {@link #getDeepChild(ArgumentBuffer)},
+ * but this method incorporates checks on the command of traversed children:
+ * {@link Command#isVisibleTo(CommandSender)}
+ * and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
+ * <p>
+ * The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
+ *
+ * @param sender the sender of the command
+ * @param buffer the command itself as a buffer.
+ * @return the address that is the target of the command.
+ */
+ @Deprecated
+ ICommandAddress getCommandTarget(CommandSender sender, ArgumentBuffer buffer);
+
+ /**
+ * Similar to {@link #getDeepChild(ArgumentBuffer)},
+ * but this method incorporates checks on the command of traversed children:
+ * {@link Command#isVisibleTo(CommandSender)}
+ * and {@link Command#takePrecedenceOverSubcommand(String, ArgumentBuffer)}
+ * <p>
+ * The target of a command is never null, however, the same instance might be returned, and the returned address might not hold a command.
+ *
+ * @param context the context of the command. The context must not have its address set.
+ * @param buffer the command itself as a buffer.
+ * @return the address that is the target of the command.
+ */
+ ICommandAddress getCommandTarget(ExecutionContext context, ArgumentBuffer buffer) throws CommandException;
+
+ /**
+ * dispatch the command
+ *
+ * @param sender the sender
+ * @param command the command
+ * @return true if a command has executed
+ */
+ boolean dispatchCommand(CommandSender sender, String[] command);
+
+ /**
+ * dispatch the command
+ *
+ * @param sender the sender
+ * @param usedLabel the label (word after the /)
+ * @param args the arguments
+ * @return true if a command has executed
+ */
+ boolean dispatchCommand(CommandSender sender, String usedLabel, String[] args);
+
+ /**
+ * dispatch the command
+ *
+ * @param sender the sender
+ * @param buffer the command
+ * @return true if a command has executed
+ */
+ boolean dispatchCommand(CommandSender sender, ArgumentBuffer buffer);
+
+ /**
+ * suggest tab completions
+ *
+ * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * args must be sanitized such that it contains no empty elements, particularly at the last index.
+ * @return tab completions
+ */
+ List<String> getTabCompletions(CommandSender sender, Location location, String[] args);
+
+ /**
+ * suggest tab completions
+ *
+ * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param usedLabel the label as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param args the arguments as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @return tab completions
+ */
+ List<String> getTabCompletions(CommandSender sender, String usedLabel, Location location, String[] args);
+
+ /**
+ * suggest tab completions
+ *
+ * @param sender the sender as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param location the location as passed to {@link org.bukkit.command.Command#tabComplete(CommandSender, String, String[], Location)}
+ * @param buffer the arguments as a buffer
+ * @return tab completions
+ */
+ List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer);
+
+ /**
+ * Register this dispatcher's commands to the command map
+ *
+ * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
+ */
+ default void registerToCommandMap() {
+ registerToCommandMap(null, CommandMap.getCommandMap(), EOverridePolicy.OVERRIDE_ALL);
+ }
+
+ /**
+ * Register this dispatcher's commands to the command map
+ *
+ * @param fallbackPrefix the fallback prefix to use, null if none
+ * @param overridePolicy the override policy
+ * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
+ */
+ default void registerToCommandMap(String fallbackPrefix, EOverridePolicy overridePolicy) {
+ registerToCommandMap(fallbackPrefix, CommandMap.getCommandMap(), overridePolicy);
+ }
+
+ /**
+ * Register this dispatcher's commands to the command map
+ *
+ * @param fallbackPrefix the fallback prefix to use, null if none
+ * @param map the command map
+ * @param overridePolicy the override policy
+ * @throws UnsupportedOperationException if this dispatcher is not the root of the tree
+ */
+ void registerToCommandMap(String fallbackPrefix, Map<String, org.bukkit.command.Command> map, EOverridePolicy overridePolicy);
+
+ default void unregisterFromCommandMap() {
+ unregisterFromCommandMap(CommandMap.getCommandMap());
+ }
+
+ void unregisterFromCommandMap(Map<String, org.bukkit.command.Command> map);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/IContextFilter.java b/dicore3/command/src/main/java/io/dico/dicore/command/IContextFilter.java
index 5c05e27..bf34873 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/IContextFilter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/IContextFilter.java
@@ -1,201 +1,201 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
-import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
-import org.bukkit.command.CommandSender;
-import org.jetbrains.annotations.NotNull;
-
-public interface IContextFilter extends Comparable<IContextFilter> {
-
- /**
- * Filter the given context by this filter's criteria.
- * If the context does not match the criteria, an exception is thrown describing the problem.
- *
- * @param context the context to match
- * @throws CommandException if it doesn't match
- */
- void filterContext(ExecutionContext context) throws CommandException;
-
- /**
- * Filter an execution context for a direct or indirect sub command of the command that registered this filter.
- *
- * @param subContext the context for the execution
- * @param path the path traversed from the command that registered this filter to the executed command
- */
- default void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
- filterContext(subContext);
- }
-
- /**
- * Get the priority of this context filter.
- * The priorities determine the order in which a command's context filters are executed.
- *
- * @return the priority
- */
- Priority getPriority();
-
- default boolean allowsContext(ExecutionContext context) {
- try {
- filterContext(context);
- return true;
- } catch (CommandException ex) {
- return false;
- }
- }
-
- /**
- * Used to sort filters in execution order. That is, filters are ordered by {@link #getPriority()}
- *
- * @param o compared filter
- * @return comparison value
- */
- @Override
- default int compareTo(@NotNull IContextFilter o) {
- return getPriority().compareTo(o.getPriority());
- }
-
- /*
- default boolean isInheritable() {
- return false;
- }
-
- default IContextFilter inherit(String... components) {
- if (!isInheritable()) {
- throw new IllegalStateException("This IContextFilter cannot be inherited");
- }
-
- return this;
- }*/
-
- /**
- * IContextFilter priorities. Executes from top to bottom.
- */
- enum Priority {
- /**
- * This priority should have checks on the sender type.
- * Any filters on this priority are tested before permissions are.
- * This is the highest priority.
- */
- VERY_EARLY, // sender type check
-
- /**
- * This priority is specific to permissions.
- */
- PERMISSION,
-
- /**
- * Early priority. Post permissions, pre parameter-parsing.
- */
- EARLY,
-
- /**
- * Normal priority. Post permissions, pre parameter-parsing.
- */
- NORMAL,
-
- /**
- * Late priority. Post permissions, pre parameter-parsing.
- */
- LATE,
-
- /**
- * Very late priority. Post permissions, pre parameter-parsing.
- */
- VERY_LATE,
-
- /**
- * Post parameters priority. Post permissions, post parameter-parsing.
- * This is the lowest priority.
- */
- POST_PARAMETERS;
-
- private IContextFilter inheritor;
-
- /**
- * Get the context filter that inherits context filters from the parent of the same priority.
- * If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
- *
- * @return the inheritor
- */
- public IContextFilter getInheritor() {
- if (inheritor == null) {
- inheritor = InheritingContextFilter.inheritingPriority(this);
- }
- return inheritor;
- }
-
- }
-
- /**
- * Ensures that only {@link org.bukkit.entity.Player} type senders can execute the command.
- */
- IContextFilter PLAYER_ONLY = filterSender(Priority.VERY_EARLY, Validate::isPlayer);
-
- /**
- * Ensures that only {@link org.bukkit.command.ConsoleCommandSender} type senders can execute the command.
- */
- IContextFilter CONSOLE_ONLY = filterSender(Priority.VERY_EARLY, Validate::isConsole);
-
- /**
- * This filter is not working as intended.
- * <p>
- * There is supposed to be a permission filter that takes a base, and appends the command's address to the base, and checks that permission.
- */
- IContextFilter INHERIT_PERMISSIONS = Priority.PERMISSION.getInheritor();
-
- static IContextFilter fromCheckedRunnable(Priority priority, CheckedRunnable<? extends CommandException> runnable) {
- return new IContextFilter() {
- @Override
- public void filterContext(ExecutionContext context) throws CommandException {
- runnable.checkedRun();
- }
-
- @Override
- public Priority getPriority() {
- return priority;
- }
- };
- }
-
- static IContextFilter filterSender(Priority priority, CheckedConsumer<? super CommandSender, ? extends CommandException> consumer) {
- return new IContextFilter() {
- @Override
- public void filterContext(ExecutionContext context) throws CommandException {
- consumer.checkedAccept(context.getSender());
- }
-
- @Override
- public Priority getPriority() {
- return priority;
- }
- };
- }
-
- static IContextFilter permission(String permission) {
- return new PermissionContextFilter(permission);
- }
-
- static IContextFilter permission(String permission, String failMessage) {
- return new PermissionContextFilter(permission, failMessage);
- }
-
- static IContextFilter inheritablePermission(String permission) {
- return new PermissionContextFilter(permission, true);
- }
-
- /**
- * Produce an inheritable permission context filter.
- * A permission component is an element in {@code permission.split("\\.")}
- *
- * @param permission The permission that is required for the command that this is directly assigned to
- * @param componentInsertionIndex the index where any sub-components are inserted. -1 for "at the end".
- * @param failMessage the message to send if the permission is not met
- * @return the context filter
- * @throws IllegalArgumentException if componentInsertionIndex is out of range
- */
- static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
- return new PermissionContextFilter(permission, componentInsertionIndex, failMessage);
- }
-
-}
-
+package io.dico.dicore.command;
+
+import io.dico.dicore.exceptions.checkedfunctions.CheckedConsumer;
+import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+public interface IContextFilter extends Comparable<IContextFilter> {
+
+ /**
+ * Filter the given context by this filter's criteria.
+ * If the context does not match the criteria, an exception is thrown describing the problem.
+ *
+ * @param context the context to match
+ * @throws CommandException if it doesn't match
+ */
+ void filterContext(ExecutionContext context) throws CommandException;
+
+ /**
+ * Filter an execution context for a direct or indirect sub command of the command that registered this filter.
+ *
+ * @param subContext the context for the execution
+ * @param path the path traversed from the command that registered this filter to the executed command
+ */
+ default void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
+ filterContext(subContext);
+ }
+
+ /**
+ * Get the priority of this context filter.
+ * The priorities determine the order in which a command's context filters are executed.
+ *
+ * @return the priority
+ */
+ Priority getPriority();
+
+ default boolean allowsContext(ExecutionContext context) {
+ try {
+ filterContext(context);
+ return true;
+ } catch (CommandException ex) {
+ return false;
+ }
+ }
+
+ /**
+ * Used to sort filters in execution order. That is, filters are ordered by {@link #getPriority()}
+ *
+ * @param o compared filter
+ * @return comparison value
+ */
+ @Override
+ default int compareTo(@NotNull IContextFilter o) {
+ return getPriority().compareTo(o.getPriority());
+ }
+
+ /*
+ default boolean isInheritable() {
+ return false;
+ }
+
+ default IContextFilter inherit(String... components) {
+ if (!isInheritable()) {
+ throw new IllegalStateException("This IContextFilter cannot be inherited");
+ }
+
+ return this;
+ }*/
+
+ /**
+ * IContextFilter priorities. Executes from top to bottom.
+ */
+ enum Priority {
+ /**
+ * This priority should have checks on the sender type.
+ * Any filters on this priority are tested before permissions are.
+ * This is the highest priority.
+ */
+ VERY_EARLY, // sender type check
+
+ /**
+ * This priority is specific to permissions.
+ */
+ PERMISSION,
+
+ /**
+ * Early priority. Post permissions, pre parameter-parsing.
+ */
+ EARLY,
+
+ /**
+ * Normal priority. Post permissions, pre parameter-parsing.
+ */
+ NORMAL,
+
+ /**
+ * Late priority. Post permissions, pre parameter-parsing.
+ */
+ LATE,
+
+ /**
+ * Very late priority. Post permissions, pre parameter-parsing.
+ */
+ VERY_LATE,
+
+ /**
+ * Post parameters priority. Post permissions, post parameter-parsing.
+ * This is the lowest priority.
+ */
+ POST_PARAMETERS;
+
+ private IContextFilter inheritor;
+
+ /**
+ * Get the context filter that inherits context filters from the parent of the same priority.
+ * If this filter is also present at the parent, it will do the same for the parent's parent, and so on.
+ *
+ * @return the inheritor
+ */
+ public IContextFilter getInheritor() {
+ if (inheritor == null) {
+ inheritor = InheritingContextFilter.inheritingPriority(this);
+ }
+ return inheritor;
+ }
+
+ }
+
+ /**
+ * Ensures that only {@link org.bukkit.entity.Player} type senders can execute the command.
+ */
+ IContextFilter PLAYER_ONLY = filterSender(Priority.VERY_EARLY, Validate::isPlayer);
+
+ /**
+ * Ensures that only {@link org.bukkit.command.ConsoleCommandSender} type senders can execute the command.
+ */
+ IContextFilter CONSOLE_ONLY = filterSender(Priority.VERY_EARLY, Validate::isConsole);
+
+ /**
+ * This filter is not working as intended.
+ * <p>
+ * There is supposed to be a permission filter that takes a base, and appends the command's address to the base, and checks that permission.
+ */
+ IContextFilter INHERIT_PERMISSIONS = Priority.PERMISSION.getInheritor();
+
+ static IContextFilter fromCheckedRunnable(Priority priority, CheckedRunnable<? extends CommandException> runnable) {
+ return new IContextFilter() {
+ @Override
+ public void filterContext(ExecutionContext context) throws CommandException {
+ runnable.checkedRun();
+ }
+
+ @Override
+ public Priority getPriority() {
+ return priority;
+ }
+ };
+ }
+
+ static IContextFilter filterSender(Priority priority, CheckedConsumer<? super CommandSender, ? extends CommandException> consumer) {
+ return new IContextFilter() {
+ @Override
+ public void filterContext(ExecutionContext context) throws CommandException {
+ consumer.checkedAccept(context.getSender());
+ }
+
+ @Override
+ public Priority getPriority() {
+ return priority;
+ }
+ };
+ }
+
+ static IContextFilter permission(String permission) {
+ return new PermissionContextFilter(permission);
+ }
+
+ static IContextFilter permission(String permission, String failMessage) {
+ return new PermissionContextFilter(permission, failMessage);
+ }
+
+ static IContextFilter inheritablePermission(String permission) {
+ return new PermissionContextFilter(permission, true);
+ }
+
+ /**
+ * Produce an inheritable permission context filter.
+ * A permission component is an element in {@code permission.split("\\.")}
+ *
+ * @param permission The permission that is required for the command that this is directly assigned to
+ * @param componentInsertionIndex the index where any sub-components are inserted. -1 for "at the end".
+ * @param failMessage the message to send if the permission is not met
+ * @return the context filter
+ * @throws IllegalArgumentException if componentInsertionIndex is out of range
+ */
+ static IContextFilter inheritablePermission(String permission, int componentInsertionIndex, String failMessage) {
+ return new PermissionContextFilter(permission, componentInsertionIndex, failMessage);
+ }
+
+}
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/InheritingContextFilter.java b/dicore3/command/src/main/java/io/dico/dicore/command/InheritingContextFilter.java
index 0b4875b..58cd7a6 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/InheritingContextFilter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/InheritingContextFilter.java
@@ -1,64 +1,64 @@
-package io.dico.dicore.command;
-
-import java.util.List;
-
-public abstract class InheritingContextFilter implements IContextFilter {
- private static final String[] emptyStringArray = new String[0];
-
- private static String[] addParent(String[] path, String parent) {
- String[] out = new String[path.length + 1];
- System.arraycopy(path, 0, out, 1, path.length);
- out[0] = parent;
- return out;
- }
-
- protected abstract boolean isInherited(IContextFilter filter);
-
- @Override
- public void filterContext(ExecutionContext context) throws CommandException {
- ICommandAddress address = context.getAddress();
-
- String[] traversedPath = emptyStringArray;
- do {
- traversedPath = addParent(traversedPath, address.getMainKey());
- address = address.getParent();
-
- if (address != null && address.hasCommand()) {
- boolean doBreak = true;
-
- Command command = address.getCommand();
- List<IContextFilter> contextFilterList = command.getContextFilters();
- for (IContextFilter filter : contextFilterList) {
- if (isInherited(filter)) {
- if (filter == this) {
- // do the same for next parent
- // this method is necessary to keep traversedPath information
- doBreak = false;
- } else {
- filter.filterSubContext(context, traversedPath);
- }
- }
- }
-
- if (doBreak) {
- break;
- }
- }
- } while (address != null);
- }
-
- static InheritingContextFilter inheritingPriority(Priority priority) {
- return new InheritingContextFilter() {
- @Override
- protected boolean isInherited(IContextFilter filter) {
- return filter.getPriority() == priority;
- }
-
- @Override
- public Priority getPriority() {
- return priority;
- }
- };
- }
-
-}
+package io.dico.dicore.command;
+
+import java.util.List;
+
+public abstract class InheritingContextFilter implements IContextFilter {
+ private static final String[] emptyStringArray = new String[0];
+
+ private static String[] addParent(String[] path, String parent) {
+ String[] out = new String[path.length + 1];
+ System.arraycopy(path, 0, out, 1, path.length);
+ out[0] = parent;
+ return out;
+ }
+
+ protected abstract boolean isInherited(IContextFilter filter);
+
+ @Override
+ public void filterContext(ExecutionContext context) throws CommandException {
+ ICommandAddress address = context.getAddress();
+
+ String[] traversedPath = emptyStringArray;
+ do {
+ traversedPath = addParent(traversedPath, address.getMainKey());
+ address = address.getParent();
+
+ if (address != null && address.hasCommand()) {
+ boolean doBreak = true;
+
+ Command command = address.getCommand();
+ List<IContextFilter> contextFilterList = command.getContextFilters();
+ for (IContextFilter filter : contextFilterList) {
+ if (isInherited(filter)) {
+ if (filter == this) {
+ // do the same for next parent
+ // this method is necessary to keep traversedPath information
+ doBreak = false;
+ } else {
+ filter.filterSubContext(context, traversedPath);
+ }
+ }
+ }
+
+ if (doBreak) {
+ break;
+ }
+ }
+ } while (address != null);
+ }
+
+ static InheritingContextFilter inheritingPriority(Priority priority) {
+ return new InheritingContextFilter() {
+ @Override
+ protected boolean isInherited(IContextFilter filter) {
+ return filter.getPriority() == priority;
+ }
+
+ @Override
+ public Priority getPriority() {
+ return priority;
+ }
+ };
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/LambdaCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/LambdaCommand.java
index 71b5ca4..5f55122 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/LambdaCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/LambdaCommand.java
@@ -1,35 +1,35 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.exceptions.checkedfunctions.CheckedBiFunction;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.List;
-import java.util.Objects;
-import java.util.function.BiFunction;
-
-public class LambdaCommand extends ExtendedCommand<LambdaCommand> {
- private CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor;
- private BiFunction<CommandSender, ExecutionContext, List<String>> completer;
-
- public LambdaCommand executor(CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor) {
- this.executor = Objects.requireNonNull(executor);
- return this;
- }
-
- public LambdaCommand completer(BiFunction<CommandSender, ExecutionContext, List<String>> completer) {
- this.completer = Objects.requireNonNull(completer);
- return this;
- }
-
- @Override
- public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
- return executor.checkedApply(sender, context);
- }
-
- @Override
- public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
- return completer == null ? super.tabComplete(sender, context, location) : completer.apply(sender, context);
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.exceptions.checkedfunctions.CheckedBiFunction;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+public class LambdaCommand extends ExtendedCommand<LambdaCommand> {
+ private CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor;
+ private BiFunction<CommandSender, ExecutionContext, List<String>> completer;
+
+ public LambdaCommand executor(CheckedBiFunction<CommandSender, ExecutionContext, String, CommandException> executor) {
+ this.executor = Objects.requireNonNull(executor);
+ return this;
+ }
+
+ public LambdaCommand completer(BiFunction<CommandSender, ExecutionContext, List<String>> completer) {
+ this.completer = Objects.requireNonNull(completer);
+ return this;
+ }
+
+ @Override
+ public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
+ return executor.checkedApply(sender, context);
+ }
+
+ @Override
+ public List<String> tabComplete(CommandSender sender, ExecutionContext context, Location location) {
+ return completer == null ? super.tabComplete(sender, context, location) : completer.apply(sender, context);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
index 0cfd755..70e3e03 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/ModifiableCommandAddress.java
@@ -1,312 +1,312 @@
-package io.dico.dicore.command;
-
-import io.dico.dicore.command.chat.ChatHandlers;
-import io.dico.dicore.command.chat.IChatHandler;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.ParameterList;
-import io.dico.dicore.command.predef.DefaultGroupCommand;
-import io.dico.dicore.command.predef.HelpCommand;
-import io.dico.dicore.command.predef.PredefinedCommand;
-
-import java.util.*;
-
-public abstract class ModifiableCommandAddress implements ICommandAddress {
- Map<String, ChildCommandAddress> children;
- Collection<String> childrenMainKeys = Collections.emptyList();
-
- // the chat handler as configured by the programmer
- IChatHandler chatHandler;
- // cache for the algorithm that finds the first chat handler going up the tree
- transient IChatHandler cachedChatHandlerFallback;
-
- ModifiableCommandAddress helpChild;
-
- public ModifiableCommandAddress() {
- this.children = new LinkedHashMap<>(4);
- }
-
- @Override
- public boolean hasParent() {
- return getParent() != null;
- }
-
- @Override
- public boolean hasCommand() {
- return getCommand() != null;
- }
-
- @Override
- public boolean hasUserDeclaredCommand() {
- Command command = getCommand();
- return command != null && !(command instanceof PredefinedCommand);
- }
-
- @Override
- public Command getCommand() {
- return null;
- }
-
- @Override
- public boolean isRoot() {
- return false;
- }
-
- @Override
- public List<String> getNames() {
- return null;
- }
-
- @Override
- public List<String> getAliases() {
- List<String> names = getNames();
- if (names == null) {
- return null;
- }
- if (names.isEmpty()) {
- return Collections.emptyList();
- }
- return names.subList(1, names.size());
- }
-
- @Override
- public String getMainKey() {
- return null;
- }
-
- public void setCommand(Command command) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public abstract ModifiableCommandAddress getParent();
-
- @Override
- public RootCommandAddress getRoot() {
- ModifiableCommandAddress out = this;
- while (out.hasParent()) {
- out = out.getParent();
- }
- return out.isRoot() ? (RootCommandAddress) out : null;
- }
-
- @Override
- public int getDepth() {
- int depth = 0;
- ICommandAddress address = this;
- while (address.hasParent()) {
- address = address.getParent();
- depth++;
- }
- return depth;
- }
-
- @Override
- public boolean isDepthLargerThan(int value) {
- int depth = 0;
- ICommandAddress address = this;
- do {
- if (depth > value) {
- return true;
- }
-
- address = address.getParent();
- depth++;
- } while (address != null);
- return false;
- }
-
- @Override
- public boolean hasChildren() {
- return !children.isEmpty();
- }
-
- @Override
- public int getNumberOfRealChildren() {
- return childrenMainKeys.size();
- }
-
- @Override
- public Collection<String> getChildrenMainKeys() {
- return Collections.unmodifiableCollection(childrenMainKeys);
- }
-
- @Override
- public Map<String, ? extends ModifiableCommandAddress> getChildren() {
- return Collections.unmodifiableMap(children);
- }
-
- @Override
- public ChildCommandAddress getChild(String key) {
- return children.get(key);
- }
-
- @Override
- public ChildCommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
- return buffer.hasNext() ? getChild(buffer.next()) : null;
- }
-
- public void addChild(ICommandAddress child) {
- if (!(child instanceof ChildCommandAddress)) {
- throw new IllegalArgumentException("Argument must be a ChildCommandAddress");
- }
-
- ChildCommandAddress mChild = (ChildCommandAddress) child;
- if (mChild.parent != null) {
- throw new IllegalArgumentException("Argument already has a parent");
- }
-
- if (mChild.names.isEmpty()) {
- throw new IllegalArgumentException("Argument must have names");
- }
-
- Iterator<String> names = mChild.modifiableNamesIterator();
- String mainKey = names.next();
-
- if (!childrenMainKeys.contains(mainKey)) {
- if (!(childrenMainKeys instanceof ArrayList)) {
- childrenMainKeys = new ArrayList<>();
- }
- childrenMainKeys.add(mainKey);
- }
-
- children.put(mainKey, mChild);
-
- while (names.hasNext()) {
- String name = names.next();
- if (children.putIfAbsent(name, mChild) != null) {
- names.remove();
- }
- }
-
- mChild.setParent(this);
-
- if (mChild.hasCommand() && mChild.getCommand() instanceof HelpCommand) {
- helpChild = mChild;
- }
- }
-
- public void removeChildren(boolean removeAliases, String... keys) {
- if (keys.length == 0) {
- throw new IllegalArgumentException("keys is empty");
- }
-
- for (String key : keys) {
- ChildCommandAddress keyTarget = getChild(key);
- if (keyTarget == null) {
- continue;
- }
-
- if (removeAliases) {
- Iterator<String> iterator = keyTarget.namesModifiable.iterator();
- boolean first = true;
- while (iterator.hasNext()) {
- String alias = iterator.next();
- ChildCommandAddress aliasTarget = getChild(key);
- if (aliasTarget == keyTarget) {
- if (first) {
- childrenMainKeys.remove(alias);
- }
- children.remove(alias);
- }
- iterator.remove();
- first = false;
- }
-
- } else {
- if (key.equals(keyTarget.getMainKey())) {
- childrenMainKeys.remove(key);
- }
-
- children.remove(key);
- keyTarget.namesModifiable.remove(key);
- }
- }
- }
-
- public boolean hasHelpCommand() {
- return helpChild != null;
- }
-
- public ModifiableCommandAddress getHelpCommand() {
- return helpChild;
- }
-
- @Override
- public IChatHandler getChatHandler() {
- if (cachedChatHandlerFallback == null) {
- if (chatHandler != null) {
- cachedChatHandlerFallback = chatHandler;
- } else if (!hasParent()) {
- cachedChatHandlerFallback = ChatHandlers.defaultChat();
- } else {
- cachedChatHandlerFallback = getParent().getChatHandler();
- }
- }
- return cachedChatHandlerFallback;
- }
-
- public void setChatHandler(IChatHandler chatHandler) {
- this.chatHandler = chatHandler;
- resetChatHandlerCache(new HashSet<>());
- }
-
- void resetChatHandlerCache(Set<ModifiableCommandAddress> dejaVu) {
- if (dejaVu.add(this)) {
- cachedChatHandlerFallback = chatHandler;
- for (ChildCommandAddress address : children.values()) {
- if (address.chatHandler == null) {
- address.resetChatHandlerCache(dejaVu);
- }
- }
- }
- }
-
- @Override
- public ICommandDispatcher getDispatcherForTree() {
- return getRoot();
- }
-
- @Override
- public boolean isCommandTrailing() {
- return false;
- }
-
- public void setCommandTrailing(boolean trailing) {
- throw new UnsupportedOperationException();
- }
-
- void appendDebugInformation(StringBuilder target, String linePrefix, Set<ICommandAddress> seen) {
- target.append('\n').append(linePrefix);
- if (!seen.add(this)) {
- target.append("<duplicate of address '").append(getAddress()).append("'>");
- return;
- }
-
- if (this instanceof ChildCommandAddress) {
- List<String> namesModifiable = ((ChildCommandAddress) this).namesModifiable;
- if (namesModifiable.isEmpty()) {
- target.append("<no key>");
- } else {
- Iterator<String> keys = namesModifiable.iterator();
- target.append(keys.next()).append(' ');
- if (keys.hasNext()) {
- target.append('(').append(keys.next());
- while (keys.hasNext()) {
- target.append(" ,").append(keys.next());
- }
- target.append(") ");
- }
- }
- } else {
- target.append("<root> ");
- }
-
- String commandClass = hasCommand() ? getCommand().getClass().getCanonicalName() : "<no command>";
- target.append(commandClass);
-
- for (ChildCommandAddress child : new HashSet<>(children.values())) {
- child.appendDebugInformation(target, linePrefix + " ", seen);
- }
- }
-
-}
+package io.dico.dicore.command;
+
+import io.dico.dicore.command.chat.ChatHandlers;
+import io.dico.dicore.command.chat.IChatHandler;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.ParameterList;
+import io.dico.dicore.command.predef.DefaultGroupCommand;
+import io.dico.dicore.command.predef.HelpCommand;
+import io.dico.dicore.command.predef.PredefinedCommand;
+
+import java.util.*;
+
+public abstract class ModifiableCommandAddress implements ICommandAddress {
+ Map<String, ChildCommandAddress> children;
+ Collection<String> childrenMainKeys = Collections.emptyList();
+
+ // the chat handler as configured by the programmer
+ IChatHandler chatHandler;
+ // cache for the algorithm that finds the first chat handler going up the tree
+ transient IChatHandler cachedChatHandlerFallback;
+
+ ModifiableCommandAddress helpChild;
+
+ public ModifiableCommandAddress() {
+ this.children = new LinkedHashMap<>(4);
+ }
+
+ @Override
+ public boolean hasParent() {
+ return getParent() != null;
+ }
+
+ @Override
+ public boolean hasCommand() {
+ return getCommand() != null;
+ }
+
+ @Override
+ public boolean hasUserDeclaredCommand() {
+ Command command = getCommand();
+ return command != null && !(command instanceof PredefinedCommand);
+ }
+
+ @Override
+ public Command getCommand() {
+ return null;
+ }
+
+ @Override
+ public boolean isRoot() {
+ return false;
+ }
+
+ @Override
+ public List<String> getNames() {
+ return null;
+ }
+
+ @Override
+ public List<String> getAliases() {
+ List<String> names = getNames();
+ if (names == null) {
+ return null;
+ }
+ if (names.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return names.subList(1, names.size());
+ }
+
+ @Override
+ public String getMainKey() {
+ return null;
+ }
+
+ public void setCommand(Command command) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public abstract ModifiableCommandAddress getParent();
+
+ @Override
+ public RootCommandAddress getRoot() {
+ ModifiableCommandAddress out = this;
+ while (out.hasParent()) {
+ out = out.getParent();
+ }
+ return out.isRoot() ? (RootCommandAddress) out : null;
+ }
+
+ @Override
+ public int getDepth() {
+ int depth = 0;
+ ICommandAddress address = this;
+ while (address.hasParent()) {
+ address = address.getParent();
+ depth++;
+ }
+ return depth;
+ }
+
+ @Override
+ public boolean isDepthLargerThan(int value) {
+ int depth = 0;
+ ICommandAddress address = this;
+ do {
+ if (depth > value) {
+ return true;
+ }
+
+ address = address.getParent();
+ depth++;
+ } while (address != null);
+ return false;
+ }
+
+ @Override
+ public boolean hasChildren() {
+ return !children.isEmpty();
+ }
+
+ @Override
+ public int getNumberOfRealChildren() {
+ return childrenMainKeys.size();
+ }
+
+ @Override
+ public Collection<String> getChildrenMainKeys() {
+ return Collections.unmodifiableCollection(childrenMainKeys);
+ }
+
+ @Override
+ public Map<String, ? extends ModifiableCommandAddress> getChildren() {
+ return Collections.unmodifiableMap(children);
+ }
+
+ @Override
+ public ChildCommandAddress getChild(String key) {
+ return children.get(key);
+ }
+
+ @Override
+ public ChildCommandAddress getChild(ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
+ return buffer.hasNext() ? getChild(buffer.next()) : null;
+ }
+
+ public void addChild(ICommandAddress child) {
+ if (!(child instanceof ChildCommandAddress)) {
+ throw new IllegalArgumentException("Argument must be a ChildCommandAddress");
+ }
+
+ ChildCommandAddress mChild = (ChildCommandAddress) child;
+ if (mChild.parent != null) {
+ throw new IllegalArgumentException("Argument already has a parent");
+ }
+
+ if (mChild.names.isEmpty()) {
+ throw new IllegalArgumentException("Argument must have names");
+ }
+
+ Iterator<String> names = mChild.modifiableNamesIterator();
+ String mainKey = names.next();
+
+ if (!childrenMainKeys.contains(mainKey)) {
+ if (!(childrenMainKeys instanceof ArrayList)) {
+ childrenMainKeys = new ArrayList<>();
+ }
+ childrenMainKeys.add(mainKey);
+ }
+
+ children.put(mainKey, mChild);
+
+ while (names.hasNext()) {
+ String name = names.next();
+ if (children.putIfAbsent(name, mChild) != null) {
+ names.remove();
+ }
+ }
+
+ mChild.setParent(this);
+
+ if (mChild.hasCommand() && mChild.getCommand() instanceof HelpCommand) {
+ helpChild = mChild;
+ }
+ }
+
+ public void removeChildren(boolean removeAliases, String... keys) {
+ if (keys.length == 0) {
+ throw new IllegalArgumentException("keys is empty");
+ }
+
+ for (String key : keys) {
+ ChildCommandAddress keyTarget = getChild(key);
+ if (keyTarget == null) {
+ continue;
+ }
+
+ if (removeAliases) {
+ Iterator<String> iterator = keyTarget.namesModifiable.iterator();
+ boolean first = true;
+ while (iterator.hasNext()) {
+ String alias = iterator.next();
+ ChildCommandAddress aliasTarget = getChild(key);
+ if (aliasTarget == keyTarget) {
+ if (first) {
+ childrenMainKeys.remove(alias);
+ }
+ children.remove(alias);
+ }
+ iterator.remove();
+ first = false;
+ }
+
+ } else {
+ if (key.equals(keyTarget.getMainKey())) {
+ childrenMainKeys.remove(key);
+ }
+
+ children.remove(key);
+ keyTarget.namesModifiable.remove(key);
+ }
+ }
+ }
+
+ public boolean hasHelpCommand() {
+ return helpChild != null;
+ }
+
+ public ModifiableCommandAddress getHelpCommand() {
+ return helpChild;
+ }
+
+ @Override
+ public IChatHandler getChatHandler() {
+ if (cachedChatHandlerFallback == null) {
+ if (chatHandler != null) {
+ cachedChatHandlerFallback = chatHandler;
+ } else if (!hasParent()) {
+ cachedChatHandlerFallback = ChatHandlers.defaultChat();
+ } else {
+ cachedChatHandlerFallback = getParent().getChatHandler();
+ }
+ }
+ return cachedChatHandlerFallback;
+ }
+
+ public void setChatHandler(IChatHandler chatHandler) {
+ this.chatHandler = chatHandler;
+ resetChatHandlerCache(new HashSet<>());
+ }
+
+ void resetChatHandlerCache(Set<ModifiableCommandAddress> dejaVu) {
+ if (dejaVu.add(this)) {
+ cachedChatHandlerFallback = chatHandler;
+ for (ChildCommandAddress address : children.values()) {
+ if (address.chatHandler == null) {
+ address.resetChatHandlerCache(dejaVu);
+ }
+ }
+ }
+ }
+
+ @Override
+ public ICommandDispatcher getDispatcherForTree() {
+ return getRoot();
+ }
+
+ @Override
+ public boolean isCommandTrailing() {
+ return false;
+ }
+
+ public void setCommandTrailing(boolean trailing) {
+ throw new UnsupportedOperationException();
+ }
+
+ void appendDebugInformation(StringBuilder target, String linePrefix, Set<ICommandAddress> seen) {
+ target.append('\n').append(linePrefix);
+ if (!seen.add(this)) {
+ target.append("<duplicate of address '").append(getAddress()).append("'>");
+ return;
+ }
+
+ if (this instanceof ChildCommandAddress) {
+ List<String> namesModifiable = ((ChildCommandAddress) this).namesModifiable;
+ if (namesModifiable.isEmpty()) {
+ target.append("<no key>");
+ } else {
+ Iterator<String> keys = namesModifiable.iterator();
+ target.append(keys.next()).append(' ');
+ if (keys.hasNext()) {
+ target.append('(').append(keys.next());
+ while (keys.hasNext()) {
+ target.append(" ,").append(keys.next());
+ }
+ target.append(") ");
+ }
+ }
+ } else {
+ target.append("<root> ");
+ }
+
+ String commandClass = hasCommand() ? getCommand().getClass().getCanonicalName() : "<no command>";
+ target.append(commandClass);
+
+ for (ChildCommandAddress child : new HashSet<>(children.values())) {
+ child.appendDebugInformation(target, linePrefix + " ", seen);
+ }
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java b/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
index 75b2035..c996356 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/PermissionContextFilter.java
@@ -1,136 +1,136 @@
-package io.dico.dicore.command;
-
-import java.util.List;
-import java.util.Objects;
-
-public class PermissionContextFilter implements IContextFilter {
- private String permission;
- private String[] permissionComponents;
- private int componentInsertionIndex;
- private String failMessage;
-
- public PermissionContextFilter(String permission) {
- this.permission = Objects.requireNonNull(permission);
- }
-
- public PermissionContextFilter(String permission, String failMessage) {
- this(permission);
- this.failMessage = failMessage;
- }
-
- public PermissionContextFilter(String permission, boolean inheritable) {
- this(permission, null, inheritable);
- }
-
- public PermissionContextFilter(String permission, String failMessage, boolean inheritable) {
- this(permission, failMessage);
- if (inheritable) {
- setupInheritability(-1);
- }
- }
-
- public PermissionContextFilter(String permission, int componentInsertionIndex, String failMessage) {
- this(permission, failMessage);
- setupInheritability(componentInsertionIndex);
- }
-
- private void setupInheritability(int componentInsertionIndex) {
- this.permissionComponents = permission.split("\\.");
- this.componentInsertionIndex = componentInsertionIndex < 0 ? permissionComponents.length : componentInsertionIndex;
- if (componentInsertionIndex > permissionComponents.length) throw new IllegalArgumentException();
- }
-
- private void doFilter(ExecutionContext context, String permission) throws CommandException {
- if (failMessage != null) {
- Validate.isAuthorized(context.getSender(), permission, failMessage);
- } else {
- Validate.isAuthorized(context.getSender(), permission);
- }
- }
-
- @Override
- public void filterContext(ExecutionContext context) throws CommandException {
- doFilter(context, permission);
- }
-
- public String getInheritedPermission(String[] components) {
- int insertedAmount = components.length;
- String[] currentComponents = permissionComponents;
- int currentAmount = currentComponents.length;
- String[] targetArray = new String[currentAmount + insertedAmount];
-
- int insertionIndex;
- //int newInsertionIndex;
- if (componentInsertionIndex == -1) {
- insertionIndex = currentAmount;
- //newInsertionIndex = -1;
- } else {
- insertionIndex = componentInsertionIndex;
- //newInsertionIndex = insertionIndex + insertedAmount;
- }
-
- // copy the current components up to insertionIndex
- System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
- // copy the new components into the array at insertionIndex
- System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
- // copy the current components from insertionIndex + inserted amount
- System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
-
- return String.join(".", targetArray);
- }
-
- @Override
- public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
- if (isInheritable()) {
- doFilter(subContext, getInheritedPermission(path));
- }
- }
-
- @Override
- public Priority getPriority() {
- return Priority.PERMISSION;
- }
-
- public boolean isInheritable() {
- return permissionComponents != null;
- }
-
- public String getPermission() {
- return permission;
- }
-
- public int getComponentInsertionIndex() {
- return componentInsertionIndex;
- }
-
- public String getFailMessage() {
- return failMessage;
- }
-
- /*
- private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf())
-
- private fun getPermissionsOf(address: ICommandAddress, path: Array<String>, result: MutableList<String>): List<String> {
- val command = address.command ?: return result
-
- var inherited = false
- for (filter in command.contextFilters) {
- when (filter) {
- is PermissionContextFilter -> {
- if (path.isEmpty()) result.add(filter.permission)
- else if (filter.isInheritable) result.add(filter.getInheritedPermission(path))
- }
- is InheritingContextFilter -> {
- if (filter.priority == PERMISSION && address.hasParent() && !inherited) {
- inherited = true
- getPermissionsOf(address.parent, arrayOf(address.mainKey, *path), result)
- }
- }
- }
- }
-
- return result
- }
- */
-
-}
+package io.dico.dicore.command;
+
+import java.util.List;
+import java.util.Objects;
+
+public class PermissionContextFilter implements IContextFilter {
+ private String permission;
+ private String[] permissionComponents;
+ private int componentInsertionIndex;
+ private String failMessage;
+
+ public PermissionContextFilter(String permission) {
+ this.permission = Objects.requireNonNull(permission);
+ }
+
+ public PermissionContextFilter(String permission, String failMessage) {
+ this(permission);
+ this.failMessage = failMessage;
+ }
+
+ public PermissionContextFilter(String permission, boolean inheritable) {
+ this(permission, null, inheritable);
+ }
+
+ public PermissionContextFilter(String permission, String failMessage, boolean inheritable) {
+ this(permission, failMessage);
+ if (inheritable) {
+ setupInheritability(-1);
+ }
+ }
+
+ public PermissionContextFilter(String permission, int componentInsertionIndex, String failMessage) {
+ this(permission, failMessage);
+ setupInheritability(componentInsertionIndex);
+ }
+
+ private void setupInheritability(int componentInsertionIndex) {
+ this.permissionComponents = permission.split("\\.");
+ this.componentInsertionIndex = componentInsertionIndex < 0 ? permissionComponents.length : componentInsertionIndex;
+ if (componentInsertionIndex > permissionComponents.length) throw new IllegalArgumentException();
+ }
+
+ private void doFilter(ExecutionContext context, String permission) throws CommandException {
+ if (failMessage != null) {
+ Validate.isAuthorized(context.getSender(), permission, failMessage);
+ } else {
+ Validate.isAuthorized(context.getSender(), permission);
+ }
+ }
+
+ @Override
+ public void filterContext(ExecutionContext context) throws CommandException {
+ doFilter(context, permission);
+ }
+
+ public String getInheritedPermission(String[] components) {
+ int insertedAmount = components.length;
+ String[] currentComponents = permissionComponents;
+ int currentAmount = currentComponents.length;
+ String[] targetArray = new String[currentAmount + insertedAmount];
+
+ int insertionIndex;
+ //int newInsertionIndex;
+ if (componentInsertionIndex == -1) {
+ insertionIndex = currentAmount;
+ //newInsertionIndex = -1;
+ } else {
+ insertionIndex = componentInsertionIndex;
+ //newInsertionIndex = insertionIndex + insertedAmount;
+ }
+
+ // copy the current components up to insertionIndex
+ System.arraycopy(currentComponents, 0, targetArray, 0, insertionIndex);
+ // copy the new components into the array at insertionIndex
+ System.arraycopy(components, 0, targetArray, insertionIndex, insertedAmount);
+ // copy the current components from insertionIndex + inserted amount
+ System.arraycopy(currentComponents, insertionIndex, targetArray, insertionIndex + insertedAmount, currentAmount - insertionIndex);
+
+ return String.join(".", targetArray);
+ }
+
+ @Override
+ public void filterSubContext(ExecutionContext subContext, String... path) throws CommandException {
+ if (isInheritable()) {
+ doFilter(subContext, getInheritedPermission(path));
+ }
+ }
+
+ @Override
+ public Priority getPriority() {
+ return Priority.PERMISSION;
+ }
+
+ public boolean isInheritable() {
+ return permissionComponents != null;
+ }
+
+ public String getPermission() {
+ return permission;
+ }
+
+ public int getComponentInsertionIndex() {
+ return componentInsertionIndex;
+ }
+
+ public String getFailMessage() {
+ return failMessage;
+ }
+
+ /*
+ private fun getPermissionsOf(address: ICommandAddress) = getPermissionsOf(address, emptyArray(), mutableListOf())
+
+ private fun getPermissionsOf(address: ICommandAddress, path: Array<String>, result: MutableList<String>): List<String> {
+ val command = address.command ?: return result
+
+ var inherited = false
+ for (filter in command.contextFilters) {
+ when (filter) {
+ is PermissionContextFilter -> {
+ if (path.isEmpty()) result.add(filter.permission)
+ else if (filter.isInheritable) result.add(filter.getInheritedPermission(path))
+ }
+ is InheritingContextFilter -> {
+ if (filter.priority == PERMISSION && address.hasParent() && !inherited) {
+ inherited = true
+ getPermissionsOf(address.parent, arrayOf(address.mainKey, *path), result)
+ }
+ }
+ }
+ }
+
+ return result
+ }
+ */
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
index 44f0540..a17cfb0 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/RootCommandAddress.java
@@ -76,7 +76,7 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
}
- private static void debugChildren(ModifiableCommandAddress address) {
+ public static void debugChildren(ModifiableCommandAddress address) {
Collection<String> keys = address.getChildrenMainKeys();
for (String key : keys) {
ChildCommandAddress child = address.getChild(key);
@@ -233,18 +233,19 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
@Override
public List<String> getTabCompletions(CommandSender sender, Location location, ArgumentBuffer buffer) {
ExecutionContext context = new ExecutionContext(sender, buffer, true);
+ long start = System.currentTimeMillis();
try {
ICommandAddress target = getCommandTarget(context, buffer);
- List<String> out;
- if (target.hasCommand()) {
+ List<String> out = Collections.emptyList();
+ /*if (target.hasCommand()) {
context.setCommand(target.getCommand());
target.getCommand().initializeAndFilterContext(context);
out = target.getCommand().tabComplete(sender, context, location);
} else {
out = Collections.emptyList();
- }
+ }*/
int cursor = buffer.getCursor();
String input;
@@ -269,6 +270,11 @@ public class RootCommandAddress extends ModifiableCommandAddress implements ICom
} catch (CommandException ex) {
return Collections.emptyList();
+ } finally {
+ long duration = System.currentTimeMillis() - start;
+ if (duration > 2) {
+ System.out.println(String.format("Complete took %.3f seconds", duration / 1000.0));
+ }
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/Validate.java b/dicore3/command/src/main/java/io/dico/dicore/command/Validate.java
index 596ad08..3b1f7d4 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/Validate.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/Validate.java
@@ -1,52 +1,52 @@
-package io.dico.dicore.command;
-
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.ConsoleCommandSender;
-import org.bukkit.entity.Player;
-
-import java.util.Optional;
-
-public class Validate {
-
- private Validate() {
-
- }
-
- //@Contract("false, _ -> fail")
- public static void isTrue(boolean expression, String failMessage) throws CommandException {
- if (!expression) {
- throw new CommandException(failMessage);
- }
- }
-
- //@Contract("null, _ -> fail")
- public static void notNull(Object obj, String failMessage) throws CommandException {
- Validate.isTrue(obj != null, failMessage);
- }
-
- public static void isAuthorized(CommandSender sender, String permission, String failMessage) throws CommandException {
- Validate.isTrue(sender.hasPermission(permission), failMessage);
- }
-
- public static void isAuthorized(CommandSender sender, String permission) throws CommandException {
- Validate.isAuthorized(sender, permission, "You do not have permission to use that command");
- }
-
- //@Contract("null -> fail")
- public static void isPlayer(CommandSender sender) throws CommandException {
- isTrue(sender instanceof Player, "That command can only be used by players");
- }
-
- //@Contract("null -> fail")
- public static void isConsole(CommandSender sender) throws CommandException {
- isTrue(sender instanceof ConsoleCommandSender, "That command can only be used by the console");
- }
-
- public static <T> T returnIfPresent(Optional<T> maybe, String failMessage) throws CommandException {
- if (!maybe.isPresent()) {
- throw new CommandException(failMessage);
- }
- return maybe.get();
- }
-
-}
+package io.dico.dicore.command;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.Optional;
+
+public class Validate {
+
+ private Validate() {
+
+ }
+
+ //@Contract("false, _ -> fail")
+ public static void isTrue(boolean expression, String failMessage) throws CommandException {
+ if (!expression) {
+ throw new CommandException(failMessage);
+ }
+ }
+
+ //@Contract("null, _ -> fail")
+ public static void notNull(Object obj, String failMessage) throws CommandException {
+ Validate.isTrue(obj != null, failMessage);
+ }
+
+ public static void isAuthorized(CommandSender sender, String permission, String failMessage) throws CommandException {
+ Validate.isTrue(sender.hasPermission(permission), failMessage);
+ }
+
+ public static void isAuthorized(CommandSender sender, String permission) throws CommandException {
+ Validate.isAuthorized(sender, permission, "You do not have permission to use that command");
+ }
+
+ //@Contract("null -> fail")
+ public static void isPlayer(CommandSender sender) throws CommandException {
+ isTrue(sender instanceof Player, "That command can only be used by players");
+ }
+
+ //@Contract("null -> fail")
+ public static void isConsole(CommandSender sender) throws CommandException {
+ isTrue(sender instanceof ConsoleCommandSender, "That command can only be used by the console");
+ }
+
+ public static <T> T returnIfPresent(Optional<T> maybe, String failMessage) throws CommandException {
+ if (!maybe.isPresent()) {
+ throw new CommandException(failMessage);
+ }
+ return maybe.get();
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/BigRange.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/BigRange.java
index 467ba4b..b0277c6 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/BigRange.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/BigRange.java
@@ -1,52 +1,52 @@
-package io.dico.dicore.command.annotation;
-
-import io.dico.dicore.command.parameter.type.ParameterConfig;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface BigRange {
- Class<?> MEMORY_CLASS = Memory.class;
- ParameterConfig<BigRange, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(BigRange.class);
- Memory DEFAULT = new Memory("MIN", "MAX", "0");
-
- String min() default "MIN";
-
- String max() default "MAX";
-
- String defaultValue() default "0";
-
- class Memory {
- private final String min;
- private final String max;
- private final String defaultValue;
-
- public Memory(BigRange range) {
- this(range.min(), range.max(), range.defaultValue());
- }
-
- public Memory(String min, String max, String defaultValue) {
- this.min = min;
- this.max = max;
- this.defaultValue = defaultValue;
- }
-
- public String min() {
- return min;
- }
-
- public String max() {
- return max;
- }
-
- public String defaultValue() {
- return defaultValue;
- }
-
- }
-
-}
+package io.dico.dicore.command.annotation;
+
+import io.dico.dicore.command.parameter.type.ParameterConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface BigRange {
+ Class<?> MEMORY_CLASS = Memory.class;
+ ParameterConfig<BigRange, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(BigRange.class);
+ Memory DEFAULT = new Memory("MIN", "MAX", "0");
+
+ String min() default "MIN";
+
+ String max() default "MAX";
+
+ String defaultValue() default "0";
+
+ class Memory {
+ private final String min;
+ private final String max;
+ private final String defaultValue;
+
+ public Memory(BigRange range) {
+ this(range.min(), range.max(), range.defaultValue());
+ }
+
+ public Memory(String min, String max, String defaultValue) {
+ this.min = min;
+ this.max = max;
+ this.defaultValue = defaultValue;
+ }
+
+ public String min() {
+ return min;
+ }
+
+ public String max() {
+ return max;
+ }
+
+ public String defaultValue() {
+ return defaultValue;
+ }
+
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Cmd.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Cmd.java
index 109490a..dfad0bb 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Cmd.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Cmd.java
@@ -1,16 +1,16 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface Cmd {
-
- String value();
-
- String[] aliases() default {};
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Cmd {
+
+ String value();
+
+ String[] aliases() default {};
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CmdParamType.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CmdParamType.java
index ea51e44..3eb2d53 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CmdParamType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CmdParamType.java
@@ -1,27 +1,27 @@
-package io.dico.dicore.command.annotation;
-
-import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to mark methods that register a parameter type to the localized selector for use in reflective commands.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface CmdParamType {
-
- /**
- * If this flag is set, the type is registered without its annotation type.
- * As a result, the {@link IParameterTypeSelector} is more likely to select it (faster).
- * This is irrelevant if there is no annotation type or param config.
- *
- * @return true if this parameter type should be registered without its annotation type too
- */
- boolean infolessAlias() default false;
-
-}
-
+package io.dico.dicore.command.annotation;
+
+import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to mark methods that register a parameter type to the localized selector for use in reflective commands.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface CmdParamType {
+
+ /**
+ * If this flag is set, the type is registered without its annotation type.
+ * As a result, the {@link IParameterTypeSelector} is more likely to select it (faster).
+ * This is irrelevant if there is no annotation type or param config.
+ *
+ * @return true if this parameter type should be registered without its annotation type too
+ */
+ boolean infolessAlias() default false;
+
+}
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CommandAnnotationUtils.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CommandAnnotationUtils.java
index 868884c..7983997 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CommandAnnotationUtils.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/CommandAnnotationUtils.java
@@ -1,35 +1,35 @@
-package io.dico.dicore.command.annotation;
-
-public class CommandAnnotationUtils {
-
- /**
- * Get the short description from a {@link Desc} annotation.
- * If {@link Desc#shortVersion()} is given, returns that.
- * Otherwise, returns the first element of {@link Desc#value()}
- * If neither is available, returns null.
- *
- * @param desc the annotation
- * @return the short description
- */
- public static String getShortDescription(Desc desc) {
- String descString;
- if (desc == null) {
- descString = null;
- } else if (!desc.shortVersion().isEmpty()) {
- descString = desc.shortVersion();
- } else if (desc.value().length > 0) {
- descString = desc.value()[0];
- if (desc.value().length > 1) {
- //System.out.println("[Command Warning] Multiline descriptions not supported here. Keep it short for: " + targetIdentifier);
- }
- if (descString != null && descString.isEmpty()) {
- descString = null;
- }
- } else {
- descString = null;
- }
-
- return descString;
- }
-
-}
+package io.dico.dicore.command.annotation;
+
+public class CommandAnnotationUtils {
+
+ /**
+ * Get the short description from a {@link Desc} annotation.
+ * If {@link Desc#shortVersion()} is given, returns that.
+ * Otherwise, returns the first element of {@link Desc#value()}
+ * If neither is available, returns null.
+ *
+ * @param desc the annotation
+ * @return the short description
+ */
+ public static String getShortDescription(Desc desc) {
+ String descString;
+ if (desc == null) {
+ descString = null;
+ } else if (!desc.shortVersion().isEmpty()) {
+ descString = desc.shortVersion();
+ } else if (desc.value().length > 0) {
+ descString = desc.value()[0];
+ if (desc.value().length > 1) {
+ //System.out.println("[Command Warning] Multiline descriptions not supported here. Keep it short for: " + targetIdentifier);
+ }
+ if (descString != null && descString.isEmpty()) {
+ descString = null;
+ }
+ } else {
+ descString = null;
+ }
+
+ return descString;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Desc.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Desc.java
index 0011fb8..ab3e555 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Desc.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Desc.java
@@ -1,27 +1,27 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Desc {
-
- /**
- * Multiline description if {@link #shortVersion} is set.
- * Otherwise, this should be an array with one element (aka, you don't have to add array brackets).
- *
- * @return the multiline description.
- * @see CommandAnnotationUtils#getShortDescription(Desc)
- */
- String[] value();
-
- /**
- * Short description, use if {@link #value} is multi-line.
- * To get a short description from a {@link Desc}, you should use {@link CommandAnnotationUtils#getShortDescription(Desc)}
- *
- * @return short description
- * @see CommandAnnotationUtils#getShortDescription(Desc)
- */
- String shortVersion() default "";
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Desc {
+
+ /**
+ * Multiline description if {@link #shortVersion} is set.
+ * Otherwise, this should be an array with one element (aka, you don't have to add array brackets).
+ *
+ * @return the multiline description.
+ * @see CommandAnnotationUtils#getShortDescription(Desc)
+ */
+ String[] value();
+
+ /**
+ * Short description, use if {@link #value} is multi-line.
+ * To get a short description from a {@link Desc}, you should use {@link CommandAnnotationUtils#getShortDescription(Desc)}
+ *
+ * @return short description
+ * @see CommandAnnotationUtils#getShortDescription(Desc)
+ */
+ String shortVersion() default "";
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Flag.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Flag.java
index 31a47dd..edc50ef 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Flag.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Flag.java
@@ -1,16 +1,16 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface Flag {
-
- String value() default "";
-
- String permission() default "";
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface Flag {
+
+ String value() default "";
+
+ String permission() default "";
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GenerateCommands.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GenerateCommands.java
index 9b7164d..eeff351 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GenerateCommands.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GenerateCommands.java
@@ -1,14 +1,14 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface GenerateCommands {
-
- String[] value() default {"help"};
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface GenerateCommands {
+
+ String[] value() default {"help"};
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GroupMatchedCommands.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GroupMatchedCommands.java
index 53e3e9e..de89e00 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GroupMatchedCommands.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/GroupMatchedCommands.java
@@ -1,68 +1,68 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Annotation to define sub-groups of the group registered reflectively from all methods in a class.
- * <p>
- * Commands are selected for grouping by matching their method's names to a regular expression.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface GroupMatchedCommands {
-
- @Retention(RetentionPolicy.RUNTIME)
- @interface GroupEntry {
-
- /**
- * Regular expression to match method names for this group
- * Must be non-empty
- *
- * @return the regular expression
- */
- String regex();
-
- /**
- * The name or main key of the sub-group or address
- * Must be non-empty
- *
- * @return the group name
- */
- String group();
-
- /**
- * The aliases for the sub-group
- *
- * @return the group aliases
- */
- String[] groupAliases() default {};
-
- /**
- * Generated (predefined) commands for the sub-group
- */
- String[] generatedCommands() default {};
-
- /**
- * @see Desc
- */
- String[] description() default {};
-
- /**
- * @see Desc
- */
- String shortDescription() default "";
- }
-
- /**
- * The defined groups.
- * If a method name matches the regex of multiple groups,
- * groups are prioritized by the order in which they appear in this array.
- *
- * @return the defined groups
- */
- GroupEntry[] value();
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to define sub-groups of the group registered reflectively from all methods in a class.
+ * <p>
+ * Commands are selected for grouping by matching their method's names to a regular expression.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface GroupMatchedCommands {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface GroupEntry {
+
+ /**
+ * Regular expression to match method names for this group
+ * Must be non-empty
+ *
+ * @return the regular expression
+ */
+ String regex();
+
+ /**
+ * The name or main key of the sub-group or address
+ * Must be non-empty
+ *
+ * @return the group name
+ */
+ String group();
+
+ /**
+ * The aliases for the sub-group
+ *
+ * @return the group aliases
+ */
+ String[] groupAliases() default {};
+
+ /**
+ * Generated (predefined) commands for the sub-group
+ */
+ String[] generatedCommands() default {};
+
+ /**
+ * @see Desc
+ */
+ String[] description() default {};
+
+ /**
+ * @see Desc
+ */
+ String shortDescription() default "";
+ }
+
+ /**
+ * The defined groups.
+ * If a method name matches the regex of multiple groups,
+ * groups are prioritized by the order in which they appear in this array.
+ *
+ * @return the defined groups
+ */
+ GroupEntry[] value();
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/NamedArg.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/NamedArg.java
index fa42e6b..d84358b 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/NamedArg.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/NamedArg.java
@@ -1,14 +1,14 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface NamedArg {
-
- String value();
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface NamedArg {
+
+ String value();
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
index 57f53bd..32b0723 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/PreprocessArgs.java
@@ -1,17 +1,17 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-@Deprecated
-public @interface PreprocessArgs {
-
- String tokens() default "\"\"";
-
- char escapeChar() default '\\';
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+@Deprecated
+public @interface PreprocessArgs {
+
+ String tokens() default "\"\"";
+
+ char escapeChar() default '\\';
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Range.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Range.java
index 3fd4160..98aec22 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Range.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/Range.java
@@ -1,67 +1,67 @@
-package io.dico.dicore.command.annotation;
-
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.Validate;
-import io.dico.dicore.command.parameter.type.ParameterConfig;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.PARAMETER)
-public @interface Range {
- Class<?> MEMORY_CLASS = Memory.class;
- ParameterConfig<Range, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(Range.class);
- Memory DEFAULT = new Memory(-Double.MAX_VALUE, Double.MAX_VALUE, 0);
-
- double min() default -Double.MAX_VALUE;
-
- double max() default Double.MAX_VALUE;
-
- double defaultValue() default 0;
-
- class Memory {
- private final double min;
- private final double max;
- private final double defaultValue;
-
- public Memory(Range range) {
- this(range.min(), range.max(), range.defaultValue());
- }
-
- public Memory(double min, double max, double defaultValue) {
- this.min = min;
- this.max = max;
- this.defaultValue = defaultValue;
- }
-
- public double min() {
- return min;
- }
-
- public double max() {
- return max;
- }
-
- public double defaultValue() {
- return defaultValue;
- }
-
- public void validate(Number x, String failMessage) throws CommandException {
- Validate.isTrue(valid(x), failMessage);
- }
-
- public boolean valid(Number x) {
- double d = x.doubleValue();
- return min <= d && d <= max;
- }
-
- public boolean isDefault() {
- return this == DEFAULT || (min == DEFAULT.min && max == DEFAULT.max && defaultValue == DEFAULT.defaultValue);
- }
-
- }
-
-}
+package io.dico.dicore.command.annotation;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.Validate;
+import io.dico.dicore.command.parameter.type.ParameterConfig;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface Range {
+ Class<?> MEMORY_CLASS = Memory.class;
+ ParameterConfig<Range, Memory> CONFIG = ParameterConfig.getMemoryClassFromField(Range.class);
+ Memory DEFAULT = new Memory(-Double.MAX_VALUE, Double.MAX_VALUE, 0);
+
+ double min() default -Double.MAX_VALUE;
+
+ double max() default Double.MAX_VALUE;
+
+ double defaultValue() default 0;
+
+ class Memory {
+ private final double min;
+ private final double max;
+ private final double defaultValue;
+
+ public Memory(Range range) {
+ this(range.min(), range.max(), range.defaultValue());
+ }
+
+ public Memory(double min, double max, double defaultValue) {
+ this.min = min;
+ this.max = max;
+ this.defaultValue = defaultValue;
+ }
+
+ public double min() {
+ return min;
+ }
+
+ public double max() {
+ return max;
+ }
+
+ public double defaultValue() {
+ return defaultValue;
+ }
+
+ public void validate(Number x, String failMessage) throws CommandException {
+ Validate.isTrue(valid(x), failMessage);
+ }
+
+ public boolean valid(Number x) {
+ double d = x.doubleValue();
+ return min <= d && d <= max;
+ }
+
+ public boolean isDefault() {
+ return this == DEFAULT || (min == DEFAULT.min && max == DEFAULT.max && defaultValue == DEFAULT.defaultValue);
+ }
+
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireConsole.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireConsole.java
index 362f05c..3510ca8 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireConsole.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireConsole.java
@@ -1,11 +1,11 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface RequireConsole {
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface RequireConsole {
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireParameters.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireParameters.java
index 02f5548..68d5706 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireParameters.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequireParameters.java
@@ -1,14 +1,14 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface RequireParameters {
-
- int value();
-
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface RequireParameters {
+
+ int value();
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePermissions.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePermissions.java
index d2ba782..13d7167 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePermissions.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePermissions.java
@@ -1,33 +1,33 @@
-package io.dico.dicore.command.annotation;
-
-import io.dico.dicore.command.IContextFilter;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * If this annotation is not present, inheriting permissions is default.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface RequirePermissions {
-
- /**
- * Any permissions that must be present on the sender
- *
- * @return an array of permission nodes
- */
- String[] value();
-
- /**
- * Whether permissions should (also) be inherited from the parent.
- * This uses {@link IContextFilter#INHERIT_PERMISSIONS}
- * This is true by default.
- *
- * @return true if permissions should be inherited.
- */
- boolean inherit() default true;
-
-}
+package io.dico.dicore.command.annotation;
+
+import io.dico.dicore.command.IContextFilter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * If this annotation is not present, inheriting permissions is default.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface RequirePermissions {
+
+ /**
+ * Any permissions that must be present on the sender
+ *
+ * @return an array of permission nodes
+ */
+ String[] value();
+
+ /**
+ * Whether permissions should (also) be inherited from the parent.
+ * This uses {@link IContextFilter#INHERIT_PERMISSIONS}
+ * This is true by default.
+ *
+ * @return true if permissions should be inherited.
+ */
+ boolean inherit() default true;
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePlayer.java b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePlayer.java
index 2165e05..3f447f9 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePlayer.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/annotation/RequirePlayer.java
@@ -1,11 +1,11 @@
-package io.dico.dicore.command.annotation;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.METHOD)
-public @interface RequirePlayer {
-}
+package io.dico.dicore.command.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface RequirePlayer {
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatHandler.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatHandler.java
index c0d23ee..ac2a76d 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatHandler.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/AbstractChatHandler.java
@@ -1,94 +1,94 @@
-package io.dico.dicore.command.chat;
-
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.HelpPages;
-import org.bukkit.command.CommandSender;
-import org.jetbrains.annotations.NotNull;
-
-public class AbstractChatHandler implements IChatHandler {
- private @NotNull HelpPages helpPages;
-
- public AbstractChatHandler(@NotNull HelpPages helpPages) {
- this.helpPages = helpPages;
- }
-
- public AbstractChatHandler() {
- this(HelpPages.newDefaultHelpPages());
- }
-
- @NotNull
- public HelpPages getHelpPages() {
- return helpPages;
- }
-
- public void setHelpPages(@NotNull HelpPages helpPages) {
- this.helpPages = helpPages;
- }
-
- @Override
- public Formatting getChatFormatForType(EMessageType type) {
- switch (type) {
- case EXCEPTION:
- case BAD_NEWS:
- return Formatting.RED;
- case INSTRUCTION:
- case NEUTRAL:
- return Formatting.GRAY;
- case CUSTOM:
- return Formatting.WHITE;
- case INFORMATIVE:
- return Formatting.AQUA;
- case RESULT:
- default:
- case GOOD_NEWS:
- return Formatting.GREEN;
- case WARNING:
- return Formatting.YELLOW;
-
- case DESCRIPTION:
- return Formatting.GREEN;
- case SYNTAX:
- return Formatting.AQUA;
- case HIGHLIGHT:
- return Formatting.RED;
- case SUBCOMMAND:
- return Formatting.GRAY;
- case NUMBER:
- return Formatting.YELLOW;
- }
- }
-
- @Override
- public String getMessagePrefixForType(EMessageType type) {
- return "";
- }
-
- protected String createMessage(EMessageType type, String message) {
- if (message == null || message.isEmpty()) return null;
- return getMessagePrefixForType(type) + getChatFormatForType(type) + message;
- }
-
- @Override
- public String createMessage(ExecutionContext context, EMessageType type, String message) {
- return createMessage(type, message);
- }
-
- @Override
- public String createMessage(CommandSender sender, EMessageType type, String message) {
- return createMessage(type, message);
- }
-
- @Override
- public String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
- return helpPages.getHelpPage(sender, context, address, page);
- }
-
- @Override
- public String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
- return helpPages.getSyntax(sender, context, address);
- }
-
-}
+package io.dico.dicore.command.chat;
+
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.HelpPages;
+import org.bukkit.command.CommandSender;
+import org.jetbrains.annotations.NotNull;
+
+public class AbstractChatHandler implements IChatHandler {
+ private @NotNull HelpPages helpPages;
+
+ public AbstractChatHandler(@NotNull HelpPages helpPages) {
+ this.helpPages = helpPages;
+ }
+
+ public AbstractChatHandler() {
+ this(HelpPages.newDefaultHelpPages());
+ }
+
+ @NotNull
+ public HelpPages getHelpPages() {
+ return helpPages;
+ }
+
+ public void setHelpPages(@NotNull HelpPages helpPages) {
+ this.helpPages = helpPages;
+ }
+
+ @Override
+ public Formatting getChatFormatForType(EMessageType type) {
+ switch (type) {
+ case EXCEPTION:
+ case BAD_NEWS:
+ return Formatting.RED;
+ case INSTRUCTION:
+ case NEUTRAL:
+ return Formatting.GRAY;
+ case CUSTOM:
+ return Formatting.WHITE;
+ case INFORMATIVE:
+ return Formatting.AQUA;
+ case RESULT:
+ default:
+ case GOOD_NEWS:
+ return Formatting.GREEN;
+ case WARNING:
+ return Formatting.YELLOW;
+
+ case DESCRIPTION:
+ return Formatting.GREEN;
+ case SYNTAX:
+ return Formatting.AQUA;
+ case HIGHLIGHT:
+ return Formatting.RED;
+ case SUBCOMMAND:
+ return Formatting.GRAY;
+ case NUMBER:
+ return Formatting.YELLOW;
+ }
+ }
+
+ @Override
+ public String getMessagePrefixForType(EMessageType type) {
+ return "";
+ }
+
+ protected String createMessage(EMessageType type, String message) {
+ if (message == null || message.isEmpty()) return null;
+ return getMessagePrefixForType(type) + getChatFormatForType(type) + message;
+ }
+
+ @Override
+ public String createMessage(ExecutionContext context, EMessageType type, String message) {
+ return createMessage(type, message);
+ }
+
+ @Override
+ public String createMessage(CommandSender sender, EMessageType type, String message) {
+ return createMessage(type, message);
+ }
+
+ @Override
+ public String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
+ return helpPages.getHelpPage(sender, context, address, page);
+ }
+
+ @Override
+ public String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
+ return helpPages.getSyntax(sender, context, address);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/ChatHandlers.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/ChatHandlers.java
index 232d5cf..cebdb45 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/ChatHandlers.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/ChatHandlers.java
@@ -1,20 +1,20 @@
-package io.dico.dicore.command.chat;
-
-/**
- * Static factory methods for {@link IChatHandler}
- */
-public class ChatHandlers {
- private static final IChatHandler defaultChat;
-
- private ChatHandlers() {
-
- }
-
- public static IChatHandler defaultChat() {
- return defaultChat;
- }
-
- static {
- defaultChat = new AbstractChatHandler();
- }
-}
+package io.dico.dicore.command.chat;
+
+/**
+ * Static factory methods for {@link IChatHandler}
+ */
+public class ChatHandlers {
+ private static final IChatHandler defaultChat;
+
+ private ChatHandlers() {
+
+ }
+
+ public static IChatHandler defaultChat() {
+ return defaultChat;
+ }
+
+ static {
+ defaultChat = new AbstractChatHandler();
+ }
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/IChatHandler.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/IChatHandler.java
index 98283ef..0dd6002 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/IChatHandler.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/IChatHandler.java
@@ -1,60 +1,60 @@
-package io.dico.dicore.command.chat;
-
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import org.bukkit.command.CommandSender;
-
-//TODO add methods to send JSON messages
-public interface IChatHandler {
-
- default void sendMessage(ExecutionContext context, EMessageType type, String message) {
- message = createMessage(context, type, message);
- if (message != null) {
- context.getSender().sendMessage(message);
- }
- }
-
- default void sendMessage(CommandSender sender, EMessageType type, String message) {
- message = createMessage(sender, type, message);
- if (message != null) {
- sender.sendMessage(message);
- }
- }
-
- default void handleCommandException(CommandSender sender, ExecutionContext context, CommandException exception) {
- sendMessage(context, EMessageType.EXCEPTION, exception.getMessage());
- }
-
- default void handleException(CommandSender sender, ExecutionContext context, Throwable exception) {
- if (exception instanceof CommandException) {
- handleCommandException(sender, context, (CommandException) exception);
- } else {
- sendMessage(sender, EMessageType.EXCEPTION, "An internal error occurred whilst executing this command");
- exception.printStackTrace();
- }
- }
-
- default void sendHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
- sender.sendMessage(createHelpMessage(sender, context, address, page));
- }
-
- default void sendSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
- sender.sendMessage(createSyntaxMessage(sender, context, address));
- }
-
- Formatting getChatFormatForType(EMessageType type);
-
- String getMessagePrefixForType(EMessageType type);
-
- String createMessage(ExecutionContext context, EMessageType type, String message);
-
- String createMessage(CommandSender sender, EMessageType type, String message);
-
- String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page);
-
- String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address);
-
-}
+package io.dico.dicore.command.chat;
+
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import org.bukkit.command.CommandSender;
+
+//TODO add methods to send JSON messages
+public interface IChatHandler {
+
+ default void sendMessage(ExecutionContext context, EMessageType type, String message) {
+ message = createMessage(context, type, message);
+ if (message != null) {
+ context.getSender().sendMessage(message);
+ }
+ }
+
+ default void sendMessage(CommandSender sender, EMessageType type, String message) {
+ message = createMessage(sender, type, message);
+ if (message != null) {
+ sender.sendMessage(message);
+ }
+ }
+
+ default void handleCommandException(CommandSender sender, ExecutionContext context, CommandException exception) {
+ sendMessage(context, EMessageType.EXCEPTION, exception.getMessage());
+ }
+
+ default void handleException(CommandSender sender, ExecutionContext context, Throwable exception) {
+ if (exception instanceof CommandException) {
+ handleCommandException(sender, context, (CommandException) exception);
+ } else {
+ sendMessage(sender, EMessageType.EXCEPTION, "An internal error occurred whilst executing this command");
+ exception.printStackTrace();
+ }
+ }
+
+ default void sendHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page) {
+ sender.sendMessage(createHelpMessage(sender, context, address, page));
+ }
+
+ default void sendSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address) {
+ sender.sendMessage(createSyntaxMessage(sender, context, address));
+ }
+
+ Formatting getChatFormatForType(EMessageType type);
+
+ String getMessagePrefixForType(EMessageType type);
+
+ String createMessage(ExecutionContext context, EMessageType type, String message);
+
+ String createMessage(CommandSender sender, EMessageType type, String message);
+
+ String createHelpMessage(CommandSender sender, ExecutionContext context, ICommandAddress address, int page);
+
+ String createSyntaxMessage(CommandSender sender, ExecutionContext context, ICommandAddress address);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java
index 4382d93..616e85a 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpPages.java
@@ -1,92 +1,92 @@
-package io.dico.dicore.command.chat.help;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.defaults.*;
-import org.bukkit.permissions.Permissible;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class HelpPages {
- private @NotNull IPageBuilder pageBuilder;
- private @NotNull IPageLayout pageLayout;
- private int pageLength;
- private @NotNull List<IHelpTopic> helpTopics;
- private @NotNull IHelpTopic syntaxTopic;
-
- public HelpPages(@NotNull IPageBuilder pageBuilder, @NotNull IPageLayout pageLayout, int pageLength, @NotNull IHelpTopic syntaxTopic, @NotNull List<IHelpTopic> helpTopics) {
- this.pageBuilder = pageBuilder;
- this.pageLayout = pageLayout;
- this.pageLength = pageLength;
- this.syntaxTopic = syntaxTopic;
- this.helpTopics = helpTopics;
- }
-
- public HelpPages(IPageBuilder pageBuilder, IPageLayout pageLayout, int pageLength, IHelpTopic syntaxTopic, IHelpTopic... helpTopics) {
- this(pageBuilder, pageLayout, pageLength, syntaxTopic, new ArrayList<>(Arrays.asList(helpTopics)));
- }
-
- @SuppressWarnings("RedundantArrayCreation")
- public static HelpPages newDefaultHelpPages() {
- IHelpTopic syntaxTopic = new SyntaxHelpTopic();
- return new HelpPages(new DefaultPageBuilder(), new DefaultPageLayout(), 12,
- syntaxTopic, new IHelpTopic[]{new DescriptionHelpTopic(), syntaxTopic, new SubcommandsHelpTopic()});
- }
-
- public @NotNull IPageBuilder getPageBuilder() {
- return pageBuilder;
- }
-
- public void setPageBuilder(@NotNull IPageBuilder pageBuilder) {
- this.pageBuilder = pageBuilder;
- }
-
- public @NotNull IPageLayout getPageLayout() {
- return pageLayout;
- }
-
- public void setPageLayout(@NotNull IPageLayout pageLayout) {
- this.pageLayout = pageLayout;
- }
-
- public int getPageLength() {
- return pageLength;
- }
-
- public void setPageLength(int pageLength) {
- this.pageLength = pageLength;
- }
-
- public @NotNull IHelpTopic getSyntaxTopic() {
- return syntaxTopic;
- }
-
- public void setSyntaxTopic(@NotNull IHelpTopic syntaxTopic) {
- this.syntaxTopic = syntaxTopic;
- }
-
- @NotNull
- public List<IHelpTopic> getHelpTopics() {
- return helpTopics;
- }
-
- public void setHelpTopics(@NotNull List<IHelpTopic> helpTopics) {
- this.helpTopics = helpTopics;
- }
-
- public @NotNull String getHelpPage(Permissible viewer, ExecutionContext context, ICommandAddress address, int page) {
- return pageBuilder.getPage(helpTopics, pageLayout, address, viewer, context, page, pageLength);
- }
-
- public @NotNull String getSyntax(Permissible viewer, ExecutionContext context, ICommandAddress address) {
- List<IHelpComponent> components = syntaxTopic.getComponents(address, viewer, context, false);
- if (components.isEmpty()) {
- return getHelpPage(viewer, context, address, 1);
- }
- return DefaultPageBuilder.combine(components);
- }
-
-}
+package io.dico.dicore.command.chat.help;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.defaults.*;
+import org.bukkit.permissions.Permissible;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class HelpPages {
+ private @NotNull IPageBuilder pageBuilder;
+ private @NotNull IPageLayout pageLayout;
+ private int pageLength;
+ private @NotNull List<IHelpTopic> helpTopics;
+ private @NotNull IHelpTopic syntaxTopic;
+
+ public HelpPages(@NotNull IPageBuilder pageBuilder, @NotNull IPageLayout pageLayout, int pageLength, @NotNull IHelpTopic syntaxTopic, @NotNull List<IHelpTopic> helpTopics) {
+ this.pageBuilder = pageBuilder;
+ this.pageLayout = pageLayout;
+ this.pageLength = pageLength;
+ this.syntaxTopic = syntaxTopic;
+ this.helpTopics = helpTopics;
+ }
+
+ public HelpPages(IPageBuilder pageBuilder, IPageLayout pageLayout, int pageLength, IHelpTopic syntaxTopic, IHelpTopic... helpTopics) {
+ this(pageBuilder, pageLayout, pageLength, syntaxTopic, new ArrayList<>(Arrays.asList(helpTopics)));
+ }
+
+ @SuppressWarnings("RedundantArrayCreation")
+ public static HelpPages newDefaultHelpPages() {
+ IHelpTopic syntaxTopic = new SyntaxHelpTopic();
+ return new HelpPages(new DefaultPageBuilder(), new DefaultPageLayout(), 12,
+ syntaxTopic, new IHelpTopic[]{new DescriptionHelpTopic(), syntaxTopic, new SubcommandsHelpTopic()});
+ }
+
+ public @NotNull IPageBuilder getPageBuilder() {
+ return pageBuilder;
+ }
+
+ public void setPageBuilder(@NotNull IPageBuilder pageBuilder) {
+ this.pageBuilder = pageBuilder;
+ }
+
+ public @NotNull IPageLayout getPageLayout() {
+ return pageLayout;
+ }
+
+ public void setPageLayout(@NotNull IPageLayout pageLayout) {
+ this.pageLayout = pageLayout;
+ }
+
+ public int getPageLength() {
+ return pageLength;
+ }
+
+ public void setPageLength(int pageLength) {
+ this.pageLength = pageLength;
+ }
+
+ public @NotNull IHelpTopic getSyntaxTopic() {
+ return syntaxTopic;
+ }
+
+ public void setSyntaxTopic(@NotNull IHelpTopic syntaxTopic) {
+ this.syntaxTopic = syntaxTopic;
+ }
+
+ @NotNull
+ public List<IHelpTopic> getHelpTopics() {
+ return helpTopics;
+ }
+
+ public void setHelpTopics(@NotNull List<IHelpTopic> helpTopics) {
+ this.helpTopics = helpTopics;
+ }
+
+ public @NotNull String getHelpPage(Permissible viewer, ExecutionContext context, ICommandAddress address, int page) {
+ return pageBuilder.getPage(helpTopics, pageLayout, address, viewer, context, page, pageLength);
+ }
+
+ public @NotNull String getSyntax(Permissible viewer, ExecutionContext context, ICommandAddress address) {
+ List<IHelpComponent> components = syntaxTopic.getComponents(address, viewer, context, false);
+ if (components.isEmpty()) {
+ return getHelpPage(viewer, context, address, 1);
+ }
+ return DefaultPageBuilder.combine(components);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java
index 7aeb304..b295a35 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/HelpTopicModifier.java
@@ -1,24 +1,24 @@
-package io.dico.dicore.command.chat.help;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-import java.util.Objects;
-
-public abstract class HelpTopicModifier implements IHelpTopic {
- private final IHelpTopic delegate;
-
- public HelpTopicModifier(IHelpTopic delegate) {
- this.delegate = Objects.requireNonNull(delegate);
- }
-
- @Override
- public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
- return modify(delegate.getComponents(target, viewer, context, true), target, viewer, context);
- }
-
- protected abstract List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context);
-
-}
+package io.dico.dicore.command.chat.help;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+import java.util.Objects;
+
+public abstract class HelpTopicModifier implements IHelpTopic {
+ private final IHelpTopic delegate;
+
+ public HelpTopicModifier(IHelpTopic delegate) {
+ this.delegate = Objects.requireNonNull(delegate);
+ }
+
+ @Override
+ public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
+ return modify(delegate.getComponents(target, viewer, context, true), target, viewer, context);
+ }
+
+ protected abstract List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpComponent.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpComponent.java
index e1867b5..446c7d7 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpComponent.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpComponent.java
@@ -1,9 +1,9 @@
-package io.dico.dicore.command.chat.help;
-
-public interface IHelpComponent {
-
- int lineCount();
-
- void appendTo(StringBuilder sb);
-
-}
+package io.dico.dicore.command.chat.help;
+
+public interface IHelpComponent {
+
+ int lineCount();
+
+ void appendTo(StringBuilder sb);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java
index 0b3fba2..0f1b5c9 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IHelpTopic.java
@@ -1,23 +1,23 @@
-package io.dico.dicore.command.chat.help;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-
-public interface IHelpTopic {
-
- /**
- * Get the components of this help topic
- *
- * @param target The address of the command to provide help about
- * @param viewer The permissible that the page will be shown to (null -> choose a default set).
- * @param context Context of the command execution
- * @param isForPage A boolean indicating if the components are to be used in a page (for help)
- * @return a mutable list of components to include in the help pages
- */
- List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage);
-
-
-}
+package io.dico.dicore.command.chat.help;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+
+public interface IHelpTopic {
+
+ /**
+ * Get the components of this help topic
+ *
+ * @param target The address of the command to provide help about
+ * @param viewer The permissible that the page will be shown to (null -> choose a default set).
+ * @param context Context of the command execution
+ * @param isForPage A boolean indicating if the components are to be used in a page (for help)
+ * @return a mutable list of components to include in the help pages
+ */
+ List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage);
+
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBorder.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBorder.java
index 1ae3561..2789975 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBorder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBorder.java
@@ -1,7 +1,7 @@
-package io.dico.dicore.command.chat.help;
-
-public interface IPageBorder extends IHelpComponent {
-
- void setPageCount(int pageCount);
-
-}
+package io.dico.dicore.command.chat.help;
+
+public interface IPageBorder extends IHelpComponent {
+
+ void setPageCount(int pageCount);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBuilder.java
index 86d9450..0584ade 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBuilder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageBuilder.java
@@ -1,13 +1,13 @@
-package io.dico.dicore.command.chat.help;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-
-public interface IPageBuilder {
-
- String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum, int pageLen);
-
-}
+package io.dico.dicore.command.chat.help;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+
+public interface IPageBuilder {
+
+ String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum, int pageLen);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageLayout.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageLayout.java
index 3223e32..32c41d7 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageLayout.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/IPageLayout.java
@@ -1,20 +1,20 @@
-package io.dico.dicore.command.chat.help;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import org.bukkit.permissions.Permissible;
-
-public interface IPageLayout {
-
- /**
- * Get the page borders for a help page
- *
- * @param target the address that help is displayed for
- * @param viewer the viewer of the help page, or null if irrelevant
- * @param context the context of the execution
- * @param pageNum the page number as displayed in the help page (so it's 1-bound and not 0-bound)
- * @return the page borders.
- */
- PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum);
-
-}
+package io.dico.dicore.command.chat.help;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import org.bukkit.permissions.Permissible;
+
+public interface IPageLayout {
+
+ /**
+ * Get the page borders for a help page
+ *
+ * @param target the address that help is displayed for
+ * @param viewer the viewer of the help page, or null if irrelevant
+ * @param context the context of the execution
+ * @param pageNum the page number as displayed in the help page (so it's 1-bound and not 0-bound)
+ * @return the page borders.
+ */
+ PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/PageBorders.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/PageBorders.java
index 43c0514..cd105b1 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/PageBorders.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/PageBorders.java
@@ -1,76 +1,76 @@
-package io.dico.dicore.command.chat.help;
-
-import java.util.Arrays;
-
-public class PageBorders {
- private final IPageBorder header, footer;
-
- public PageBorders(IPageBorder header, IPageBorder footer) {
- this.header = header;
- this.footer = footer;
- }
-
- public IPageBorder getHeader() {
- return header;
- }
-
- public IPageBorder getFooter() {
- return footer;
- }
-
- public static IPageBorder simpleBorder(String... lines) {
- return new SimplePageBorder(lines);
- }
-
- public static IPageBorder disappearingBorder(int pageNum, String... lines) {
- return disappearingBorder(pageNum, 0, lines);
- }
-
- public static IPageBorder disappearingBorder(int pageNum, int keptLines, String... lines) {
- return new DisappearingPageBorder(pageNum, keptLines, lines);
- }
-
- static class SimplePageBorder extends SimpleHelpComponent implements IPageBorder {
- private final String replacedSequence;
-
- public SimplePageBorder(String replacedSequence, String... lines) {
- super(lines);
- this.replacedSequence = replacedSequence;
- }
-
- public SimplePageBorder(String... lines) {
- super(lines);
- this.replacedSequence = "%pageCount%";
- }
-
- @Override
- public void setPageCount(int pageCount) {
- String[] lines = this.lines;
- for (int i = 0; i < lines.length; i++) {
- lines[i] = lines[i].replace(replacedSequence, Integer.toString(pageCount));
- }
- }
-
- }
-
- static class DisappearingPageBorder extends SimpleHelpComponent implements IPageBorder {
- private final int pageNum;
- private final int keptLines;
-
- public DisappearingPageBorder(int pageNum, int keptLines, String... lines) {
- super(lines);
- this.pageNum = pageNum;
- this.keptLines = keptLines;
- }
-
- @Override
- public void setPageCount(int pageCount) {
- if (pageCount == pageNum) {
- String[] lines = this.lines;
- this.lines = Arrays.copyOfRange(lines, Math.max(0, lines.length - keptLines), lines.length);
- }
- }
-
- }
-
-}
+package io.dico.dicore.command.chat.help;
+
+import java.util.Arrays;
+
+public class PageBorders {
+ private final IPageBorder header, footer;
+
+ public PageBorders(IPageBorder header, IPageBorder footer) {
+ this.header = header;
+ this.footer = footer;
+ }
+
+ public IPageBorder getHeader() {
+ return header;
+ }
+
+ public IPageBorder getFooter() {
+ return footer;
+ }
+
+ public static IPageBorder simpleBorder(String... lines) {
+ return new SimplePageBorder(lines);
+ }
+
+ public static IPageBorder disappearingBorder(int pageNum, String... lines) {
+ return disappearingBorder(pageNum, 0, lines);
+ }
+
+ public static IPageBorder disappearingBorder(int pageNum, int keptLines, String... lines) {
+ return new DisappearingPageBorder(pageNum, keptLines, lines);
+ }
+
+ static class SimplePageBorder extends SimpleHelpComponent implements IPageBorder {
+ private final String replacedSequence;
+
+ public SimplePageBorder(String replacedSequence, String... lines) {
+ super(lines);
+ this.replacedSequence = replacedSequence;
+ }
+
+ public SimplePageBorder(String... lines) {
+ super(lines);
+ this.replacedSequence = "%pageCount%";
+ }
+
+ @Override
+ public void setPageCount(int pageCount) {
+ String[] lines = this.lines;
+ for (int i = 0; i < lines.length; i++) {
+ lines[i] = lines[i].replace(replacedSequence, Integer.toString(pageCount));
+ }
+ }
+
+ }
+
+ static class DisappearingPageBorder extends SimpleHelpComponent implements IPageBorder {
+ private final int pageNum;
+ private final int keptLines;
+
+ public DisappearingPageBorder(int pageNum, int keptLines, String... lines) {
+ super(lines);
+ this.pageNum = pageNum;
+ this.keptLines = keptLines;
+ }
+
+ @Override
+ public void setPageCount(int pageCount) {
+ if (pageCount == pageNum) {
+ String[] lines = this.lines;
+ this.lines = Arrays.copyOfRange(lines, Math.max(0, lines.length - keptLines), lines.length);
+ }
+ }
+
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/SimpleHelpComponent.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/SimpleHelpComponent.java
index 22707fd..1b74d0f 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/SimpleHelpComponent.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/SimpleHelpComponent.java
@@ -1,27 +1,27 @@
-package io.dico.dicore.command.chat.help;
-
-public class SimpleHelpComponent implements IHelpComponent {
- String[] lines;
-
- public SimpleHelpComponent(String... lines) {
- this.lines = lines;
- }
-
- @Override
- public int lineCount() {
- return lines.length;
- }
-
- @Override
- public void appendTo(StringBuilder sb) {
- String[] lines = this.lines;
- int len = lines.length;
- if (0 < len) {
- sb.append(lines[0]);
- }
- for (int i = 1; i < len; i++) {
- sb.append('\n').append(lines[i]);
- }
- }
-
-}
+package io.dico.dicore.command.chat.help;
+
+public class SimpleHelpComponent implements IHelpComponent {
+ String[] lines;
+
+ public SimpleHelpComponent(String... lines) {
+ this.lines = lines;
+ }
+
+ @Override
+ public int lineCount() {
+ return lines.length;
+ }
+
+ @Override
+ public void appendTo(StringBuilder sb) {
+ String[] lines = this.lines;
+ int len = lines.length;
+ if (0 < len) {
+ sb.append(lines[0]);
+ }
+ for (int i = 1; i < len; i++) {
+ sb.append('\n').append(lines[i]);
+ }
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
index a584e7e..e06730f 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageBuilder.java
@@ -1,115 +1,115 @@
-package io.dico.dicore.command.chat.help.defaults;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.*;
-import org.bukkit.permissions.Permissible;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-
-public class DefaultPageBuilder implements IPageBuilder {
-
- @Override
- public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target,
- Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
- if (pageLen <= 0 || pageNum < 0) {
- throw new IllegalArgumentException();
- }
-
- List<IHelpComponent> components = new LinkedList<>();
- for (IHelpTopic topic : helpTopics) {
- components.addAll(topic.getComponents(target, viewer, context, true));
- }
-
- PageBorders pageBorders = null;
- int componentStartIdx = -1;
- int componentEndIdx = -1;
- int totalPageCount = 0;
- int curPageLines = 0;
-
- ListIterator<IHelpComponent> iterator = components.listIterator();
-
- while (iterator.hasNext()) {
- if (curPageLines == 0) {
-
- if (pageBorders != null) {
- iterator.add(pageBorders.getFooter());
- }
-
- if (pageNum == totalPageCount) {
- componentStartIdx = iterator.nextIndex();
- } else if (pageNum + 1 == totalPageCount) {
- componentEndIdx = iterator.nextIndex();
- }
-
- pageBorders = pageLayout.getPageBorders(target, viewer, context, totalPageCount + 1);
-
- if (pageBorders != null) {
- iterator.add(pageBorders.getHeader());
- iterator.previous();
-
- curPageLines += pageBorders.getFooter().lineCount();
- }
-
- totalPageCount++;
- }
-
- IHelpComponent component = iterator.next();
- int lineCount = component.lineCount();
- curPageLines += lineCount;
-
- if (curPageLines >= pageLen) {
- curPageLines = 0;
- }
- }
-
- if (componentStartIdx == -1) {
- // page does not exist
- return "";
- }
-
- if (componentEndIdx == -1) {
- componentEndIdx = components.size();
- }
-
- StringBuilder sb = new StringBuilder();
- iterator = components.listIterator(componentStartIdx);
- int count = componentEndIdx - componentStartIdx;
- boolean first = true;
-
- while (count-- > 0) {
- IHelpComponent component = iterator.next();
- if (component instanceof IPageBorder) {
- ((IPageBorder) component).setPageCount(totalPageCount);
- }
- if (first) {
- first = false;
- } else {
- sb.append('\n');
- }
- component.appendTo(sb);
-
- }
-
- return sb.toString();
- }
-
- public static String combine(List<IHelpComponent> components) {
- StringBuilder rv = new StringBuilder();
-
- Iterator<IHelpComponent> iterator = components.iterator();
- if (iterator.hasNext()) {
- iterator.next().appendTo(rv);
- }
- while (iterator.hasNext()) {
- rv.append('\n');
- iterator.next().appendTo(rv);
- }
-
- return rv.toString();
- }
-
-}
+package io.dico.dicore.command.chat.help.defaults;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.*;
+import org.bukkit.permissions.Permissible;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+public class DefaultPageBuilder implements IPageBuilder {
+
+ @Override
+ public String getPage(List<IHelpTopic> helpTopics, IPageLayout pageLayout, ICommandAddress target,
+ Permissible viewer, ExecutionContext context, int pageNum, int pageLen) {
+ if (pageLen <= 0 || pageNum < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ List<IHelpComponent> components = new LinkedList<>();
+ for (IHelpTopic topic : helpTopics) {
+ components.addAll(topic.getComponents(target, viewer, context, true));
+ }
+
+ PageBorders pageBorders = null;
+ int componentStartIdx = -1;
+ int componentEndIdx = -1;
+ int totalPageCount = 0;
+ int curPageLines = 0;
+
+ ListIterator<IHelpComponent> iterator = components.listIterator();
+
+ while (iterator.hasNext()) {
+ if (curPageLines == 0) {
+
+ if (pageBorders != null) {
+ iterator.add(pageBorders.getFooter());
+ }
+
+ if (pageNum == totalPageCount) {
+ componentStartIdx = iterator.nextIndex();
+ } else if (pageNum + 1 == totalPageCount) {
+ componentEndIdx = iterator.nextIndex();
+ }
+
+ pageBorders = pageLayout.getPageBorders(target, viewer, context, totalPageCount + 1);
+
+ if (pageBorders != null) {
+ iterator.add(pageBorders.getHeader());
+ iterator.previous();
+
+ curPageLines += pageBorders.getFooter().lineCount();
+ }
+
+ totalPageCount++;
+ }
+
+ IHelpComponent component = iterator.next();
+ int lineCount = component.lineCount();
+ curPageLines += lineCount;
+
+ if (curPageLines >= pageLen) {
+ curPageLines = 0;
+ }
+ }
+
+ if (componentStartIdx == -1) {
+ // page does not exist
+ return "";
+ }
+
+ if (componentEndIdx == -1) {
+ componentEndIdx = components.size();
+ }
+
+ StringBuilder sb = new StringBuilder();
+ iterator = components.listIterator(componentStartIdx);
+ int count = componentEndIdx - componentStartIdx;
+ boolean first = true;
+
+ while (count-- > 0) {
+ IHelpComponent component = iterator.next();
+ if (component instanceof IPageBorder) {
+ ((IPageBorder) component).setPageCount(totalPageCount);
+ }
+ if (first) {
+ first = false;
+ } else {
+ sb.append('\n');
+ }
+ component.appendTo(sb);
+
+ }
+
+ return sb.toString();
+ }
+
+ public static String combine(List<IHelpComponent> components) {
+ StringBuilder rv = new StringBuilder();
+
+ Iterator<IHelpComponent> iterator = components.iterator();
+ if (iterator.hasNext()) {
+ iterator.next().appendTo(rv);
+ }
+ while (iterator.hasNext()) {
+ rv.append('\n');
+ iterator.next().appendTo(rv);
+ }
+
+ return rv.toString();
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageLayout.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageLayout.java
index 8d3d004..d950b09 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageLayout.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DefaultPageLayout.java
@@ -1,40 +1,40 @@
-package io.dico.dicore.command.chat.help.defaults;
-
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.ModifiableCommandAddress;
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.chat.IChatHandler;
-import io.dico.dicore.command.chat.help.IPageBorder;
-import io.dico.dicore.command.chat.help.IPageLayout;
-import io.dico.dicore.command.chat.help.PageBorders;
-import org.bukkit.permissions.Permissible;
-
-public class DefaultPageLayout implements IPageLayout {
-
- @Override
- public PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum) {
- IChatHandler c = context.getAddress().getChatHandler();
- String prefix = c.getMessagePrefixForType(EMessageType.INFORMATIVE);
- Formatting informative = c.getChatFormatForType(EMessageType.INFORMATIVE);
- Formatting number = c.getChatFormatForType(EMessageType.NEUTRAL);
-
- String nextPageCommand;
- ICommandAddress executor = context.getAddress();
- if (((ModifiableCommandAddress) executor).hasHelpCommand()) {
- nextPageCommand = ((ModifiableCommandAddress) executor).getHelpCommand().getAddress() + ' ' + (pageNum + 1);
- } else {
- nextPageCommand = executor.getAddress() + ' ' + (pageNum + 1);
- }
-
- String header = prefix + informative + "Help page " + number + pageNum + informative +
- '/' + number + "%pageCount%" + informative + " for /" + target.getAddress();
- String footer = informative + "Type /" + nextPageCommand + " for the next page";
-
- IPageBorder headerBorder = PageBorders.simpleBorder("", header);
- IPageBorder footerBorder = PageBorders.disappearingBorder(pageNum, footer);
- return new PageBorders(headerBorder, footerBorder);
- }
-
-}
+package io.dico.dicore.command.chat.help.defaults;
+
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.ModifiableCommandAddress;
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.chat.IChatHandler;
+import io.dico.dicore.command.chat.help.IPageBorder;
+import io.dico.dicore.command.chat.help.IPageLayout;
+import io.dico.dicore.command.chat.help.PageBorders;
+import org.bukkit.permissions.Permissible;
+
+public class DefaultPageLayout implements IPageLayout {
+
+ @Override
+ public PageBorders getPageBorders(ICommandAddress target, Permissible viewer, ExecutionContext context, int pageNum) {
+ IChatHandler c = context.getAddress().getChatHandler();
+ String prefix = c.getMessagePrefixForType(EMessageType.INFORMATIVE);
+ Formatting informative = c.getChatFormatForType(EMessageType.INFORMATIVE);
+ Formatting number = c.getChatFormatForType(EMessageType.NEUTRAL);
+
+ String nextPageCommand;
+ ICommandAddress executor = context.getAddress();
+ if (((ModifiableCommandAddress) executor).hasHelpCommand()) {
+ nextPageCommand = ((ModifiableCommandAddress) executor).getHelpCommand().getAddress() + ' ' + (pageNum + 1);
+ } else {
+ nextPageCommand = executor.getAddress() + ' ' + (pageNum + 1);
+ }
+
+ String header = prefix + informative + "Help page " + number + pageNum + informative +
+ '/' + number + "%pageCount%" + informative + " for /" + target.getAddress();
+ String footer = informative + "Type /" + nextPageCommand + " for the next page";
+
+ IPageBorder headerBorder = PageBorders.simpleBorder("", header);
+ IPageBorder footerBorder = PageBorders.disappearingBorder(pageNum, footer);
+ return new PageBorders(headerBorder, footerBorder);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java
index ae88ea2..0899db4 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/DescriptionHelpTopic.java
@@ -1,45 +1,45 @@
-package io.dico.dicore.command.chat.help.defaults;
-
-import io.dico.dicore.command.Command;
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import io.dico.dicore.command.chat.help.IHelpTopic;
-import io.dico.dicore.command.chat.help.SimpleHelpComponent;
-import org.bukkit.permissions.Permissible;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class DescriptionHelpTopic implements IHelpTopic {
-
- @Override
- public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
- List<IHelpComponent> out = new ArrayList<>();
- Formatting format = context.getFormat(EMessageType.DESCRIPTION);
-
- if (!target.hasCommand()) {
- return out;
- }
- Command command = target.getCommand();
- String[] description = command.getDescription();
- if (description.length == 0) {
- String shortDescription = command.getShortDescription();
- if (shortDescription == null) {
- return out;
- }
-
- description = new String[]{shortDescription};
- }
-
- for (int i = 0; i < description.length; i++) {
- description[i] = format + description[i];
- }
-
- out.add(new SimpleHelpComponent(description));
- return out;
- }
-
-}
+package io.dico.dicore.command.chat.help.defaults;
+
+import io.dico.dicore.command.Command;
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import io.dico.dicore.command.chat.help.IHelpTopic;
+import io.dico.dicore.command.chat.help.SimpleHelpComponent;
+import org.bukkit.permissions.Permissible;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class DescriptionHelpTopic implements IHelpTopic {
+
+ @Override
+ public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
+ List<IHelpComponent> out = new ArrayList<>();
+ Formatting format = context.getFormat(EMessageType.DESCRIPTION);
+
+ if (!target.hasCommand()) {
+ return out;
+ }
+ Command command = target.getCommand();
+ String[] description = command.getDescription();
+ if (description.length == 0) {
+ String shortDescription = command.getShortDescription();
+ if (shortDescription == null) {
+ return out;
+ }
+
+ description = new String[]{shortDescription};
+ }
+
+ for (int i = 0; i < description.length; i++) {
+ description[i] = format + description[i];
+ }
+
+ out.add(new SimpleHelpComponent(description));
+ return out;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java
index 0e680ae..b302769 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SubcommandsHelpTopic.java
@@ -1,59 +1,59 @@
-package io.dico.dicore.command.chat.help.defaults;
-
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import io.dico.dicore.command.chat.help.IHelpTopic;
-import io.dico.dicore.command.chat.help.SimpleHelpComponent;
-import org.bukkit.command.CommandSender;
-import org.bukkit.permissions.Permissible;
-
-import java.util.*;
-
-public class SubcommandsHelpTopic implements IHelpTopic {
-
- @Override
- public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
- Collection<String> mainKeys = target.getChildrenMainKeys();
- if (mainKeys.isEmpty()) {
- return Collections.emptyList();
- }
-
- List<IHelpComponent> result = new ArrayList<>();
-
- mainKeys = new ArrayList<>(target.getChildrenMainKeys());
- ((ArrayList<String>) mainKeys).sort(null);
-
- CommandSender sender = viewer instanceof CommandSender ? (CommandSender) viewer : context.getSender();
- for (String key : mainKeys) {
- ICommandAddress child = target.getChild(key);
- if ((child.hasChildren() || child.hasUserDeclaredCommand()) && child.getCommand().isVisibleTo(sender)) {
- result.add(getComponent(child, viewer, context));
- }
- }
-
- return result;
- }
-
- public IHelpComponent getComponent(ICommandAddress child, Permissible viewer, ExecutionContext context) {
- Formatting subcommand = colorOf(context, EMessageType.SUBCOMMAND);
- Formatting highlight = colorOf(context, EMessageType.HIGHLIGHT);
-
- String address = subcommand + "/" + child.getParent().getAddress() + ' ' + highlight + child.getMainKey();
-
- String description = child.hasCommand() ? child.getCommand().getShortDescription() : null;
- if (description != null) {
- Formatting descriptionFormat = colorOf(context, EMessageType.DESCRIPTION);
- return new SimpleHelpComponent(address, descriptionFormat + description);
- }
-
- return new SimpleHelpComponent(address);
- }
-
- private static Formatting colorOf(ExecutionContext context, EMessageType type) {
- return context.getAddress().getChatHandler().getChatFormatForType(type);
- }
-
-}
+package io.dico.dicore.command.chat.help.defaults;
+
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import io.dico.dicore.command.chat.help.IHelpTopic;
+import io.dico.dicore.command.chat.help.SimpleHelpComponent;
+import org.bukkit.command.CommandSender;
+import org.bukkit.permissions.Permissible;
+
+import java.util.*;
+
+public class SubcommandsHelpTopic implements IHelpTopic {
+
+ @Override
+ public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
+ Collection<String> mainKeys = target.getChildrenMainKeys();
+ if (mainKeys.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ List<IHelpComponent> result = new ArrayList<>();
+
+ mainKeys = new ArrayList<>(target.getChildrenMainKeys());
+ ((ArrayList<String>) mainKeys).sort(null);
+
+ CommandSender sender = viewer instanceof CommandSender ? (CommandSender) viewer : context.getSender();
+ for (String key : mainKeys) {
+ ICommandAddress child = target.getChild(key);
+ if ((child.hasChildren() || child.hasUserDeclaredCommand()) && child.getCommand().isVisibleTo(sender)) {
+ result.add(getComponent(child, viewer, context));
+ }
+ }
+
+ return result;
+ }
+
+ public IHelpComponent getComponent(ICommandAddress child, Permissible viewer, ExecutionContext context) {
+ Formatting subcommand = colorOf(context, EMessageType.SUBCOMMAND);
+ Formatting highlight = colorOf(context, EMessageType.HIGHLIGHT);
+
+ String address = subcommand + "/" + child.getParent().getAddress() + ' ' + highlight + child.getMainKey();
+
+ String description = child.hasCommand() ? child.getCommand().getShortDescription() : null;
+ if (description != null) {
+ Formatting descriptionFormat = colorOf(context, EMessageType.DESCRIPTION);
+ return new SimpleHelpComponent(address, descriptionFormat + description);
+ }
+
+ return new SimpleHelpComponent(address);
+ }
+
+ private static Formatting colorOf(ExecutionContext context, EMessageType type) {
+ return context.getAddress().getChatHandler().getChatFormatForType(type);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java
index d0e3ebe..f0f820f 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/defaults/SyntaxHelpTopic.java
@@ -1,92 +1,92 @@
-package io.dico.dicore.command.chat.help.defaults;
-
-import io.dico.dicore.command.Command;
-import io.dico.dicore.command.EMessageType;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.Formatting;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import io.dico.dicore.command.chat.help.IHelpTopic;
-import io.dico.dicore.command.chat.help.SimpleHelpComponent;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.ParameterList;
-import org.bukkit.permissions.Permissible;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-public class SyntaxHelpTopic implements IHelpTopic {
-
- @Override
- public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
- if (!target.hasCommand()) {
- return Collections.emptyList();
- }
-
- if (target.hasChildren()) {
- if (!isForPage) {
- // HelpPages will send help instead of syntax, which might in turn include syntax as well.
- return Collections.emptyList();
- }
-
- if (!target.hasUserDeclaredCommand() && !target.getCommand().getParameterList().hasAnyParameters()) {
- // no point adding syntax at all
- return Collections.emptyList();
- }
- }
-
- StringBuilder line = new StringBuilder();
- if (isForPage)
- line.append(context.getFormat(EMessageType.SYNTAX))
- .append("Syntax: ");
-
- line.append('/')
- .append(context.getFormat(EMessageType.INSTRUCTION))
- .append(target.getAddress())
- .append(' ');
-
- addShortSyntax(line, target, context);
-
- return Collections.singletonList(new SimpleHelpComponent(line.toString()));
- }
-
- private static void addShortSyntax(StringBuilder builder, ICommandAddress address, ExecutionContext ctx) {
- if (address.hasCommand()) {
- Formatting syntaxColor = ctx.getFormat(EMessageType.SYNTAX);
- Formatting highlight = ctx.getFormat(EMessageType.HIGHLIGHT);
- builder.append(syntaxColor);
-
- Command command = address.getCommand();
- ParameterList list = command.getParameterList();
- Parameter<?, ?> repeated = list.getRepeatedParameter();
-
- int requiredCount = list.getRequiredCount();
- List<Parameter<?, ?>> indexedParameters = list.getIndexedParameters();
- for (int i = 0, n = indexedParameters.size(); i < n; i++) {
- builder.append(i < requiredCount ? " <" : " [");
- Parameter<?, ?> param = indexedParameters.get(i);
- builder.append(param.getName());
- if (param == repeated) {
- builder.append(highlight).append("...").append(syntaxColor);
- }
- builder.append(i < requiredCount ? '>' : ']');
- }
-
- Map<String, Parameter<?, ?>> parametersByName = list.getParametersByName();
- for (Parameter<?, ?> param : parametersByName.values()) {
- if (param.isFlag()) {
- builder.append(" [").append(param.getName());
- if (param.expectsInput()) {
- builder.append(" <").append(param.getName()).append(">");
- }
- builder.append(']');
- }
- }
-
- } else {
- builder.append(' ');
- }
- }
-
-}
+package io.dico.dicore.command.chat.help.defaults;
+
+import io.dico.dicore.command.Command;
+import io.dico.dicore.command.EMessageType;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.Formatting;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import io.dico.dicore.command.chat.help.IHelpTopic;
+import io.dico.dicore.command.chat.help.SimpleHelpComponent;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.ParameterList;
+import org.bukkit.permissions.Permissible;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class SyntaxHelpTopic implements IHelpTopic {
+
+ @Override
+ public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
+ if (!target.hasCommand()) {
+ return Collections.emptyList();
+ }
+
+ if (target.hasChildren()) {
+ if (!isForPage) {
+ // HelpPages will send help instead of syntax, which might in turn include syntax as well.
+ return Collections.emptyList();
+ }
+
+ if (!target.hasUserDeclaredCommand() && !target.getCommand().getParameterList().hasAnyParameters()) {
+ // no point adding syntax at all
+ return Collections.emptyList();
+ }
+ }
+
+ StringBuilder line = new StringBuilder();
+ if (isForPage)
+ line.append(context.getFormat(EMessageType.SYNTAX))
+ .append("Syntax: ");
+
+ line.append('/')
+ .append(context.getFormat(EMessageType.INSTRUCTION))
+ .append(target.getAddress())
+ .append(' ');
+
+ addShortSyntax(line, target, context);
+
+ return Collections.singletonList(new SimpleHelpComponent(line.toString()));
+ }
+
+ private static void addShortSyntax(StringBuilder builder, ICommandAddress address, ExecutionContext ctx) {
+ if (address.hasCommand()) {
+ Formatting syntaxColor = ctx.getFormat(EMessageType.SYNTAX);
+ Formatting highlight = ctx.getFormat(EMessageType.HIGHLIGHT);
+ builder.append(syntaxColor);
+
+ Command command = address.getCommand();
+ ParameterList list = command.getParameterList();
+ Parameter<?, ?> repeated = list.getRepeatedParameter();
+
+ int requiredCount = list.getRequiredCount();
+ List<Parameter<?, ?>> indexedParameters = list.getIndexedParameters();
+ for (int i = 0, n = indexedParameters.size(); i < n; i++) {
+ builder.append(i < requiredCount ? " <" : " [");
+ Parameter<?, ?> param = indexedParameters.get(i);
+ builder.append(param.getName());
+ if (param == repeated) {
+ builder.append(highlight).append("...").append(syntaxColor);
+ }
+ builder.append(i < requiredCount ? '>' : ']');
+ }
+
+ Map<String, Parameter<?, ?>> parametersByName = list.getParametersByName();
+ for (Parameter<?, ?> param : parametersByName.values()) {
+ if (param.isFlag()) {
+ builder.append(" [").append(param.getName());
+ if (param.expectsInput()) {
+ builder.append(" <").append(param.getName()).append(">");
+ }
+ builder.append(']');
+ }
+ }
+
+ } else {
+ builder.append(' ');
+ }
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/EInsertionStage.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/EInsertionStage.java
index 4f0026d..eb3605d 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/EInsertionStage.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/EInsertionStage.java
@@ -1,29 +1,29 @@
-package io.dico.dicore.command.chat.help.insertion;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-
-public enum EInsertionStage implements IInsertionFunction {
- START {
- @Override
- public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- return 0;
- }
- },
- CENTER {
- @Override
- public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- return current.size() / 2;
- }
- },
- END {
- @Override
- public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- return current.size();
- }
- }
-}
+package io.dico.dicore.command.chat.help.insertion;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+
+public enum EInsertionStage implements IInsertionFunction {
+ START {
+ @Override
+ public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
+ return 0;
+ }
+ },
+ CENTER {
+ @Override
+ public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
+ return current.size() / 2;
+ }
+ },
+ END {
+ @Override
+ public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
+ return current.size();
+ }
+ }
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
index f153165..75b52d0 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/HelpComponentInserter.java
@@ -1,43 +1,43 @@
-package io.dico.dicore.command.chat.help.insertion;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.HelpTopicModifier;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import io.dico.dicore.command.chat.help.IHelpTopic;
-import org.bukkit.permissions.Permissible;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class HelpComponentInserter extends HelpTopicModifier {
- private List<IInsertion> insertions = new ArrayList<>();
-
- public HelpComponentInserter(IHelpTopic delegate) {
- super(delegate);
- }
-
- @Override
- protected List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- // int componentCount = components.size();
-
- for (int i = insertions.size() - 1; i >= 0; i--) {
- IInsertion insertion = insertions.get(i);
- int idx = insertion.insertionIndex(components, target, viewer, context);
- List<IHelpComponent> inserted = insertion.getComponents(target, viewer, context, true);
- components.addAll(idx, inserted);
- }
-
- return components;
- }
-
- public HelpComponentInserter insert(IInsertionFunction insertionFunction, IHelpTopic helpTopic) {
- return insert(Insertions.combine(helpTopic, insertionFunction));
- }
-
- public HelpComponentInserter insert(IInsertion insertion) {
- insertions.add(insertion);
- return this;
- }
-
-}
+package io.dico.dicore.command.chat.help.insertion;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.HelpTopicModifier;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import io.dico.dicore.command.chat.help.IHelpTopic;
+import org.bukkit.permissions.Permissible;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class HelpComponentInserter extends HelpTopicModifier {
+ private List<IInsertion> insertions = new ArrayList<>();
+
+ public HelpComponentInserter(IHelpTopic delegate) {
+ super(delegate);
+ }
+
+ @Override
+ protected List<IHelpComponent> modify(List<IHelpComponent> components, ICommandAddress target, Permissible viewer, ExecutionContext context) {
+ // int componentCount = components.size();
+
+ for (int i = insertions.size() - 1; i >= 0; i--) {
+ IInsertion insertion = insertions.get(i);
+ int idx = insertion.insertionIndex(components, target, viewer, context);
+ List<IHelpComponent> inserted = insertion.getComponents(target, viewer, context, true);
+ components.addAll(idx, inserted);
+ }
+
+ return components;
+ }
+
+ public HelpComponentInserter insert(IInsertionFunction insertionFunction, IHelpTopic helpTopic) {
+ return insert(Insertions.combine(helpTopic, insertionFunction));
+ }
+
+ public HelpComponentInserter insert(IInsertion insertion) {
+ insertions.add(insertion);
+ return this;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertion.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertion.java
index 757cb91..92309d3 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertion.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertion.java
@@ -1,7 +1,7 @@
-package io.dico.dicore.command.chat.help.insertion;
-
-import io.dico.dicore.command.chat.help.IHelpTopic;
-
-interface IInsertion extends IHelpTopic, IInsertionFunction {
-
-}
+package io.dico.dicore.command.chat.help.insertion;
+
+import io.dico.dicore.command.chat.help.IHelpTopic;
+
+interface IInsertion extends IHelpTopic, IInsertionFunction {
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertionFunction.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertionFunction.java
index e99c246..356d002 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertionFunction.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/IInsertionFunction.java
@@ -1,14 +1,14 @@
-package io.dico.dicore.command.chat.help.insertion;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-
-public interface IInsertionFunction {
-
- int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context);
-
-}
+package io.dico.dicore.command.chat.help.insertion;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+
+public interface IInsertionFunction {
+
+ int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java
index 39b2784..220f05b 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/chat/help/insertion/Insertions.java
@@ -1,31 +1,31 @@
-package io.dico.dicore.command.chat.help.insertion;
-
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.chat.help.IHelpComponent;
-import io.dico.dicore.command.chat.help.IHelpTopic;
-import org.bukkit.permissions.Permissible;
-
-import java.util.List;
-
-public class Insertions {
-
- private Insertions() {
-
- }
-
- public static IInsertion combine(IHelpTopic topic, IInsertionFunction function) {
- return new IInsertion() {
- @Override
- public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
- return topic.getComponents(target, viewer, context, true);
- }
-
- @Override
- public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
- return function.insertionIndex(current, target, viewer, context);
- }
- };
- }
-
-}
+package io.dico.dicore.command.chat.help.insertion;
+
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.chat.help.IHelpComponent;
+import io.dico.dicore.command.chat.help.IHelpTopic;
+import org.bukkit.permissions.Permissible;
+
+import java.util.List;
+
+public class Insertions {
+
+ private Insertions() {
+
+ }
+
+ public static IInsertion combine(IHelpTopic topic, IInsertionFunction function) {
+ return new IInsertion() {
+ @Override
+ public List<IHelpComponent> getComponents(ICommandAddress target, Permissible viewer, ExecutionContext context, boolean isForPage) {
+ return topic.getComponents(target, viewer, context, true);
+ }
+
+ @Override
+ public int insertionIndex(List<IHelpComponent> current, ICommandAddress target, Permissible viewer, ExecutionContext context) {
+ return function.insertionIndex(current, target, viewer, context);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
index aa69730..5646814 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentBuffer.java
@@ -1,295 +1,295 @@
-package io.dico.dicore.command.parameter;
-
-import io.dico.dicore.command.CommandException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * Buffer for the arguments.
- * Easy to traverse for the parser.
- */
-public class ArgumentBuffer extends AbstractList<String> implements Iterator<String>, RandomAccess {
- private String[] array;
- private int cursor = 0; // index of the next return value
- private transient ArgumentBuffer unaffectingCopy = null; // see #getUnaffectingCopy()
-
- public ArgumentBuffer(String label, String[] args) {
- this(combine(label, args));
- }
-
- private static String[] combine(String label, String[] args) {
- String[] result;
- //if (args.length > 0 && "".equals(args[args.length - 1])) {
- // // drop the last element of args if it is empty
- // result = args;
- //} else {
- result = new String[args.length + 1];
- //}
- System.arraycopy(args, 0, result, 1, result.length - 1);
- result[0] = Objects.requireNonNull(label);
- return result;
- }
-
- /**
- * Constructs a new ArgumentBuffer using the given array, without copying it first.
- * None of the array its elements should be empty.
- *
- * @param array the array
- * @throws NullPointerException if the array or any of its elements are null
- */
- public ArgumentBuffer(String[] array) {
- for (String elem : array) {
- if (elem == null) throw new NullPointerException("ArgumentBuffer array element");
- }
- this.array = array;
-
- }
-
- public int getCursor() {
- return cursor;
- }
-
- public @NotNull ArgumentBuffer setCursor(int cursor) {
- if (cursor <= 0) {
- cursor = 0;
- } else if (size() <= cursor) {
- cursor = size();
- }
- this.cursor = cursor;
- return this;
- }
-
- @Override
- public int size() {
- return array.length;
- }
-
- @Override
- public @NotNull String get(int index) {
- return array[index];
- }
-
- public int nextIndex() {
- return cursor;
- }
-
- public int previousIndex() {
- return cursor - 1;
- }
-
- public int remainingElements() {
- return size() - nextIndex() - 1;
- }
-
- @Override
- public boolean hasNext() {
- return nextIndex() < size();
- }
-
- public boolean hasPrevious() {
- return 0 <= previousIndex();
- }
-
- /**
- * Unlike conventional ListIterator implementations, this returns null if there is no next element
- *
- * @return the next value, or null
- */
- @Override
- public @Nullable String next() {
- return hasNext() ? get(cursor++) : null;
- }
-
- public @NotNull String requireNext(String parameterName) throws CommandException {
- String next = next();
- if (next == null) {
- throw CommandException.missingArgument(parameterName);
- }
- return next;
- }
-
- // useful for completion code
- public @NotNull String nextOrEmpty() {
- return hasNext() ? get(cursor++) : "";
- }
-
- /**
- * Unlike conventional ListIterator implementations, this returns null if there is no previous element
- *
- * @return the previous value, or null
- */
- public @Nullable String previous() {
- return hasPrevious() ? get(--cursor) : null;
- }
-
- public @Nullable String peekNext() {
- return hasNext() ? get(cursor) : null;
- }
-
- public @Nullable String peekPrevious() {
- return hasPrevious() ? get(cursor - 1) : null;
- }
-
- public @NotNull ArgumentBuffer advance() {
- return advance(1);
- }
-
- public @NotNull ArgumentBuffer advance(int amount) {
- cursor = Math.min(Math.max(0, cursor + amount), size());
- return this;
- }
-
- public @NotNull ArgumentBuffer rewind() {
- return rewind(1);
- }
-
- public @NotNull ArgumentBuffer rewind(int amount) {
- return advance(-amount);
- }
-
- @NotNull String[] getArray() {
- return array;
- }
-
- public @NotNull String[] getArrayFromCursor() {
- return getArrayFromIndex(cursor);
- }
-
- public @NotNull String[] getArrayFromIndex(int index) {
- return Arrays.copyOfRange(array, index, array.length);
- }
-
- public @NotNull String getRawInput() {
- return String.join(" ", array);
- }
-
- public @NotNull String[] toArray() {
- return array.clone();
- }
-
- @Override
- public @NotNull Iterator<String> iterator() {
- return this;
- }
-
- @Override
- public @NotNull ListIterator<String> listIterator() {
- return new ListIterator<String>() {
- @Override
- public boolean hasNext() {
- return ArgumentBuffer.this.hasNext();
- }
-
- @Override
- public String next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- return ArgumentBuffer.this.next();
- }
-
- @Override
- public boolean hasPrevious() {
- return ArgumentBuffer.this.hasPrevious();
- }
-
- @Override
- public String previous() {
- if (!hasPrevious()) {
- throw new NoSuchElementException();
- }
- return ArgumentBuffer.this.previous();
- }
-
- @Override
- public int nextIndex() {
- return ArgumentBuffer.this.nextIndex();
- }
-
- @Override
- public int previousIndex() {
- return ArgumentBuffer.this.previousIndex();
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void set(String s) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void add(String s) {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- public void dropTrailingEmptyElements() {
- int removeCount = 0;
- String[] array = this.array;
- for (int i = array.length - 1; i >= 0; i--) {
- if ("".equals(array[i])) {
- removeCount++;
- }
- }
-
- if (removeCount > 0) {
- String[] newArray = new String[array.length - removeCount];
- System.arraycopy(array, 0, newArray, 0, newArray.length);
- this.array = newArray;
-
- if (cursor > newArray.length) {
- cursor = newArray.length;
- }
- }
- }
-
- /**
- * Preprocess this argument buffer with the given preprocessor
- *
- * @param preProcessor preprocessor
- * @return a new ArgumentBuffer with processed contents. Might be this buffer if nothing changed.
- */
- public @NotNull ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
- return preProcessor.process(this, -1);
- }
-
- /**
- * Allows a piece of code to traverse this buffer without modifying its cursor.
- * After this method has been called for the first time on this instance, if this method
- * or the {@link #clone()} method are called, the operation carried out on the prior result has finished.
- * As such, the same instance might be returned again.
- *
- * @return A view of this buffer that doesn't affect this buffer's cursor.
- */
- public ArgumentBuffer getUnaffectingCopy() {
- // the copy doesn't alter the cursor of this ArgumentBuffer when moved, but traverses the same array reference.
- // there is only ever one copy of an ArgumentBuffer, the cursor of which is updated on every call to this method.
-
- ArgumentBuffer unaffectingCopy = this.unaffectingCopy;
- if (unaffectingCopy == null) {
- this.unaffectingCopy = unaffectingCopy = new ArgumentBuffer(array);
- }
- unaffectingCopy.cursor = this.cursor;
- return unaffectingCopy;
- }
-
- @SuppressWarnings("MethodDoesntCallSuperMethod")
- public @NotNull ArgumentBuffer clone() {
- ArgumentBuffer result = getUnaffectingCopy();
- this.unaffectingCopy = null;
- return result;
- }
-
- @Override
- public String toString() {
- return String.format("ArgumentBuffer(size = %d, cursor = %d)", size(), getCursor());
- }
-
-}
+package io.dico.dicore.command.parameter;
+
+import io.dico.dicore.command.CommandException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * Buffer for the arguments.
+ * Easy to traverse for the parser.
+ */
+public class ArgumentBuffer extends AbstractList<String> implements Iterator<String>, RandomAccess {
+ private String[] array;
+ private int cursor = 0; // index of the next return value
+ private transient ArgumentBuffer unaffectingCopy = null; // see #getUnaffectingCopy()
+
+ public ArgumentBuffer(String label, String[] args) {
+ this(combine(label, args));
+ }
+
+ private static String[] combine(String label, String[] args) {
+ String[] result;
+ //if (args.length > 0 && "".equals(args[args.length - 1])) {
+ // // drop the last element of args if it is empty
+ // result = args;
+ //} else {
+ result = new String[args.length + 1];
+ //}
+ System.arraycopy(args, 0, result, 1, result.length - 1);
+ result[0] = Objects.requireNonNull(label);
+ return result;
+ }
+
+ /**
+ * Constructs a new ArgumentBuffer using the given array, without copying it first.
+ * None of the array its elements should be empty.
+ *
+ * @param array the array
+ * @throws NullPointerException if the array or any of its elements are null
+ */
+ public ArgumentBuffer(String[] array) {
+ for (String elem : array) {
+ if (elem == null) throw new NullPointerException("ArgumentBuffer array element");
+ }
+ this.array = array;
+
+ }
+
+ public int getCursor() {
+ return cursor;
+ }
+
+ public @NotNull ArgumentBuffer setCursor(int cursor) {
+ if (cursor <= 0) {
+ cursor = 0;
+ } else if (size() <= cursor) {
+ cursor = size();
+ }
+ this.cursor = cursor;
+ return this;
+ }
+
+ @Override
+ public int size() {
+ return array.length;
+ }
+
+ @Override
+ public @NotNull String get(int index) {
+ return array[index];
+ }
+
+ public int nextIndex() {
+ return cursor;
+ }
+
+ public int previousIndex() {
+ return cursor - 1;
+ }
+
+ public int remainingElements() {
+ return size() - nextIndex() - 1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return nextIndex() < size();
+ }
+
+ public boolean hasPrevious() {
+ return 0 <= previousIndex();
+ }
+
+ /**
+ * Unlike conventional ListIterator implementations, this returns null if there is no next element
+ *
+ * @return the next value, or null
+ */
+ @Override
+ public @Nullable String next() {
+ return hasNext() ? get(cursor++) : null;
+ }
+
+ public @NotNull String requireNext(String parameterName) throws CommandException {
+ String next = next();
+ if (next == null) {
+ throw CommandException.missingArgument(parameterName);
+ }
+ return next;
+ }
+
+ // useful for completion code
+ public @NotNull String nextOrEmpty() {
+ return hasNext() ? get(cursor++) : "";
+ }
+
+ /**
+ * Unlike conventional ListIterator implementations, this returns null if there is no previous element
+ *
+ * @return the previous value, or null
+ */
+ public @Nullable String previous() {
+ return hasPrevious() ? get(--cursor) : null;
+ }
+
+ public @Nullable String peekNext() {
+ return hasNext() ? get(cursor) : null;
+ }
+
+ public @Nullable String peekPrevious() {
+ return hasPrevious() ? get(cursor - 1) : null;
+ }
+
+ public @NotNull ArgumentBuffer advance() {
+ return advance(1);
+ }
+
+ public @NotNull ArgumentBuffer advance(int amount) {
+ cursor = Math.min(Math.max(0, cursor + amount), size());
+ return this;
+ }
+
+ public @NotNull ArgumentBuffer rewind() {
+ return rewind(1);
+ }
+
+ public @NotNull ArgumentBuffer rewind(int amount) {
+ return advance(-amount);
+ }
+
+ @NotNull String[] getArray() {
+ return array;
+ }
+
+ public @NotNull String[] getArrayFromCursor() {
+ return getArrayFromIndex(cursor);
+ }
+
+ public @NotNull String[] getArrayFromIndex(int index) {
+ return Arrays.copyOfRange(array, index, array.length);
+ }
+
+ public @NotNull String getRawInput() {
+ return String.join(" ", array);
+ }
+
+ public @NotNull String[] toArray() {
+ return array.clone();
+ }
+
+ @Override
+ public @NotNull Iterator<String> iterator() {
+ return this;
+ }
+
+ @Override
+ public @NotNull ListIterator<String> listIterator() {
+ return new ListIterator<String>() {
+ @Override
+ public boolean hasNext() {
+ return ArgumentBuffer.this.hasNext();
+ }
+
+ @Override
+ public String next() {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+ return ArgumentBuffer.this.next();
+ }
+
+ @Override
+ public boolean hasPrevious() {
+ return ArgumentBuffer.this.hasPrevious();
+ }
+
+ @Override
+ public String previous() {
+ if (!hasPrevious()) {
+ throw new NoSuchElementException();
+ }
+ return ArgumentBuffer.this.previous();
+ }
+
+ @Override
+ public int nextIndex() {
+ return ArgumentBuffer.this.nextIndex();
+ }
+
+ @Override
+ public int previousIndex() {
+ return ArgumentBuffer.this.previousIndex();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void set(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void add(String s) {
+ throw new UnsupportedOperationException();
+ }
+ };
+ }
+
+ public void dropTrailingEmptyElements() {
+ int removeCount = 0;
+ String[] array = this.array;
+ for (int i = array.length - 1; i >= 0; i--) {
+ if ("".equals(array[i])) {
+ removeCount++;
+ }
+ }
+
+ if (removeCount > 0) {
+ String[] newArray = new String[array.length - removeCount];
+ System.arraycopy(array, 0, newArray, 0, newArray.length);
+ this.array = newArray;
+
+ if (cursor > newArray.length) {
+ cursor = newArray.length;
+ }
+ }
+ }
+
+ /**
+ * Preprocess this argument buffer with the given preprocessor
+ *
+ * @param preProcessor preprocessor
+ * @return a new ArgumentBuffer with processed contents. Might be this buffer if nothing changed.
+ */
+ public @NotNull ArgumentBuffer preprocessArguments(IArgumentPreProcessor preProcessor) {
+ return preProcessor.process(this, -1);
+ }
+
+ /**
+ * Allows a piece of code to traverse this buffer without modifying its cursor.
+ * After this method has been called for the first time on this instance, if this method
+ * or the {@link #clone()} method are called, the operation carried out on the prior result has finished.
+ * As such, the same instance might be returned again.
+ *
+ * @return A view of this buffer that doesn't affect this buffer's cursor.
+ */
+ public ArgumentBuffer getUnaffectingCopy() {
+ // the copy doesn't alter the cursor of this ArgumentBuffer when moved, but traverses the same array reference.
+ // there is only ever one copy of an ArgumentBuffer, the cursor of which is updated on every call to this method.
+
+ ArgumentBuffer unaffectingCopy = this.unaffectingCopy;
+ if (unaffectingCopy == null) {
+ this.unaffectingCopy = unaffectingCopy = new ArgumentBuffer(array);
+ }
+ unaffectingCopy.cursor = this.cursor;
+ return unaffectingCopy;
+ }
+
+ @SuppressWarnings("MethodDoesntCallSuperMethod")
+ public @NotNull ArgumentBuffer clone() {
+ ArgumentBuffer result = getUnaffectingCopy();
+ this.unaffectingCopy = null;
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("ArgumentBuffer(size = %d, cursor = %d)", size(), getCursor());
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
index ce818b7..a9ccd20 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ArgumentMergingPreProcessor.java
@@ -1,177 +1,177 @@
-package io.dico.dicore.command.parameter;
-
-public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
- private final String tokens;
- private final char escapeChar;
-
- public ArgumentMergingPreProcessor(String tokens, char escapeChar) {
- if ((tokens.length() & 1) != 0 || tokens.isEmpty()) throw new IllegalArgumentException();
- this.tokens = tokens;
- this.escapeChar = escapeChar;
- }
-
- @Override
- public ArgumentBuffer process(ArgumentBuffer buffer, int count) {
- Parser parser = new Parser(buffer.getArray().clone(), buffer.getCursor(), count);
- String[] array = parser.doProcess();
- ArgumentBuffer result = new ArgumentBuffer(array);
- parser.updateBuffer(result);
- return result;
- }
-
- private class Parser {
- private final String[] args;
- private final int start;
- private final int count;
-
- private int foundSectionCount;
- private int currentIndex;
- private int sectionStart;
- private char closingToken;
- private int sectionEnd;
- private int removeCount;
-
- Parser(String[] args, int start, int count) {
- this.start = start;
- this.args = args;
- this.count = count;
- }
-
- private void reset() {
- foundSectionCount = 0;
- currentIndex = start;
- sectionStart = -1;
- closingToken = 0;
- sectionEnd = -1;
- removeCount = 0;
- }
-
- private boolean findNextSectionStart() {
- if (count >= 0 && foundSectionCount >= count) return false;
-
- while (currentIndex < args.length) {
- String arg = args[currentIndex];
- if (arg == null) {
- throw new IllegalArgumentException();
- }
-
- if (arg.isEmpty()) {
- ++currentIndex;
- continue;
- }
-
- int openingTokenIndex = tokens.indexOf(arg.charAt(0));
- if (openingTokenIndex == -1 || (openingTokenIndex & 1) != 0) {
- ++currentIndex;
- continue;
- }
-
- // found
- closingToken = tokens.charAt(openingTokenIndex | 1);
- sectionStart = currentIndex;
- return true;
- }
-
- return false;
- }
-
- private boolean findNextSectionEnd() {
- while (currentIndex < args.length) {
- String arg = args[currentIndex];
- if (arg == null) {
- throw new IllegalArgumentException();
- }
-
- if (arg.isEmpty()
- || arg.charAt(arg.length() - 1) != closingToken
- || (sectionStart == currentIndex && arg.length() == 1)) {
- ++currentIndex;
- continue;
- }
-
- if (escapeChar != 0
- && arg.length() > 1
- && arg.charAt(arg.length() - 2) == escapeChar) {
- // escaped
- ++currentIndex;
- continue;
- }
-
- // found
- closingToken = 0;
- sectionEnd = currentIndex;
- ++currentIndex;
- return true;
- }
-
- return false;
- }
-
- private void processFoundSection() {
- if (sectionStart == sectionEnd) {
- String arg = args[sectionStart];
- args[sectionStart] = arg.substring(1, arg.length() - 1);
- return;
- }
-
- removeCount += sectionEnd - sectionStart;
-
- StringBuilder sb = new StringBuilder();
- sb.append(args[sectionStart].substring(1));
-
- for (int i = sectionStart + 1; i < sectionEnd; i++) {
- sb.append(' ');
- sb.append(args[i]);
- args[i] = null;
- }
- sb.append(' ');
- sb.append(args[sectionEnd].substring(0, args[sectionEnd].length() - 1));
- args[sectionEnd] = null;
-
- args[sectionStart] = sb.toString();
-
- sectionStart = -1;
- sectionEnd = -1;
-
- ++foundSectionCount;
- }
-
- String[] doProcess() {
- reset();
-
- while (findNextSectionStart()) {
- if (findNextSectionEnd()) {
- processFoundSection();
- } else {
- currentIndex = sectionStart + 1;
- }
- }
-
- if (removeCount == 0) {
- return args;
- }
-
- String[] result = new String[args.length - removeCount];
- int i = 0;
- for (String arg : args) {
- if (arg != null) {
- result[i++] = arg;
- }
- }
-
- return result;
- }
-
- void updateBuffer(ArgumentBuffer buffer) {
- if (count < 0) {
- buffer.setCursor(start);
- } else {
- buffer.setCursor(currentIndex);
- }
- }
-
- }
-
-}
-
-
+package io.dico.dicore.command.parameter;
+
+public class ArgumentMergingPreProcessor implements IArgumentPreProcessor {
+ private final String tokens;
+ private final char escapeChar;
+
+ public ArgumentMergingPreProcessor(String tokens, char escapeChar) {
+ if ((tokens.length() & 1) != 0 || tokens.isEmpty()) throw new IllegalArgumentException();
+ this.tokens = tokens;
+ this.escapeChar = escapeChar;
+ }
+
+ @Override
+ public ArgumentBuffer process(ArgumentBuffer buffer, int count) {
+ Parser parser = new Parser(buffer.getArray().clone(), buffer.getCursor(), count);
+ String[] array = parser.doProcess();
+ ArgumentBuffer result = new ArgumentBuffer(array);
+ parser.updateBuffer(result);
+ return result;
+ }
+
+ private class Parser {
+ private final String[] args;
+ private final int start;
+ private final int count;
+
+ private int foundSectionCount;
+ private int currentIndex;
+ private int sectionStart;
+ private char closingToken;
+ private int sectionEnd;
+ private int removeCount;
+
+ Parser(String[] args, int start, int count) {
+ this.start = start;
+ this.args = args;
+ this.count = count;
+ }
+
+ private void reset() {
+ foundSectionCount = 0;
+ currentIndex = start;
+ sectionStart = -1;
+ closingToken = 0;
+ sectionEnd = -1;
+ removeCount = 0;
+ }
+
+ private boolean findNextSectionStart() {
+ if (count >= 0 && foundSectionCount >= count) return false;
+
+ while (currentIndex < args.length) {
+ String arg = args[currentIndex];
+ if (arg == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (arg.isEmpty()) {
+ ++currentIndex;
+ continue;
+ }
+
+ int openingTokenIndex = tokens.indexOf(arg.charAt(0));
+ if (openingTokenIndex == -1 || (openingTokenIndex & 1) != 0) {
+ ++currentIndex;
+ continue;
+ }
+
+ // found
+ closingToken = tokens.charAt(openingTokenIndex | 1);
+ sectionStart = currentIndex;
+ return true;
+ }
+
+ return false;
+ }
+
+ private boolean findNextSectionEnd() {
+ while (currentIndex < args.length) {
+ String arg = args[currentIndex];
+ if (arg == null) {
+ throw new IllegalArgumentException();
+ }
+
+ if (arg.isEmpty()
+ || arg.charAt(arg.length() - 1) != closingToken
+ || (sectionStart == currentIndex && arg.length() == 1)) {
+ ++currentIndex;
+ continue;
+ }
+
+ if (escapeChar != 0
+ && arg.length() > 1
+ && arg.charAt(arg.length() - 2) == escapeChar) {
+ // escaped
+ ++currentIndex;
+ continue;
+ }
+
+ // found
+ closingToken = 0;
+ sectionEnd = currentIndex;
+ ++currentIndex;
+ return true;
+ }
+
+ return false;
+ }
+
+ private void processFoundSection() {
+ if (sectionStart == sectionEnd) {
+ String arg = args[sectionStart];
+ args[sectionStart] = arg.substring(1, arg.length() - 1);
+ return;
+ }
+
+ removeCount += sectionEnd - sectionStart;
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(args[sectionStart].substring(1));
+
+ for (int i = sectionStart + 1; i < sectionEnd; i++) {
+ sb.append(' ');
+ sb.append(args[i]);
+ args[i] = null;
+ }
+ sb.append(' ');
+ sb.append(args[sectionEnd].substring(0, args[sectionEnd].length() - 1));
+ args[sectionEnd] = null;
+
+ args[sectionStart] = sb.toString();
+
+ sectionStart = -1;
+ sectionEnd = -1;
+
+ ++foundSectionCount;
+ }
+
+ String[] doProcess() {
+ reset();
+
+ while (findNextSectionStart()) {
+ if (findNextSectionEnd()) {
+ processFoundSection();
+ } else {
+ currentIndex = sectionStart + 1;
+ }
+ }
+
+ if (removeCount == 0) {
+ return args;
+ }
+
+ String[] result = new String[args.length - removeCount];
+ int i = 0;
+ for (String arg : args) {
+ if (arg != null) {
+ result[i++] = arg;
+ }
+ }
+
+ return result;
+ }
+
+ void updateBuffer(ArgumentBuffer buffer) {
+ if (count < 0) {
+ buffer.setCursor(start);
+ } else {
+ buffer.setCursor(currentIndex);
+ }
+ }
+
+ }
+
+}
+
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
index a5afce5..7418c4a 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ContextParser.java
@@ -89,6 +89,8 @@ public class ContextParser {
m_curRepeatingList = null;
assignDefaultValuesToUncomputedParams();
arrayifyRepeatedParamValue();
+
+ m_done = true;
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
index 0b8198e..5495cce 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/IArgumentPreProcessor.java
@@ -1,41 +1,41 @@
-package io.dico.dicore.command.parameter;
-
-/**
- * An interface to process tokens such as quotes
- */
-@Deprecated
-public interface IArgumentPreProcessor {
-
- /**
- * Preprocess the arguments contained within the given ArgumentBuffer.
- * If no changes are made, this might return the same buffer.
- * Any arguments preceding {@code buffer.getCursor()} will not be affected.
- *
- * <p>
- * If {@code count} is non-negative, it declares a limit on the number of arguments after preprocessing.
- * In that case, the buffer's cursor is set to the index of the first argument following processed arguments.
- * </p>
- *
- * @param buffer the argument buffer
- * @param count the maximum number of (processed) arguments
- * @return the arguments after preprocessing
- */
- ArgumentBuffer process(ArgumentBuffer buffer, int count);
-
- IArgumentPreProcessor NONE = (buffer, count) -> buffer;
-
- /**
- * Get an IArgumentPreProcessor that merges arguments between any two tokens
- *
- * @param tokens The tokens that the merged arguments should be enclosed by, in subsequent pairs.
- * Example: []{}""
- * This would mean the following would be merged: [ hello this is a merged argument]
- * @param escapeChar the char that can be used to escape the given tokens
- * @return The IArgumentPreProcessor
- */
- static IArgumentPreProcessor mergeOnTokens(String tokens, char escapeChar) {
- return new ArgumentMergingPreProcessor(tokens, escapeChar);
- }
-
-}
-
+package io.dico.dicore.command.parameter;
+
+/**
+ * An interface to process tokens such as quotes
+ */
+@Deprecated
+public interface IArgumentPreProcessor {
+
+ /**
+ * Preprocess the arguments contained within the given ArgumentBuffer.
+ * If no changes are made, this might return the same buffer.
+ * Any arguments preceding {@code buffer.getCursor()} will not be affected.
+ *
+ * <p>
+ * If {@code count} is non-negative, it declares a limit on the number of arguments after preprocessing.
+ * In that case, the buffer's cursor is set to the index of the first argument following processed arguments.
+ * </p>
+ *
+ * @param buffer the argument buffer
+ * @param count the maximum number of (processed) arguments
+ * @return the arguments after preprocessing
+ */
+ ArgumentBuffer process(ArgumentBuffer buffer, int count);
+
+ IArgumentPreProcessor NONE = (buffer, count) -> buffer;
+
+ /**
+ * Get an IArgumentPreProcessor that merges arguments between any two tokens
+ *
+ * @param tokens The tokens that the merged arguments should be enclosed by, in subsequent pairs.
+ * Example: []{}""
+ * This would mean the following would be merged: [ hello this is a merged argument]
+ * @param escapeChar the char that can be used to escape the given tokens
+ * @return The IArgumentPreProcessor
+ */
+ static IArgumentPreProcessor mergeOnTokens(String tokens, char escapeChar) {
+ return new ArgumentMergingPreProcessor(tokens, escapeChar);
+ }
+
+}
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
index 613d057..f35628c 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/ParameterList.java
@@ -1,148 +1,148 @@
-package io.dico.dicore.command.parameter;
-
-import java.util.*;
-
-/**
- * IParameter definition for a command
- */
-@SuppressWarnings("UnusedReturnValue")
-public class ParameterList {
- //private ParameterList parent;
- private List<Parameter<?, ?>> indexedParameters;
- private Map<String, Parameter<?, ?>> byName;
- //private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
- private int requiredCount = -1;
- private boolean repeatFinalParameter;
-
- // if the final parameter is repeated and the command is implemented through reflection,
- // the repeated parameter is simply the last parameter of the method, rather than the last
- // indexed parameter. This might be a flag. As such, this field exists to ensure the correct
- // parameter is taken for repeating
- private boolean finalParameterMayBeFlag;
-
- /*
- public ParameterList(ParameterList parent) {
- this();
- if (parent.repeatFinalParameter) {
- throw new IllegalArgumentException("Parent may not have repeating parameters");
- }
- this.parent = parent;
- }*/
-
- public ParameterList() {
- this.indexedParameters = new ArrayList<>();
- this.byName = new LinkedHashMap<>();
- this.repeatFinalParameter = false;
- }
-
- /*
- public IArgumentPreProcessor getArgumentPreProcessor() {
- return argumentPreProcessor;
- }
-
- public ParameterList setArgumentPreProcessor(IArgumentPreProcessor argumentPreProcessor) {
- this.argumentPreProcessor = argumentPreProcessor == null ? IArgumentPreProcessor.NONE : argumentPreProcessor;
- return this;
- }*/
-
- public boolean repeatFinalParameter() {
- return repeatFinalParameter;
- }
-
- public ParameterList setRepeatFinalParameter(boolean repeatFinalParameter) {
- this.repeatFinalParameter = repeatFinalParameter;
- return this;
- }
-
- public boolean finalParameterMayBeFlag() {
- return finalParameterMayBeFlag;
- }
-
- public ParameterList setFinalParameterMayBeFlag(boolean finalParameterMayBeFlag) {
- this.finalParameterMayBeFlag = finalParameterMayBeFlag;
- return this;
- }
-
- public int getRequiredCount() {
- return requiredCount == -1 ? indexedParameters.size() : requiredCount;
- }
-
- public ParameterList setRequiredCount(int requiredCount) {
- this.requiredCount = requiredCount;
- return this;
- }
-
- public boolean hasAnyParameters() {
- return !byName.isEmpty();
- }
-
- public int getIndexedParameterCount() {
- return indexedParameters.size();
- }
-
- public List<Parameter<?, ?>> getIndexedParameters() {
- return Collections.unmodifiableList(indexedParameters);
- }
-
- public Parameter<?, ?> getParameterByName(String name) {
- return byName.get(name);
- }
-
- public String getIndexedParameterName(int index) {
- return indexedParameters.get(index).getName();
- }
-
- public Map<String, Parameter<?, ?>> getParametersByName() {
- return Collections.unmodifiableMap(byName);
- }
-
- /**
- * Add the given parameter to the end of this parameter list
- * Can be a flag
- *
- * @param parameter the parameter
- * @return this
- */
- public ParameterList addParameter(Parameter<?, ?> parameter) {
- return addParameter(-1, parameter);
- }
-
- /**
- * Add the given parameter to this parameter list
- * If the parameter is a flag, the index is ignored
- *
- * @param index parameter index number, -1 if end
- * @param parameter the parameter
- * @return this
- * @throws NullPointerException if parameter is null
- */
- public ParameterList addParameter(int index, Parameter<?, ?> parameter) {
- //System.out.println("Added parameter " + parameter.getName() + ", flag: " + parameter.isFlag());
- byName.put(parameter.getName(), parameter);
- if (!parameter.isFlag()) {
- indexedParameters.add(index == -1 ? indexedParameters.size() : index, parameter);
- }
- return this;
- }
-
- public Parameter<?, ?> getRepeatedParameter() {
- if (!repeatFinalParameter) {
- return null;
- }
- if (finalParameterMayBeFlag) {
- Iterator<Parameter<?, ?>> iterator = byName.values().iterator();
- Parameter<?, ?> result = null;
- while (iterator.hasNext()) {
- result = iterator.next();
- }
- return result;
- }
-
- if (indexedParameters.isEmpty()) {
- return null;
- }
-
- return indexedParameters.get(indexedParameters.size() - 1);
- }
-
-}
+package io.dico.dicore.command.parameter;
+
+import java.util.*;
+
+/**
+ * IParameter definition for a command
+ */
+@SuppressWarnings("UnusedReturnValue")
+public class ParameterList {
+ //private ParameterList parent;
+ private List<Parameter<?, ?>> indexedParameters;
+ private Map<String, Parameter<?, ?>> byName;
+ //private IArgumentPreProcessor argumentPreProcessor = IArgumentPreProcessor.NONE;
+ private int requiredCount = -1;
+ private boolean repeatFinalParameter;
+
+ // if the final parameter is repeated and the command is implemented through reflection,
+ // the repeated parameter is simply the last parameter of the method, rather than the last
+ // indexed parameter. This might be a flag. As such, this field exists to ensure the correct
+ // parameter is taken for repeating
+ private boolean finalParameterMayBeFlag;
+
+ /*
+ public ParameterList(ParameterList parent) {
+ this();
+ if (parent.repeatFinalParameter) {
+ throw new IllegalArgumentException("Parent may not have repeating parameters");
+ }
+ this.parent = parent;
+ }*/
+
+ public ParameterList() {
+ this.indexedParameters = new ArrayList<>();
+ this.byName = new LinkedHashMap<>();
+ this.repeatFinalParameter = false;
+ }
+
+ /*
+ public IArgumentPreProcessor getArgumentPreProcessor() {
+ return argumentPreProcessor;
+ }
+
+ public ParameterList setArgumentPreProcessor(IArgumentPreProcessor argumentPreProcessor) {
+ this.argumentPreProcessor = argumentPreProcessor == null ? IArgumentPreProcessor.NONE : argumentPreProcessor;
+ return this;
+ }*/
+
+ public boolean repeatFinalParameter() {
+ return repeatFinalParameter;
+ }
+
+ public ParameterList setRepeatFinalParameter(boolean repeatFinalParameter) {
+ this.repeatFinalParameter = repeatFinalParameter;
+ return this;
+ }
+
+ public boolean finalParameterMayBeFlag() {
+ return finalParameterMayBeFlag;
+ }
+
+ public ParameterList setFinalParameterMayBeFlag(boolean finalParameterMayBeFlag) {
+ this.finalParameterMayBeFlag = finalParameterMayBeFlag;
+ return this;
+ }
+
+ public int getRequiredCount() {
+ return requiredCount == -1 ? indexedParameters.size() : requiredCount;
+ }
+
+ public ParameterList setRequiredCount(int requiredCount) {
+ this.requiredCount = requiredCount;
+ return this;
+ }
+
+ public boolean hasAnyParameters() {
+ return !byName.isEmpty();
+ }
+
+ public int getIndexedParameterCount() {
+ return indexedParameters.size();
+ }
+
+ public List<Parameter<?, ?>> getIndexedParameters() {
+ return Collections.unmodifiableList(indexedParameters);
+ }
+
+ public Parameter<?, ?> getParameterByName(String name) {
+ return byName.get(name);
+ }
+
+ public String getIndexedParameterName(int index) {
+ return indexedParameters.get(index).getName();
+ }
+
+ public Map<String, Parameter<?, ?>> getParametersByName() {
+ return Collections.unmodifiableMap(byName);
+ }
+
+ /**
+ * Add the given parameter to the end of this parameter list
+ * Can be a flag
+ *
+ * @param parameter the parameter
+ * @return this
+ */
+ public ParameterList addParameter(Parameter<?, ?> parameter) {
+ return addParameter(-1, parameter);
+ }
+
+ /**
+ * Add the given parameter to this parameter list
+ * If the parameter is a flag, the index is ignored
+ *
+ * @param index parameter index number, -1 if end
+ * @param parameter the parameter
+ * @return this
+ * @throws NullPointerException if parameter is null
+ */
+ public ParameterList addParameter(int index, Parameter<?, ?> parameter) {
+ //System.out.println("Added parameter " + parameter.getName() + ", flag: " + parameter.isFlag());
+ byName.put(parameter.getName(), parameter);
+ if (!parameter.isFlag()) {
+ indexedParameters.add(index == -1 ? indexedParameters.size() : index, parameter);
+ }
+ return this;
+ }
+
+ public Parameter<?, ?> getRepeatedParameter() {
+ if (!repeatFinalParameter) {
+ return null;
+ }
+ if (finalParameterMayBeFlag) {
+ Iterator<Parameter<?, ?>> iterator = byName.values().iterator();
+ Parameter<?, ?> result = null;
+ while (iterator.hasNext()) {
+ result = iterator.next();
+ }
+ return result;
+ }
+
+ if (indexedParameters.isEmpty()) {
+ return null;
+ }
+
+ return indexedParameters.get(indexedParameters.size() - 1);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
index c23e09b..063d381 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/EnumParameterType.java
@@ -1,46 +1,46 @@
-package io.dico.dicore.command.parameter.type;
-
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.Parameter;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Void> {
- private final E[] universe;
-
- public EnumParameterType(Class<E> returnType) {
- super(returnType);
- universe = returnType.getEnumConstants();
- if (universe == null) {
- throw new IllegalArgumentException("returnType must be an enum");
- }
- }
-
- @Override
- protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
- for (E constant : universe) {
- if (constant.name().equalsIgnoreCase(input)) {
- return constant;
- }
- }
-
- throw CommandException.invalidArgument(parameter.getName(), "the enum value does not exist");
- }
-
- @Override
- public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
- String input = buffer.next().toUpperCase();
- List<String> result = new ArrayList<>();
- for (E constant : universe) {
- if (constant.name().toUpperCase().startsWith(input.toUpperCase())) {
- result.add(constant.name().toLowerCase());
- }
- }
- return result;
- }
-
-}
+package io.dico.dicore.command.parameter.type;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class EnumParameterType<E extends Enum> extends SimpleParameterType<E, Void> {
+ private final E[] universe;
+
+ public EnumParameterType(Class<E> returnType) {
+ super(returnType);
+ universe = returnType.getEnumConstants();
+ if (universe == null) {
+ throw new IllegalArgumentException("returnType must be an enum");
+ }
+ }
+
+ @Override
+ protected E parse(Parameter<E, Void> parameter, CommandSender sender, String input) throws CommandException {
+ for (E constant : universe) {
+ if (constant.name().equalsIgnoreCase(input)) {
+ return constant;
+ }
+ }
+
+ throw CommandException.invalidArgument(parameter.getName(), "the enum value does not exist");
+ }
+
+ @Override
+ public List<String> complete(Parameter<E, Void> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
+ String input = buffer.next().toUpperCase();
+ List<String> result = new ArrayList<>();
+ for (E constant : universe) {
+ if (constant.name().toUpperCase().startsWith(input.toUpperCase())) {
+ result.add(constant.name().toLowerCase());
+ }
+ }
+ return result;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/IParameterTypeSelector.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/IParameterTypeSelector.java
index 780ea0d..381b15c 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/IParameterTypeSelector.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/IParameterTypeSelector.java
@@ -1,44 +1,44 @@
-package io.dico.dicore.command.parameter.type;
-
-import java.lang.annotation.Annotation;
-
-/**
- * An interface for an object that stores parameter types by {@link ParameterKey} and finds appropriate types for {@link ParameterKey parameterKeys}
- */
-public interface IParameterTypeSelector {
-
- <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key);
-
- //<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(ParameterKey key);
-
- <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key);
-
-
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType) {
- return selectExact(returnType, null);
- }
-
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType, Class<? extends Annotation> annotationClass) {
- return selectExact(new ParameterKey(returnType, annotationClass));
- }
-
- /*
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType) {
- return selectExactOrSubclass(returnType, null);
- }
-
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType, Class<? extends Annotation> annotationClass) {
- return selectExactOrSubclass(new ParameterKey(returnType, annotationClass));
- }
- */
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType) {
- return selectAny(returnType, null);
- }
-
- default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType, Class<? extends Annotation> annotationClass) {
- return selectAny(new ParameterKey(returnType, annotationClass));
- }
-
- void addType(boolean infolessAlias, ParameterType<?, ?> type);
-
-}
+package io.dico.dicore.command.parameter.type;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * An interface for an object that stores parameter types by {@link ParameterKey} and finds appropriate types for {@link ParameterKey parameterKeys}
+ */
+public interface IParameterTypeSelector {
+
+ <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key);
+
+ //<TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(ParameterKey key);
+
+ <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key);
+
+
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType) {
+ return selectExact(returnType, null);
+ }
+
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(Class<?> returnType, Class<? extends Annotation> annotationClass) {
+ return selectExact(new ParameterKey(returnType, annotationClass));
+ }
+
+ /*
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType) {
+ return selectExactOrSubclass(returnType, null);
+ }
+
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExactOrSubclass(Class<?> returnType, Class<? extends Annotation> annotationClass) {
+ return selectExactOrSubclass(new ParameterKey(returnType, annotationClass));
+ }
+ */
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType) {
+ return selectAny(returnType, null);
+ }
+
+ default <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(Class<?> returnType, Class<? extends Annotation> annotationClass) {
+ return selectAny(new ParameterKey(returnType, annotationClass));
+ }
+
+ void addType(boolean infolessAlias, ParameterType<?, ?> type);
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/MapBasedParameterTypeSelector.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/MapBasedParameterTypeSelector.java
index d407f87..ef86eab 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/MapBasedParameterTypeSelector.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/MapBasedParameterTypeSelector.java
@@ -1,114 +1,114 @@
-package io.dico.dicore.command.parameter.type;
-
-import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Map based implementation of {@link IParameterTypeSelector}
- */
-public class MapBasedParameterTypeSelector implements IParameterTypeSelector {
- static final MapBasedParameterTypeSelector defaultSelector = new MapBasedParameterTypeSelector(false);
- private final Map<ParameterKey, ParameterType<?, ?>> parameterTypeMap;
- private final boolean useDefault;
-
- public MapBasedParameterTypeSelector(boolean useDefault) {
- this.parameterTypeMap = new HashMap<>();
- this.useDefault = useDefault;
- }
-
- @Override
- public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key) {
- ParameterType<?, ?> out = parameterTypeMap.get(key);
- if (useDefault && out == null) {
- out = defaultSelector.selectExact(key);
- }
- if (out == null && key.getReturnType().isEnum()) {
- //noinspection unchecked
- out = new EnumParameterType(key.getReturnType());
- addType(false, out);
- }
- return cast(out);
- }
-
- @Override
- public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key) {
- ParameterType<TReturn, TParamInfo> exact = selectExact(key);
- if (exact != null) {
- return exact;
- }
-
- if (key.getAnnotationClass() != null) {
- exact = selectExact(new ParameterKey(key.getReturnType()));
- if (exact != null) {
- return exact;
- }
- }
-
- Class<?> returnType = key.getReturnType();
- Class<? extends Annotation> annotationClass = key.getAnnotationClass();
-
- ParameterType<?, ?> out = selectByReturnType(parameterTypeMap, returnType, annotationClass, false);
- if (out == null && useDefault) {
- out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, false);
- }
- if (out == null) {
- out = selectByReturnType(parameterTypeMap, returnType, annotationClass, true);
- }
- if (out == null && useDefault) {
- out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, true);
- }
- return cast(out);
- }
-
- private static ParameterType<?, ?> selectByReturnType(Map<ParameterKey, ParameterType<?, ?>> map, Class<?> returnType,
- Class<? extends Annotation> annotationClass, boolean allowSubclass) {
- ParameterType<?, ?> out = null;
- if (allowSubclass) {
- for (ParameterType<?, ?> type : map.values()) {
- if (returnType.isAssignableFrom(type.getReturnType())) {
- if (annotationClass == type.getAnnotationClass()) {
- out = type;
- break;
- }
- if (out == null) {
- out = type;
- }
- }
- }
- } else {
- for (ParameterType<?, ?> type : map.values()) {
- if (returnType == type.getReturnType()) {
- if (annotationClass == type.getAnnotationClass()) {
- out = type;
- break;
- }
- if (out == null) {
- out = type;
- }
- }
- }
- }
- return out;
- }
-
- private static <T> T cast(Object o) {
- //noinspection unchecked
- return (T) o;
- }
-
- @Override
- public void addType(boolean infolessAlias, ParameterType<?, ?> type) {
- parameterTypeMap.put(type.getTypeKey(), type);
-
- if (infolessAlias) {
- parameterTypeMap.putIfAbsent(type.getInfolessTypeKey(), type);
- }
- }
-
- static {
- // registers default parameter types
- ParameterTypes.clinit();
- }
-
-}
+package io.dico.dicore.command.parameter.type;
+
+import java.lang.annotation.Annotation;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Map based implementation of {@link IParameterTypeSelector}
+ */
+public class MapBasedParameterTypeSelector implements IParameterTypeSelector {
+ static final MapBasedParameterTypeSelector defaultSelector = new MapBasedParameterTypeSelector(false);
+ private final Map<ParameterKey, ParameterType<?, ?>> parameterTypeMap;
+ private final boolean useDefault;
+
+ public MapBasedParameterTypeSelector(boolean useDefault) {
+ this.parameterTypeMap = new HashMap<>();
+ this.useDefault = useDefault;
+ }
+
+ @Override
+ public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectExact(ParameterKey key) {
+ ParameterType<?, ?> out = parameterTypeMap.get(key);
+ if (useDefault && out == null) {
+ out = defaultSelector.selectExact(key);
+ }
+ if (out == null && key.getReturnType().isEnum()) {
+ //noinspection unchecked
+ out = new EnumParameterType(key.getReturnType());
+ addType(false, out);
+ }
+ return cast(out);
+ }
+
+ @Override
+ public <TReturn, TParamInfo> ParameterType<TReturn, TParamInfo> selectAny(ParameterKey key) {
+ ParameterType<TReturn, TParamInfo> exact = selectExact(key);
+ if (exact != null) {
+ return exact;
+ }
+
+ if (key.getAnnotationClass() != null) {
+ exact = selectExact(new ParameterKey(key.getReturnType()));
+ if (exact != null) {
+ return exact;
+ }
+ }
+
+ Class<?> returnType = key.getReturnType();
+ Class<? extends Annotation> annotationClass = key.getAnnotationClass();
+
+ ParameterType<?, ?> out = selectByReturnType(parameterTypeMap, returnType, annotationClass, false);
+ if (out == null && useDefault) {
+ out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, false);
+ }
+ if (out == null) {
+ out = selectByReturnType(parameterTypeMap, returnType, annotationClass, true);
+ }
+ if (out == null && useDefault) {
+ out = selectByReturnType(defaultSelector.parameterTypeMap, returnType, annotationClass, true);
+ }
+ return cast(out);
+ }
+
+ private static ParameterType<?, ?> selectByReturnType(Map<ParameterKey, ParameterType<?, ?>> map, Class<?> returnType,
+ Class<? extends Annotation> annotationClass, boolean allowSubclass) {
+ ParameterType<?, ?> out = null;
+ if (allowSubclass) {
+ for (ParameterType<?, ?> type : map.values()) {
+ if (returnType.isAssignableFrom(type.getReturnType())) {
+ if (annotationClass == type.getAnnotationClass()) {
+ out = type;
+ break;
+ }
+ if (out == null) {
+ out = type;
+ }
+ }
+ }
+ } else {
+ for (ParameterType<?, ?> type : map.values()) {
+ if (returnType == type.getReturnType()) {
+ if (annotationClass == type.getAnnotationClass()) {
+ out = type;
+ break;
+ }
+ if (out == null) {
+ out = type;
+ }
+ }
+ }
+ }
+ return out;
+ }
+
+ private static <T> T cast(Object o) {
+ //noinspection unchecked
+ return (T) o;
+ }
+
+ @Override
+ public void addType(boolean infolessAlias, ParameterType<?, ?> type) {
+ parameterTypeMap.put(type.getTypeKey(), type);
+
+ if (infolessAlias) {
+ parameterTypeMap.putIfAbsent(type.getInfolessTypeKey(), type);
+ }
+ }
+
+ static {
+ // registers default parameter types
+ ParameterTypes.clinit();
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterConfig.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterConfig.java
index dbd7590..d33932b 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterConfig.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterConfig.java
@@ -1,80 +1,80 @@
-package io.dico.dicore.command.parameter.type;
-
-import io.dico.dicore.Reflection;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Constructor;
-
-/**
- * This class serves the purpose of having annotated parameter configurations (such as ranges for number parameters).
- * Such configurations must be possible to obtain without using annotations, and as such, there should be a class conveying the information
- * that is separate from the annotation itself. This class acts as a bridge from the annotation to said class conveying the information.
- *
- * @param <TAnnotation> the annotation type for parameters
- * @param <TParamInfo> the object type that holds the information required in memory
- */
-public abstract class ParameterConfig<TAnnotation extends Annotation, TParamInfo> implements Comparable<ParameterConfig<?, ?>> {
- private final Class<TAnnotation> annotationClass;
- // protected final TParamInfo defaultValue;
-
- public ParameterConfig(Class<TAnnotation> annotationClass/*, TParamInfo defaultValue*/) {
- this.annotationClass = annotationClass;
- //this.defaultValue = defaultValue;
- }
-
- public final Class<TAnnotation> getAnnotationClass() {
- return annotationClass;
- }
- /*
- public TParamInfo getDefaultValue() {
- return defaultValue;
- }*/
-
- protected abstract TParamInfo toParameterInfo(TAnnotation annotation);
-
- public TParamInfo getParameterInfo(Annotation annotation) {
- //noinspection unchecked
- return toParameterInfo((TAnnotation) annotation);
- }
-
- public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo>
- includeMemoryClass(Class<TAnnotation> annotationClass, Class<TParamInfo> memoryClass) {
- Constructor<TParamInfo> constructor;
- //TParamInfo defaultValue;
- try {
- constructor = memoryClass.getConstructor(annotationClass);
- //defaultValue = Reflection.getStaticFieldValue(annotationClass, "DEFAULT");
- } catch (NoSuchMethodException | IllegalArgumentException ex) {
- throw new IllegalArgumentException(ex);
- }
- /*
- if (defaultValue == null) try {
- defaultValue = memoryClass.newInstance();
- } catch (IllegalAccessException | InstantiationException ex) {
- throw new IllegalArgumentException("Failed to get a default value for the param info", ex);
- }*/
-
- return new ParameterConfig<TAnnotation, TParamInfo>(annotationClass/*, defaultValue*/) {
-
- @Override
- public TParamInfo toParameterInfo(TAnnotation annotation) {
- try {
- return constructor.newInstance(annotation);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
- };
- }
-
- public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo> getMemoryClassFromField(Class<TAnnotation> annotationClass) {
- return ParameterConfig.includeMemoryClass(annotationClass, Reflection.getStaticFieldValue(annotationClass, "MEMORY_CLASS"));
- }
-
- @Override
- public int compareTo(ParameterConfig<?, ?> o) {
- return 0;
- }
-
-}
-
+package io.dico.dicore.command.parameter.type;
+
+import io.dico.dicore.Reflection;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+
+/**
+ * This class serves the purpose of having annotated parameter configurations (such as ranges for number parameters).
+ * Such configurations must be possible to obtain without using annotations, and as such, there should be a class conveying the information
+ * that is separate from the annotation itself. This class acts as a bridge from the annotation to said class conveying the information.
+ *
+ * @param <TAnnotation> the annotation type for parameters
+ * @param <TParamInfo> the object type that holds the information required in memory
+ */
+public abstract class ParameterConfig<TAnnotation extends Annotation, TParamInfo> implements Comparable<ParameterConfig<?, ?>> {
+ private final Class<TAnnotation> annotationClass;
+ // protected final TParamInfo defaultValue;
+
+ public ParameterConfig(Class<TAnnotation> annotationClass/*, TParamInfo defaultValue*/) {
+ this.annotationClass = annotationClass;
+ //this.defaultValue = defaultValue;
+ }
+
+ public final Class<TAnnotation> getAnnotationClass() {
+ return annotationClass;
+ }
+ /*
+ public TParamInfo getDefaultValue() {
+ return defaultValue;
+ }*/
+
+ protected abstract TParamInfo toParameterInfo(TAnnotation annotation);
+
+ public TParamInfo getParameterInfo(Annotation annotation) {
+ //noinspection unchecked
+ return toParameterInfo((TAnnotation) annotation);
+ }
+
+ public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo>
+ includeMemoryClass(Class<TAnnotation> annotationClass, Class<TParamInfo> memoryClass) {
+ Constructor<TParamInfo> constructor;
+ //TParamInfo defaultValue;
+ try {
+ constructor = memoryClass.getConstructor(annotationClass);
+ //defaultValue = Reflection.getStaticFieldValue(annotationClass, "DEFAULT");
+ } catch (NoSuchMethodException | IllegalArgumentException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ /*
+ if (defaultValue == null) try {
+ defaultValue = memoryClass.newInstance();
+ } catch (IllegalAccessException | InstantiationException ex) {
+ throw new IllegalArgumentException("Failed to get a default value for the param info", ex);
+ }*/
+
+ return new ParameterConfig<TAnnotation, TParamInfo>(annotationClass/*, defaultValue*/) {
+
+ @Override
+ public TParamInfo toParameterInfo(TAnnotation annotation) {
+ try {
+ return constructor.newInstance(annotation);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ };
+ }
+
+ public static <TAnnotation extends Annotation, TParamInfo> ParameterConfig<TAnnotation, TParamInfo> getMemoryClassFromField(Class<TAnnotation> annotationClass) {
+ return ParameterConfig.includeMemoryClass(annotationClass, Reflection.getStaticFieldValue(annotationClass, "MEMORY_CLASS"));
+ }
+
+ @Override
+ public int compareTo(ParameterConfig<?, ?> o) {
+ return 0;
+ }
+
+}
+
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
index e1a62fa..e9cca7f 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/ParameterType.java
@@ -1,149 +1,149 @@
-package io.dico.dicore.command.parameter.type;
-
-import io.dico.dicore.Reflection;
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.annotation.Range;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.Parameter;
-import org.bukkit.Location;
-import org.bukkit.command.CommandSender;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * A parameter type.
- * Takes care of parsing, default values as well as completions.
- *
- * @param <TReturn> type of the parameter
- * @param <TParamInfo> the info object type for the parameter (Example: {@link Range.Memory}
- */
-public abstract class ParameterType<TReturn, TParamInfo> {
- private final Class<TReturn> returnType;
- private final ParameterConfig<?, TParamInfo> parameterConfig;
- protected final ParameterType<TReturn, TParamInfo> otherType; // flag or non-flag, depending on current
-
- public ParameterType(Class<TReturn> returnType) {
- this(returnType, null);
- }
-
- public ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
- this.returnType = Objects.requireNonNull(returnType);
- this.parameterConfig = paramConfig;
-
- ParameterType<TReturn, TParamInfo> otherType = flagTypeParameter();
- this.otherType = otherType == null ? this : otherType;
- }
-
- protected ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> parameterConfig, ParameterType<TReturn, TParamInfo> otherType) {
- this.returnType = returnType;
- this.parameterConfig = parameterConfig;
- this.otherType = otherType;
- }
-
- public int getExpectedAmountOfConsumedArguments() {
- return 1;
- }
-
- public boolean canBeFlag() {
- return this == otherType;
- }
-
- public boolean isFlagExplicitly() {
- return this instanceof FlagParameterType;
- }
-
- /**
- * @return The return type
- */
- public final Class<TReturn> getReturnType() {
- return returnType;
- }
-
- public final Class<?> getAnnotationClass() {
- return parameterConfig == null ? null : parameterConfig.getAnnotationClass();
- }
-
- public final ParameterConfig<?, TParamInfo> getParameterConfig() {
- return parameterConfig;
- }
-
- public ParameterKey getTypeKey() {
- return new ParameterKey(returnType, parameterConfig != null ? parameterConfig.getAnnotationClass() : null);
- }
-
- public ParameterKey getInfolessTypeKey() {
- return new ParameterKey(returnType, null);
- }
-
- protected FlagParameterType<TReturn, TParamInfo> flagTypeParameter() {
- return null;
- }
-
- public ParameterType<TReturn, TParamInfo> asFlagParameter() {
- return canBeFlag() ? this : otherType;
- }
-
- public ParameterType<TReturn, TParamInfo> asNormalParameter() {
- return isFlagExplicitly() ? otherType : this;
- }
-
- public abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException;
-
- public TReturn parseForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
- return parse(parameter, context.getSender(), buffer);
- }
-
- public TReturn getDefaultValue(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
- return null;
- }
-
- public TReturn getDefaultValueForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
- return getDefaultValue(parameter, context.getSender(), buffer);
- }
-
- public List<String> complete(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
- return Collections.emptyList();
- }
-
- public List<String> completeForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, Location location, ArgumentBuffer buffer) {
- return complete(parameter, context.getSender(), location, buffer);
- }
-
- protected static abstract class FlagParameterType<TResult, TParamInfo> extends ParameterType<TResult, TParamInfo> {
-
- protected FlagParameterType(ParameterType<TResult, TParamInfo> otherType) {
- super(otherType.returnType, otherType.parameterConfig, otherType);
- }
-
- @Override
- public int getExpectedAmountOfConsumedArguments() {
- return otherType.getExpectedAmountOfConsumedArguments();
- }
-
- @Override
- public boolean canBeFlag() {
- return true;
- }
-
- @Override
- protected final FlagParameterType<TResult, TParamInfo> flagTypeParameter() {
- return this;
- }
-
- @Override
- public ParameterType<TResult, TParamInfo> asFlagParameter() {
- return this;
- }
-
- @Override
- public ParameterType<TResult, TParamInfo> asNormalParameter() {
- return otherType;
- }
-
- }
-
-}
+package io.dico.dicore.command.parameter.type;
+
+import io.dico.dicore.Reflection;
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.annotation.Range;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import org.bukkit.Location;
+import org.bukkit.command.CommandSender;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A parameter type.
+ * Takes care of parsing, default values as well as completions.
+ *
+ * @param <TReturn> type of the parameter
+ * @param <TParamInfo> the info object type for the parameter (Example: {@link Range.Memory}
+ */
+public abstract class ParameterType<TReturn, TParamInfo> {
+ private final Class<TReturn> returnType;
+ private final ParameterConfig<?, TParamInfo> parameterConfig;
+ protected final ParameterType<TReturn, TParamInfo> otherType; // flag or non-flag, depending on current
+
+ public ParameterType(Class<TReturn> returnType) {
+ this(returnType, null);
+ }
+
+ public ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
+ this.returnType = Objects.requireNonNull(returnType);
+ this.parameterConfig = paramConfig;
+
+ ParameterType<TReturn, TParamInfo> otherType = flagTypeParameter();
+ this.otherType = otherType == null ? this : otherType;
+ }
+
+ protected ParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> parameterConfig, ParameterType<TReturn, TParamInfo> otherType) {
+ this.returnType = returnType;
+ this.parameterConfig = parameterConfig;
+ this.otherType = otherType;
+ }
+
+ public int getExpectedAmountOfConsumedArguments() {
+ return 1;
+ }
+
+ public boolean canBeFlag() {
+ return this == otherType;
+ }
+
+ public boolean isFlagExplicitly() {
+ return this instanceof FlagParameterType;
+ }
+
+ /**
+ * @return The return type
+ */
+ public final Class<TReturn> getReturnType() {
+ return returnType;
+ }
+
+ public final Class<?> getAnnotationClass() {
+ return parameterConfig == null ? null : parameterConfig.getAnnotationClass();
+ }
+
+ public final ParameterConfig<?, TParamInfo> getParameterConfig() {
+ return parameterConfig;
+ }
+
+ public ParameterKey getTypeKey() {
+ return new ParameterKey(returnType, parameterConfig != null ? parameterConfig.getAnnotationClass() : null);
+ }
+
+ public ParameterKey getInfolessTypeKey() {
+ return new ParameterKey(returnType, null);
+ }
+
+ protected FlagParameterType<TReturn, TParamInfo> flagTypeParameter() {
+ return null;
+ }
+
+ public ParameterType<TReturn, TParamInfo> asFlagParameter() {
+ return canBeFlag() ? this : otherType;
+ }
+
+ public ParameterType<TReturn, TParamInfo> asNormalParameter() {
+ return isFlagExplicitly() ? otherType : this;
+ }
+
+ public abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException;
+
+ public TReturn parseForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
+ return parse(parameter, context.getSender(), buffer);
+ }
+
+ public TReturn getDefaultValue(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
+ return null;
+ }
+
+ public TReturn getDefaultValueForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
+ return getDefaultValue(parameter, context.getSender(), buffer);
+ }
+
+ public List<String> complete(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, Location location, ArgumentBuffer buffer) {
+ return Collections.emptyList();
+ }
+
+ public List<String> completeForContext(Parameter<TReturn, TParamInfo> parameter, ExecutionContext context, Location location, ArgumentBuffer buffer) {
+ return complete(parameter, context.getSender(), location, buffer);
+ }
+
+ protected static abstract class FlagParameterType<TResult, TParamInfo> extends ParameterType<TResult, TParamInfo> {
+
+ protected FlagParameterType(ParameterType<TResult, TParamInfo> otherType) {
+ super(otherType.returnType, otherType.parameterConfig, otherType);
+ }
+
+ @Override
+ public int getExpectedAmountOfConsumedArguments() {
+ return otherType.getExpectedAmountOfConsumedArguments();
+ }
+
+ @Override
+ public boolean canBeFlag() {
+ return true;
+ }
+
+ @Override
+ protected final FlagParameterType<TResult, TParamInfo> flagTypeParameter() {
+ return this;
+ }
+
+ @Override
+ public ParameterType<TResult, TParamInfo> asFlagParameter() {
+ return this;
+ }
+
+ @Override
+ public ParameterType<TResult, TParamInfo> asNormalParameter() {
+ return otherType;
+ }
+
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/SimpleParameterType.java b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/SimpleParameterType.java
index ecf19ce..667b2c7 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/SimpleParameterType.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/parameter/type/SimpleParameterType.java
@@ -1,31 +1,31 @@
-package io.dico.dicore.command.parameter.type;
-
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.Parameter;
-import org.bukkit.command.CommandSender;
-
-/**
- * An abstraction for parameter types that only parse a single argument
- *
- * @param <TReturn> the parameter type
- * @param <TParamInfo> parameter info object type
- */
-public abstract class SimpleParameterType<TReturn, TParamInfo> extends ParameterType<TReturn, TParamInfo> {
-
- public SimpleParameterType(Class<TReturn> returnType) {
- super(returnType);
- }
-
- public SimpleParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
- super(returnType, paramConfig);
- }
-
- protected abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, String input) throws CommandException;
-
- @Override
- public TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
- return parse(parameter, sender, buffer.requireNext(parameter.getName()));
- }
-
-}
+package io.dico.dicore.command.parameter.type;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import org.bukkit.command.CommandSender;
+
+/**
+ * An abstraction for parameter types that only parse a single argument
+ *
+ * @param <TReturn> the parameter type
+ * @param <TParamInfo> parameter info object type
+ */
+public abstract class SimpleParameterType<TReturn, TParamInfo> extends ParameterType<TReturn, TParamInfo> {
+
+ public SimpleParameterType(Class<TReturn> returnType) {
+ super(returnType);
+ }
+
+ public SimpleParameterType(Class<TReturn> returnType, ParameterConfig<?, TParamInfo> paramConfig) {
+ super(returnType, paramConfig);
+ }
+
+ protected abstract TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, String input) throws CommandException;
+
+ @Override
+ public TReturn parse(Parameter<TReturn, TParamInfo> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
+ return parse(parameter, sender, buffer.requireNext(parameter.getName()));
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
index e664cef..6828fcc 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/DefaultGroupCommand.java
@@ -1,56 +1,56 @@
-package io.dico.dicore.command.predef;
-
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.ExecutionContext;
-import io.dico.dicore.command.IContextFilter;
-import org.bukkit.command.CommandSender;
-
-public class DefaultGroupCommand extends PredefinedCommand<DefaultGroupCommand> {
- private static final DefaultGroupCommand instance;
- private static final IContextFilter noArgumentFilter;
-
- public static DefaultGroupCommand getInstance() {
- return instance;
- }
-
- private DefaultGroupCommand(boolean modifiable) {
- addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
- addContextFilter(noArgumentFilter);
- this.modifiable = modifiable;
- }
-
- public DefaultGroupCommand() {
- this(true);
- }
-
- @Override
- protected DefaultGroupCommand newModifiableInstance() {
- return new DefaultGroupCommand(true);
- }
-
- @Override
- public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
- context.getAddress().getChatHandler().sendHelpMessage(sender, context, context.getAddress(), 1);
- return null;
- }
-
- static {
- noArgumentFilter = new IContextFilter() {
- @Override
- public void filterContext(ExecutionContext context) throws CommandException {
- if (context.getBuffer().hasNext()) {
- throw new CommandException("No such command: /" + context.getAddress().getAddress()
- + " " + context.getBuffer().next());
- }
- }
-
- @Override
- public Priority getPriority() {
- return Priority.EARLY;
- }
- };
-
- instance = new DefaultGroupCommand(false);
- }
-
-}
+package io.dico.dicore.command.predef;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.command.IContextFilter;
+import org.bukkit.command.CommandSender;
+
+public class DefaultGroupCommand extends PredefinedCommand<DefaultGroupCommand> {
+ private static final DefaultGroupCommand instance;
+ private static final IContextFilter noArgumentFilter;
+
+ public static DefaultGroupCommand getInstance() {
+ return instance;
+ }
+
+ private DefaultGroupCommand(boolean modifiable) {
+ addContextFilter(IContextFilter.INHERIT_PERMISSIONS);
+ addContextFilter(noArgumentFilter);
+ this.modifiable = modifiable;
+ }
+
+ public DefaultGroupCommand() {
+ this(true);
+ }
+
+ @Override
+ protected DefaultGroupCommand newModifiableInstance() {
+ return new DefaultGroupCommand(true);
+ }
+
+ @Override
+ public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
+ context.getAddress().getChatHandler().sendHelpMessage(sender, context, context.getAddress(), 1);
+ return null;
+ }
+
+ static {
+ noArgumentFilter = new IContextFilter() {
+ @Override
+ public void filterContext(ExecutionContext context) throws CommandException {
+ if (context.getBuffer().hasNext()) {
+ throw new CommandException("No such command: /" + context.getAddress().getAddress()
+ + " " + context.getBuffer().next());
+ }
+ }
+
+ @Override
+ public Priority getPriority() {
+ return Priority.EARLY;
+ }
+ };
+
+ instance = new DefaultGroupCommand(false);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommand.java
index def0db1..985e055 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/HelpCommand.java
@@ -1,76 +1,76 @@
-package io.dico.dicore.command.predef;
-
-import io.dico.dicore.command.*;
-import io.dico.dicore.command.annotation.Range;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.type.NumberParameterType;
-import org.bukkit.command.CommandSender;
-
-/**
- * The help command
- */
-public class HelpCommand extends PredefinedCommand<HelpCommand> {
- private static final Parameter<Integer, Range.Memory> pageParameter;
- public static final HelpCommand INSTANCE;
-
- private HelpCommand(boolean modifiable) {
- super(modifiable);
- getParameterList().addParameter(pageParameter);
- getParameterList().setRequiredCount(0);
- setDescription("Shows this help page");
- }
-
- @Override
- protected HelpCommand newModifiableInstance() {
- return new HelpCommand(true);
- }
-
- @Override
- public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
- ICommandAddress target = context.getAddress();
- if (context.getAddress().getCommand() == this) {
- target = target.getParent();
- }
-
- context.getAddress().getChatHandler().sendHelpMessage(sender, context, target, context.<Integer>get("page") - 1);
- return null;
- }
-
- public static void registerAsChild(ICommandAddress address) {
- registerAsChild(address, "help");
- }
-
- public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
- ((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
- }
-
- static {
- pageParameter = new Parameter<>("page", "the page number",
- new NumberParameterType<Integer>(Integer.TYPE) {
- @Override
- protected Integer parse(String input) throws NumberFormatException {
- return Integer.parseInt(input);
- }
-
- @Override
- protected Integer select(Number number) {
- return number.intValue();
- }
-
- @Override
- public Integer parseForContext(Parameter<Integer, Range.Memory> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
- if (context.getAddress().getCommand() == null || context.getAddress().getCommand().getClass() != HelpCommand.class) {
- // An address was executed with its help command as target
- buffer.next();
- return 1;
- }
- return parse(parameter, context.getSender(), buffer);
- }
- },
- new Range.Memory(1, Integer.MAX_VALUE, 1));
-
- INSTANCE = new HelpCommand(false);
- }
-
-}
+package io.dico.dicore.command.predef;
+
+import io.dico.dicore.command.*;
+import io.dico.dicore.command.annotation.Range;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.type.NumberParameterType;
+import org.bukkit.command.CommandSender;
+
+/**
+ * The help command
+ */
+public class HelpCommand extends PredefinedCommand<HelpCommand> {
+ private static final Parameter<Integer, Range.Memory> pageParameter;
+ public static final HelpCommand INSTANCE;
+
+ private HelpCommand(boolean modifiable) {
+ super(modifiable);
+ getParameterList().addParameter(pageParameter);
+ getParameterList().setRequiredCount(0);
+ setDescription("Shows this help page");
+ }
+
+ @Override
+ protected HelpCommand newModifiableInstance() {
+ return new HelpCommand(true);
+ }
+
+ @Override
+ public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
+ ICommandAddress target = context.getAddress();
+ if (context.getAddress().getCommand() == this) {
+ target = target.getParent();
+ }
+
+ context.getAddress().getChatHandler().sendHelpMessage(sender, context, target, context.<Integer>get("page") - 1);
+ return null;
+ }
+
+ public static void registerAsChild(ICommandAddress address) {
+ registerAsChild(address, "help");
+ }
+
+ public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
+ ((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
+ }
+
+ static {
+ pageParameter = new Parameter<>("page", "the page number",
+ new NumberParameterType<Integer>(Integer.TYPE) {
+ @Override
+ protected Integer parse(String input) throws NumberFormatException {
+ return Integer.parseInt(input);
+ }
+
+ @Override
+ protected Integer select(Number number) {
+ return number.intValue();
+ }
+
+ @Override
+ public Integer parseForContext(Parameter<Integer, Range.Memory> parameter, ExecutionContext context, ArgumentBuffer buffer) throws CommandException {
+ if (context.getAddress().getCommand() == null || context.getAddress().getCommand().getClass() != HelpCommand.class) {
+ // An address was executed with its help command as target
+ buffer.next();
+ return 1;
+ }
+ return parse(parameter, context.getSender(), buffer);
+ }
+ },
+ new Range.Memory(1, Integer.MAX_VALUE, 1));
+
+ INSTANCE = new HelpCommand(false);
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/PredefinedCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/PredefinedCommand.java
index 4340356..b7c5587 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/PredefinedCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/PredefinedCommand.java
@@ -1,50 +1,50 @@
-package io.dico.dicore.command.predef;
-
-import io.dico.dicore.command.CommandBuilder;
-import io.dico.dicore.command.ExtendedCommand;
-import io.dico.dicore.command.ICommandAddress;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Consumer;
-
-/**
- * Marker class for commands that are generated. These commands can be replaced using methods in {@link CommandBuilder}
- */
-public abstract class PredefinedCommand<T extends PredefinedCommand<T>> extends ExtendedCommand<T> {
- static final Map<String, Consumer<ICommandAddress>> predefinedCommandGenerators = new HashMap<>();
-
- /**
- * Get a predefined command
- *
- * @param name the name
- * @return the subscriber
- */
- public static Consumer<ICommandAddress> getPredefinedCommandGenerator(String name) {
- return predefinedCommandGenerators.get(name);
- }
-
- /**
- * Register a predefined command
- *
- * @param name the name
- * @param consumer the generator which adds the child to the address
- * @return true if and only if the subscriber was registered (false if the name exists)
- */
- public static boolean registerPredefinedCommandGenerator(String name, Consumer<ICommandAddress> consumer) {
- return predefinedCommandGenerators.putIfAbsent(name, consumer) == null;
- }
-
- static {
- registerPredefinedCommandGenerator("help", HelpCommand::registerAsChild);
- //noinspection StaticInitializerReferencesSubClass
- registerPredefinedCommandGenerator("syntax", SyntaxCommand::registerAsChild);
- }
-
- public PredefinedCommand() {
- }
-
- public PredefinedCommand(boolean modifiable) {
- super(modifiable);
- }
-}
+package io.dico.dicore.command.predef;
+
+import io.dico.dicore.command.CommandBuilder;
+import io.dico.dicore.command.ExtendedCommand;
+import io.dico.dicore.command.ICommandAddress;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+
+/**
+ * Marker class for commands that are generated. These commands can be replaced using methods in {@link CommandBuilder}
+ */
+public abstract class PredefinedCommand<T extends PredefinedCommand<T>> extends ExtendedCommand<T> {
+ static final Map<String, Consumer<ICommandAddress>> predefinedCommandGenerators = new HashMap<>();
+
+ /**
+ * Get a predefined command
+ *
+ * @param name the name
+ * @return the subscriber
+ */
+ public static Consumer<ICommandAddress> getPredefinedCommandGenerator(String name) {
+ return predefinedCommandGenerators.get(name);
+ }
+
+ /**
+ * Register a predefined command
+ *
+ * @param name the name
+ * @param consumer the generator which adds the child to the address
+ * @return true if and only if the subscriber was registered (false if the name exists)
+ */
+ public static boolean registerPredefinedCommandGenerator(String name, Consumer<ICommandAddress> consumer) {
+ return predefinedCommandGenerators.putIfAbsent(name, consumer) == null;
+ }
+
+ static {
+ registerPredefinedCommandGenerator("help", HelpCommand::registerAsChild);
+ //noinspection StaticInitializerReferencesSubClass
+ registerPredefinedCommandGenerator("syntax", SyntaxCommand::registerAsChild);
+ }
+
+ public PredefinedCommand() {
+ }
+
+ public PredefinedCommand(boolean modifiable) {
+ super(modifiable);
+ }
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/predef/SyntaxCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/predef/SyntaxCommand.java
index 7ae8638..8532584 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/predef/SyntaxCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/predef/SyntaxCommand.java
@@ -1,36 +1,36 @@
-package io.dico.dicore.command.predef;
-
-import io.dico.dicore.command.*;
-import org.bukkit.command.CommandSender;
-
-/**
- * The syntax command
- */
-public class SyntaxCommand extends PredefinedCommand<SyntaxCommand> {
- public static final SyntaxCommand INSTANCE = new SyntaxCommand(false);
-
- private SyntaxCommand(boolean modifiable) {
- super(modifiable);
- setDescription("Describes how to use the command");
- }
-
- @Override
- protected SyntaxCommand newModifiableInstance() {
- return new SyntaxCommand(true);
- }
-
- @Override
- public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
- context.getAddress().getChatHandler().sendSyntaxMessage(sender, context, context.getAddress().getParent());
- return null;
- }
-
- public static void registerAsChild(ICommandAddress address) {
- registerAsChild(address, "syntax");
- }
-
- public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
- ((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
- }
-
-}
+package io.dico.dicore.command.predef;
+
+import io.dico.dicore.command.*;
+import org.bukkit.command.CommandSender;
+
+/**
+ * The syntax command
+ */
+public class SyntaxCommand extends PredefinedCommand<SyntaxCommand> {
+ public static final SyntaxCommand INSTANCE = new SyntaxCommand(false);
+
+ private SyntaxCommand(boolean modifiable) {
+ super(modifiable);
+ setDescription("Describes how to use the command");
+ }
+
+ @Override
+ protected SyntaxCommand newModifiableInstance() {
+ return new SyntaxCommand(true);
+ }
+
+ @Override
+ public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
+ context.getAddress().getChatHandler().sendSyntaxMessage(sender, context, context.getAddress().getParent());
+ return null;
+ }
+
+ public static void registerAsChild(ICommandAddress address) {
+ registerAsChild(address, "syntax");
+ }
+
+ public static void registerAsChild(ICommandAddress address, String main, String... aliases) {
+ ((ModifiableCommandAddress) address).addChild(new ChildCommandAddress(INSTANCE, main, aliases));
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/BukkitCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/BukkitCommand.java
index b5346d0..40de6ae 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/BukkitCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/BukkitCommand.java
@@ -1,122 +1,122 @@
-package io.dico.dicore.command.registration;
-
-import io.dico.dicore.command.ICommandAddress;
-import io.dico.dicore.command.ICommandDispatcher;
-import org.bukkit.Location;
-import org.bukkit.command.Command;
-import org.bukkit.command.CommandSender;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.List;
-
-/**
- * This class extends the bukkit's command class.
- * Instances are injected into the command map.
- */
-public class BukkitCommand extends Command {
- private ICommandDispatcher dispatcher;
- private ICommandAddress origin;
-
- public BukkitCommand(ICommandAddress address) {
- super(validateTree(address).getNames().get(0), "", "", address.getNames().subList(1, address.getNames().size()));
- this.dispatcher = address.getDispatcherForTree();
- this.origin = address;
-
- setTimingsIfNecessary(this);
- }
-
- private static ICommandAddress validateTree(ICommandAddress tree) {
- if (!tree.hasParent()) {
- throw new IllegalArgumentException();
- }
- if (tree.getNames().isEmpty()) {
- throw new IllegalArgumentException();
- }
- return tree;
- }
-
- public ICommandAddress getOrigin() {
- return origin;
- }
-
- @Override
- public boolean execute(CommandSender sender, String label, String[] args) {
- if (!dispatcher.dispatchCommand(sender, label, args)) {
- //System.out.println("failed to dispatch command");
- // target command not found, send a message in the future TODO
- }
- return true;
- }
-
- @Override
- public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
- return this.tabComplete(sender, alias, args, null);
- }
-
- //@Override
- public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
- return dispatcher.getTabCompletions(sender, alias, location, args);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- BukkitCommand that = (BukkitCommand) o;
-
- return getName().equals(that.getName()) && dispatcher == that.dispatcher;
- }
-
- @Override
- public int hashCode() {
- return dispatcher.hashCode() | getName().hashCode();
- }
-
- private static void setTimingsIfNecessary(Command object) {
- // with paper spigot, the timings are not set by super constructor but by CommandMap.register(), which is not invoked for this system
- // I use reflection so that the project does not require paper spigot to build
- try {
- // public field
- Field field = Command.class.getDeclaredField("timings");
- if (field.get(object) != null) return;
- Class<?> clazz = Class.forName("co.aikar.timings.TimingsManager");
- // public method
- Method method = clazz.getDeclaredMethod("getCommandTiming", String.class, Command.class);
- Object timings = method.invoke(null, "", object);
- field.set(object, timings);
- } catch (Throwable ignored) {
- }
- }
-
- /*
- public static void registerToMap(ICommandAddress tree, Map<String, Command> map) {
- BukkitCommand command = new BukkitCommand(tree);
- Iterator<String> iterator = tree.getNames().iterator();
- map.put(iterator.next(), command);
- while (iterator.hasNext()) {
- map.putIfAbsent(iterator.next(), command);
- }
- }
-
- public static void unregisterFromMap(ICommandAddress tree, Map<String, Command> map) {
- map.values().remove(new BukkitCommand(tree));
- }
-
- public static void registerChildrenToMap(ICommandAddress tree, Map<String, Command> map) {
- for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
- ICommandAddress child = entry.getValue();
- registerToMap(child, map);
- }
- }
-
- public static void unregisterChildenFromMap(ICommandAddress tree, Map<String, Command> map) {
- for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
- ICommandAddress child = entry.getValue();
- unregisterFromMap(child, map);
- }
- }
- */
-
-}
+package io.dico.dicore.command.registration;
+
+import io.dico.dicore.command.ICommandAddress;
+import io.dico.dicore.command.ICommandDispatcher;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * This class extends the bukkit's command class.
+ * Instances are injected into the command map.
+ */
+public class BukkitCommand extends Command {
+ private ICommandDispatcher dispatcher;
+ private ICommandAddress origin;
+
+ public BukkitCommand(ICommandAddress address) {
+ super(validateTree(address).getNames().get(0), "", "", address.getNames().subList(1, address.getNames().size()));
+ this.dispatcher = address.getDispatcherForTree();
+ this.origin = address;
+
+ setTimingsIfNecessary(this);
+ }
+
+ private static ICommandAddress validateTree(ICommandAddress tree) {
+ if (!tree.hasParent()) {
+ throw new IllegalArgumentException();
+ }
+ if (tree.getNames().isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ return tree;
+ }
+
+ public ICommandAddress getOrigin() {
+ return origin;
+ }
+
+ @Override
+ public boolean execute(CommandSender sender, String label, String[] args) {
+ if (!dispatcher.dispatchCommand(sender, label, args)) {
+ //System.out.println("failed to dispatch command");
+ // target command not found, send a message in the future TODO
+ }
+ return true;
+ }
+
+ @Override
+ public List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
+ return this.tabComplete(sender, alias, args, null);
+ }
+
+ //@Override
+ public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
+ return dispatcher.getTabCompletions(sender, alias, location, args);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ BukkitCommand that = (BukkitCommand) o;
+
+ return getName().equals(that.getName()) && dispatcher == that.dispatcher;
+ }
+
+ @Override
+ public int hashCode() {
+ return dispatcher.hashCode() | getName().hashCode();
+ }
+
+ private static void setTimingsIfNecessary(Command object) {
+ // with paper spigot, the timings are not set by super constructor but by CommandMap.register(), which is not invoked for this system
+ // I use reflection so that the project does not require paper spigot to build
+ try {
+ // public field
+ Field field = Command.class.getDeclaredField("timings");
+ if (field.get(object) != null) return;
+ Class<?> clazz = Class.forName("co.aikar.timings.TimingsManager");
+ // public method
+ Method method = clazz.getDeclaredMethod("getCommandTiming", String.class, Command.class);
+ Object timings = method.invoke(null, "", object);
+ field.set(object, timings);
+ } catch (Throwable ignored) {
+ }
+ }
+
+ /*
+ public static void registerToMap(ICommandAddress tree, Map<String, Command> map) {
+ BukkitCommand command = new BukkitCommand(tree);
+ Iterator<String> iterator = tree.getNames().iterator();
+ map.put(iterator.next(), command);
+ while (iterator.hasNext()) {
+ map.putIfAbsent(iterator.next(), command);
+ }
+ }
+
+ public static void unregisterFromMap(ICommandAddress tree, Map<String, Command> map) {
+ map.values().remove(new BukkitCommand(tree));
+ }
+
+ public static void registerChildrenToMap(ICommandAddress tree, Map<String, Command> map) {
+ for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
+ ICommandAddress child = entry.getValue();
+ registerToMap(child, map);
+ }
+ }
+
+ public static void unregisterChildenFromMap(ICommandAddress tree, Map<String, Command> map) {
+ for (Map.Entry<String, ? extends ICommandAddress> entry : tree.getChildren().entrySet()) {
+ ICommandAddress child = entry.getValue();
+ unregisterFromMap(child, map);
+ }
+ }
+ */
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/CommandMap.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/CommandMap.java
index 780ec66..2008b29 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/CommandMap.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/CommandMap.java
@@ -1,59 +1,59 @@
-package io.dico.dicore.command.registration;
-
-import io.dico.dicore.Reflection;
-import org.bukkit.Bukkit;
-import org.bukkit.command.Command;
-import org.bukkit.command.SimpleCommandMap;
-import org.bukkit.plugin.SimplePluginManager;
-
-import java.util.*;
-
-/**
- * Provides access to bukkit's {@code Map<String, org.bukkit.command.Command>} command map.
- */
-@SuppressWarnings("ConstantConditions")
-public class CommandMap {
- private static final Map<String, Command> commandMap = findCommandMap();
-
- private CommandMap() {
-
- }
-
- public static Map<String, Command> getCommandMap() {
- return Objects.requireNonNull(commandMap);
- }
-
- public static boolean isAvailable() {
- return commandMap != null;
- }
-
- public static Command get(String key) {
- return commandMap.get(key);
- }
-
- public static void put(String key, Command command) {
- commandMap.put(key, command);
- }
-
- public static Collection<String> replace(Command command, Command replacement) {
- List<String> result = new ArrayList<>();
- for (Map.Entry<String, Command> entry : commandMap.entrySet()) {
- if (entry.getValue() == command) {
- entry.setValue(replacement);
- result.add(entry.getKey());
- }
- }
- return result;
- }
-
- private static Map<String, Command> findCommandMap() {
- try {
- return Reflection.getFieldValue(SimpleCommandMap.class, "knownCommands",
- Reflection.getFieldValue(SimplePluginManager.class, "commandMap", Bukkit.getPluginManager()));
- } catch (Exception ex) {
- ex.printStackTrace();
- return null;
- }
- }
-
-}
+package io.dico.dicore.command.registration;
+
+import io.dico.dicore.Reflection;
+import org.bukkit.Bukkit;
+import org.bukkit.command.Command;
+import org.bukkit.command.SimpleCommandMap;
+import org.bukkit.plugin.SimplePluginManager;
+
+import java.util.*;
+
+/**
+ * Provides access to bukkit's {@code Map<String, org.bukkit.command.Command>} command map.
+ */
+@SuppressWarnings("ConstantConditions")
+public class CommandMap {
+ private static final Map<String, Command> commandMap = findCommandMap();
+
+ private CommandMap() {
+
+ }
+
+ public static Map<String, Command> getCommandMap() {
+ return Objects.requireNonNull(commandMap);
+ }
+
+ public static boolean isAvailable() {
+ return commandMap != null;
+ }
+
+ public static Command get(String key) {
+ return commandMap.get(key);
+ }
+
+ public static void put(String key, Command command) {
+ commandMap.put(key, command);
+ }
+
+ public static Collection<String> replace(Command command, Command replacement) {
+ List<String> result = new ArrayList<>();
+ for (Map.Entry<String, Command> entry : commandMap.entrySet()) {
+ if (entry.getValue() == command) {
+ entry.setValue(replacement);
+ result.add(entry.getKey());
+ }
+ }
+ return result;
+ }
+
+ private static Map<String, Command> findCommandMap() {
+ try {
+ return Reflection.getFieldValue(SimpleCommandMap.class, "knownCommands",
+ Reflection.getFieldValue(SimplePluginManager.class, "commandMap", Bukkit.getPluginManager()));
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/CommandParseException.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/CommandParseException.java
index 478c70c..0b7ce3c 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/CommandParseException.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/CommandParseException.java
@@ -1,27 +1,27 @@
-package io.dico.dicore.command.registration.reflect;
-
-/**
- * Thrown if an error occurs while 'parsing' a reflection command method
- * Other errors can be thrown too in there that may not be directly relevant to a parsing error.
- */
-public class CommandParseException extends Exception {
-
- public CommandParseException() {
- }
-
- public CommandParseException(String message) {
- super(message);
- }
-
- public CommandParseException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public CommandParseException(Throwable cause) {
- super(cause);
- }
-
- public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- }
-}
+package io.dico.dicore.command.registration.reflect;
+
+/**
+ * Thrown if an error occurs while 'parsing' a reflection command method
+ * Other errors can be thrown too in there that may not be directly relevant to a parsing error.
+ */
+public class CommandParseException extends Exception {
+
+ public CommandParseException() {
+ }
+
+ public CommandParseException(String message) {
+ super(message);
+ }
+
+ public CommandParseException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CommandParseException(Throwable cause) {
+ super(cause);
+ }
+
+ public CommandParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java
index 67b65e4..1e56b8a 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandInterceptor.java
@@ -1,36 +1,36 @@
-package io.dico.dicore.command.registration.reflect;
-
-import io.dico.dicore.command.ExecutionContext;
-
-import java.lang.reflect.Method;
-
-public interface ICommandInterceptor {
-
- /**
- * Get the receiver of the command, if applicable.
- * A command has a receiver if its first parameter implements {@link ICommandReceiver}
- * and its instance object implements this interface.
- *
- * @param context the context of execution
- * @param target the method of the command
- * @param cmdName the name of the command
- * @return the receiver
- */
- default ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName) {
- return null;
- }
-
- /**
- * If applicable, get the coroutine context to use in suspend functions (Kotlin only).
- * The return type is object to avoid depending on the kotlin runtime.
- *
- * @param context the context of execution
- * @param target the method of the command
- * @param cmdName the name of the command
- * @return the coroutine context
- */
- default Object getCoroutineContext(ExecutionContext context, Method target, String cmdName) {
- return null;
- }
-
-}
+package io.dico.dicore.command.registration.reflect;
+
+import io.dico.dicore.command.ExecutionContext;
+
+import java.lang.reflect.Method;
+
+public interface ICommandInterceptor {
+
+ /**
+ * Get the receiver of the command, if applicable.
+ * A command has a receiver if its first parameter implements {@link ICommandReceiver}
+ * and its instance object implements this interface.
+ *
+ * @param context the context of execution
+ * @param target the method of the command
+ * @param cmdName the name of the command
+ * @return the receiver
+ */
+ default ICommandReceiver getReceiver(ExecutionContext context, Method target, String cmdName) {
+ return null;
+ }
+
+ /**
+ * If applicable, get the coroutine context to use in suspend functions (Kotlin only).
+ * The return type is object to avoid depending on the kotlin runtime.
+ *
+ * @param context the context of execution
+ * @param target the method of the command
+ * @param cmdName the name of the command
+ * @return the coroutine context
+ */
+ default Object getCoroutineContext(ExecutionContext context, Method target, String cmdName) {
+ return null;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java
index bdcb568..d0681b1 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ICommandReceiver.java
@@ -1,5 +1,5 @@
-package io.dico.dicore.command.registration.reflect;
-
-public interface ICommandReceiver {
-
-}
+package io.dico.dicore.command.registration.reflect;
+
+public interface ICommandReceiver {
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCallFlags.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCallFlags.java
new file mode 100644
index 0000000..fa198c2
--- /dev/null
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCallFlags.java
@@ -0,0 +1,186 @@
+package io.dico.dicore.command.registration.reflect;
+
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.ExecutionContext;
+import io.dico.dicore.exceptions.checkedfunctions.CheckedSupplier;
+
+/**
+ * Call flags store which extra parameters the target function expects on top of command parameters.
+ * All 4 possible extra parameters are listed below.
+ * <p>
+ * Extra parameters are ordered by the bit that represents them in the call flags.
+ * They can either be leading or trailing the command's parameters.
+ */
+public class ReflectiveCallFlags {
+
+ /**
+ * Receiver ({@code this} in some kotlin functions - always first parameter)
+ *
+ * @see ICommandInterceptor#getReceiver(io.dico.dicore.command.ExecutionContext, java.lang.reflect.Method, String)
+ */
+ public static final int RECEIVER_BIT = 1 << 0;
+
+ /**
+ * CommandSender
+ *
+ * @see org.bukkit.command.CommandSender
+ */
+ public static final int SENDER_BIT = 1 << 1;
+
+ /**
+ * ExecutionContext
+ *
+ * @see io.dico.dicore.command.ExecutionContext
+ */
+ public static final int CONTEXT_BIT = 1 << 2;
+
+ /**
+ * Continuation (trailing parameters of kotlin suspended functions)
+ *
+ * @see kotlin.coroutines.Continuation
+ */
+ public static final int CONTINUATION_BIT = 1 << 3;
+
+ /**
+ * Mask of extra parameters that trail the command's parameters, instead of leading.
+ */
+ public static final int TRAILING_MASK = CONTINUATION_BIT;
+
+ /**
+ * Check if the call arg is trailing the command's parameters.
+ *
+ * @param bit the bit used for the call flag
+ * @return true if the call arg is trailing the command's parameters
+ */
+ public static boolean isTrailingCallArg(int bit) {
+ return (bit & TRAILING_MASK) != 0;
+ }
+
+ /**
+ * Number of call arguments leading the command parameters.
+ *
+ * @param flags the call flags
+ * @return the number of call arguments leading the command parameters
+ */
+ public static int getLeadingCallArgNum(int flags) {
+ return Integer.bitCount(flags & ~TRAILING_MASK);
+ }
+
+ /**
+ * Number of call arguments trailing the command parameters.
+ *
+ * @param flags the call flags
+ * @return the number of call arguments trailing the command parameters
+ */
+ public static int getTrailingCallArgNum(int flags) {
+ return Integer.bitCount(flags & TRAILING_MASK);
+ }
+
+ /**
+ * Check if the flags contain the call arg.
+ *
+ * @param flags the call flags
+ * @param bit the bit used for the call flag
+ * @return true if the flags contain the call arg
+ */
+ public static boolean hasCallArg(int flags, int bit) {
+ return (flags & bit) != 0;
+ }
+
+ /**
+ * Get the index used for the call arg when calling the reflective function
+ *
+ * @param flags the call flags
+ * @param bit the bit used for the call flag
+ * @param cmdParameterNum the number of parameters of the command
+ * @return the index used for the call arg
+ */
+ public static int getCallArgIndex(int flags, int bit, int cmdParameterNum) {
+ if ((bit & TRAILING_MASK) == 0) {
+ // Leading.
+
+ int preceding = precedingMaskFrom(bit);
+ int mask = flags & precedingMaskFrom(bit) & ~TRAILING_MASK;
+
+ // Count the number of present call args that are leading and precede the given bit
+ return Integer.bitCount(flags & precedingMaskFrom(bit) & ~TRAILING_MASK);
+ } else {
+ // Trailing.
+
+ // Count the number of present call args that are leading
+ // plus the number of present call args that are trailing and precede the given bit
+ // plus the command's parameters
+
+ return Integer.bitCount(flags & ~TRAILING_MASK)
+ + Integer.bitCount(flags & precedingMaskFrom(bit) & TRAILING_MASK)
+ + cmdParameterNum;
+ }
+ }
+
+ /**
+ * Get the mask for all bits trailing the given fromBit
+ *
+ * <p>
+ * For example, if the bit is 00010000
+ * This function returns 00001111
+ * <p>
+ *
+ * @param fromBit number with the bit set there the ones should stop.
+ * @return the mask for all bits trailing the given fromBit
+ */
+ private static int precedingMaskFrom(int fromBit) {
+ int trailingZeros = Integer.numberOfTrailingZeros(fromBit);
+ if (trailingZeros == 0) return 0;
+ return -1 >>> -trailingZeros;
+ }
+
+ /**
+ * Get the object array used to call the function.
+ *
+ * @param callFlags the call flags
+ * @param context the context
+ * @param parameterOrder the order of parameters in the function
+ * @param receiverFunction the function that will create the receiver for this call, if applicable
+ * @return the call args
+ */
+ public static Object[] getCallArgs(
+ int callFlags,
+ ExecutionContext context,
+ String[] parameterOrder,
+ CheckedSupplier<Object, CommandException> receiverFunction
+ ) throws CommandException {
+ int leadingParameterNum = getLeadingCallArgNum(callFlags);
+ int cmdParameterNum = parameterOrder.length;
+ int trailingParameterNum = getTrailingCallArgNum(callFlags);
+
+ Object[] result = new Object[leadingParameterNum + cmdParameterNum + trailingParameterNum];
+
+ if (hasCallArg(callFlags, RECEIVER_BIT)) {
+ int index = getCallArgIndex(callFlags, RECEIVER_BIT, cmdParameterNum);
+ result[index] = receiverFunction.get();
+ }
+
+ if (hasCallArg(callFlags, SENDER_BIT)) {
+ int index = getCallArgIndex(callFlags, SENDER_BIT, cmdParameterNum);
+ result[index] = context.getSender();
+ }
+
+ if (hasCallArg(callFlags, CONTEXT_BIT)) {
+ int index = getCallArgIndex(callFlags, CONTEXT_BIT, cmdParameterNum);
+ result[index] = context;
+ }
+
+ if (hasCallArg(callFlags, CONTINUATION_BIT)) {
+ int index = getCallArgIndex(callFlags, CONTINUATION_BIT, cmdParameterNum);
+ result[index] = null; // filled in later.
+ }
+
+ for (int i = 0; i < parameterOrder.length; i++) {
+ String parameterName = parameterOrder[i];
+ result[leadingParameterNum + i] = context.get(parameterName);
+ }
+
+ return result;
+ }
+
+}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
index 2d7c333..f4ddc70 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveCommand.java
@@ -4,6 +4,8 @@ import io.dico.dicore.command.*;
import io.dico.dicore.command.annotation.Cmd;
import io.dico.dicore.command.annotation.GenerateCommands;
import io.dico.dicore.command.parameter.type.IParameterTypeSelector;
+import io.dico.dicore.exceptions.checkedfunctions.CheckedSupplier;
+import kotlin.coroutines.CoroutineContext;
import org.bukkit.command.CommandSender;
import java.lang.reflect.InvocationTargetException;
@@ -11,14 +13,11 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public final class ReflectiveCommand extends Command {
- private static final int continuationMask = 1 << 3;
private final Cmd cmdAnnotation;
private final Method method;
private final Object instance;
private String[] parameterOrder;
-
- // hasContinuation | hasContext | hasSender | hasReceiver
- private final int flags;
+ private final int callFlags;
ReflectiveCommand(IParameterTypeSelector selector, Method method, Object instance) throws CommandParseException {
if (!method.isAnnotationPresent(Cmd.class)) {
@@ -48,7 +47,7 @@ public final class ReflectiveCommand extends Command {
this.method = method;
this.instance = instance;
- this.flags = ReflectiveRegistration.parseCommandAttributes(selector, method, this, parameters);
+ this.callFlags = ReflectiveRegistration.parseCommandAttributes(selector, method, this, parameters);
}
public Method getMethod() {
@@ -59,12 +58,22 @@ public final class ReflectiveCommand extends Command {
return instance;
}
- public String getCmdName() { return cmdAnnotation.value(); }
+ public String getCmdName() {
+ return cmdAnnotation.value();
+ }
+
+ public int getCallFlags() {
+ return callFlags;
+ }
void setParameterOrder(String[] parameterOrder) {
this.parameterOrder = parameterOrder;
}
+ public int getParameterNum() {
+ return parameterOrder.length;
+ }
+
ICommandAddress getAddress() {
ChildCommandAddress result = new ChildCommandAddress();
result.setCommand(this);
@@ -86,54 +95,24 @@ public final class ReflectiveCommand extends Command {
@Override
public String execute(CommandSender sender, ExecutionContext context) throws CommandException {
- String[] parameterOrder = this.parameterOrder;
- int extraArgumentCount = Integer.bitCount(flags);
- int parameterStartIndex = Integer.bitCount(flags & ~continuationMask);
-
- Object[] args = new Object[parameterOrder.length + extraArgumentCount];
- int i = 0;
-
- int mask = 1;
- if ((flags & mask) != 0) {
- // Has receiver
+ CheckedSupplier<Object, CommandException> receiverFunction = () -> {
try {
- args[i++] = ((ICommandInterceptor) instance).getReceiver(context, method, getCmdName());
+ return ((ICommandInterceptor) instance).getReceiver(context, method, getCmdName());
} catch (Exception ex) {
handleException(ex);
return null; // unreachable
}
- }
+ };
- mask <<= 1;
- if ((flags & mask) != 0) {
- // Has sender
- args[i++] = sender;
- }
-
- mask <<= 1;
- if ((flags & mask) != 0) {
- // Has context
- args[i++] = context;
- }
-
- mask <<= 1;
- if ((flags & mask) != 0) {
- // Has continuation
-
- extraArgumentCount--;
- }
-
- for (int n = args.length; i < n; i++) {
- args[i] = context.get(parameterOrder[i - extraArgumentCount]);
- }
+ Object[] callArgs = ReflectiveCallFlags.getCallArgs(callFlags, context, parameterOrder, receiverFunction);
- if ((flags & mask) != 0) {
- // Since it has continuation, call as coroutine
- return callAsCoroutine(context, args);
+ if (ReflectiveCallFlags.hasCallArg(callFlags, ReflectiveCallFlags.CONTINUATION_BIT)) {
+ // If it has a continuation, call as coroutine
+ return callAsCoroutine(context, callArgs);
}
- return callSynchronously(args);
+ return callSynchronously(callArgs);
}
private boolean isSuspendFunction() {
@@ -180,8 +159,11 @@ public final class ReflectiveCommand extends Command {
throw new CommandException("An internal error occurred while executing this command.", ex);
}
- private String callAsCoroutine(ExecutionContext context, Object[] args) {
- return KotlinReflectiveRegistrationKt.callAsCoroutine(this, (ICommandInterceptor) instance, context, args);
+ private String callAsCoroutine(ExecutionContext executionContext, Object[] args) throws CommandException {
+ ICommandInterceptor factory = (ICommandInterceptor) instance;
+ CoroutineContext coroutineContext = (CoroutineContext) factory.getCoroutineContext(executionContext, method, getCmdName());
+ int continuationIndex = ReflectiveCallFlags.getCallArgIndex(callFlags, ReflectiveCallFlags.CONTINUATION_BIT, parameterOrder.length);
+ return KotlinReflectiveRegistrationKt.callCommandAsCoroutine(executionContext, coroutineContext, continuationIndex, method, instance, args);
}
}
diff --git a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
index 6b1965d..ddd5420 100644
--- a/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
+++ b/dicore3/command/src/main/java/io/dico/dicore/command/registration/reflect/ReflectiveRegistration.java
@@ -22,6 +22,8 @@ import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
+import static io.dico.dicore.command.registration.reflect.ReflectiveCallFlags.*;
+
/**
* Takes care of turning a reflection {@link Method} into a command and more.
*/
@@ -196,47 +198,43 @@ public class ReflectiveRegistration {
return new ReflectiveCommand(selector, method, instance).getAddress();
}
- static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command, java.lang.reflect.Parameter[] parameters) throws CommandParseException {
+ static int parseCommandAttributes(IParameterTypeSelector selector, Method method, ReflectiveCommand command, java.lang.reflect.Parameter[] callParameters) throws CommandParseException {
ParameterList list = command.getParameterList();
- boolean hasReceiverParameter = false;
- boolean hasSenderParameter = false;
- boolean hasContextParameter = false;
- boolean hasContinuationParameter = false;
-
- int start = 0;
- int end = parameters.length;
-
Class<?> senderParameterType = null;
+ int flags = 0;
+ int start = 0;
+ int end = callParameters.length;
- if (parameters.length > start
+ if (callParameters.length > start
&& command.getInstance() instanceof ICommandInterceptor
- && ICommandReceiver.class.isAssignableFrom(parameters[start].getType())) {
- hasReceiverParameter = true;
- start++;
+ && ICommandReceiver.class.isAssignableFrom(callParameters[start].getType())) {
+ flags |= RECEIVER_BIT;
+ ++start;
}
- if (parameters.length > start && CommandSender.class.isAssignableFrom(senderParameterType = parameters[start].getType())) {
- hasSenderParameter = true;
- start++;
+ if (callParameters.length > start && CommandSender.class.isAssignableFrom(senderParameterType = callParameters[start].getType())) {
+ flags |= SENDER_BIT;
+ ++start;
}
- if (parameters.length > start && parameters[start].getType() == ExecutionContext.class) {
- hasContextParameter = true;
- start++;
+ if (callParameters.length > start && callParameters[start].getType() == ExecutionContext.class) {
+ flags |= CONTEXT_BIT;
+ ++start;
}
- if (parameters.length > start && parameters[end - 1].getType().getName().equals("kotlin.coroutines.Continuation")) {
- hasContinuationParameter = true;
- end--;
+ if (callParameters.length > start && callParameters[end - 1].getType().getName().equals("kotlin.coroutines.Continuation")) {
+ flags |= CONTINUATION_BIT;
+ --end;
}
- String[] parameterNames = lookupParameterNames(method, parameters, start);
+ String[] parameterNames = lookupParameterNames(method, callParameters, start);
for (int i = start, n = end; i < n; i++) {
- Parameter<?, ?> parameter = parseParameter(selector, method, parameters[i], parameterNames[i - start]);
+ Parameter<?, ?> parameter = parseParameter(selector, method, callParameters[i], parameterNames[i - start]);
list.addParameter(parameter);
}
- command.setParameterOrder(hasContinuationParameter ? Arrays.copyOfRange(parameterNames, 0, parameterNames.length - 1) : parameterNames);
+
+ command.setParameterOrder(hasCallArg(flags, CONTINUATION_BIT) ? Arrays.copyOfRange(parameterNames, 0, parameterNames.length - 1) : parameterNames);
RequirePermissions cmdPermissions = method.getAnnotation(RequirePermissions.class);
if (cmdPermissions != null) {
@@ -277,6 +275,7 @@ public class ReflectiveRegistration {
command.setDescription();
}
+ boolean hasSenderParameter = hasCallArg(flags, SENDER_BIT);
if (hasSenderParameter && Player.class.isAssignableFrom(senderParameterType)) {
command.addContextFilter(IContextFilter.PLAYER_ONLY);
} else if (hasSenderParameter && ConsoleCommandSender.class.isAssignableFrom(senderParameterType)) {
@@ -287,17 +286,9 @@ public class ReflectiveRegistration {
command.addContextFilter(IContextFilter.CONSOLE_ONLY);
}
- list.setRepeatFinalParameter(parameters.length > start && parameters[parameters.length - 1].isVarArgs());
+ list.setRepeatFinalParameter(callParameters.length > start && callParameters[callParameters.length - 1].isVarArgs());
list.setFinalParameterMayBeFlag(true);
- int flags = 0;
- if (hasContinuationParameter) flags |= 1;
- flags <<= 1;
- if (hasContextParameter) flags |= 1;
- flags <<= 1;
- if (hasSenderParameter) flags |= 1;
- flags <<= 1;
- if (hasReceiverParameter) flags |= 1;
return flags;
}
diff --git a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
index 2ef6e39..273cadc 100644
--- a/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
+++ b/dicore3/command/src/main/kotlin/io/dico/dicore/command/registration/reflect/KotlinReflectiveRegistration.kt
@@ -17,20 +17,23 @@ fun isSuspendFunction(method: Method): Boolean {
return func.isSuspend
}
-fun callAsCoroutine(
- command: ReflectiveCommand,
- factory: ICommandInterceptor,
- context: ExecutionContext,
+@Throws(CommandException::class)
+fun callCommandAsCoroutine(
+ executionContext: ExecutionContext,
+ coroutineContext: CoroutineContext,
+ continuationIndex: Int,
+ method: Method,
+ instance: Any?,
args: Array<Any?>
): String? {
- val coroutineContext = factory.getCoroutineContext(context, command.method, command.cmdName) as CoroutineContext
// UNDISPATCHED causes the handler to run until the first suspension point on the current thread,
// meaning command handlers that don't have suspension points will run completely synchronously.
// Tasks that take time to compute should suspend the coroutine and resume on another thread.
val job = GlobalScope.async(context = coroutineContext, start = UNDISPATCHED) {
suspendCoroutineUninterceptedOrReturn<Any?> { cont ->
- command.method.invoke(command.instance, *args, cont.intercepted())
+ args[continuationIndex] = cont.intercepted()
+ method.invoke(instance, *args)
}
}
@@ -39,12 +42,12 @@ fun callAsCoroutine(
}
job.invokeOnCompletion {
- val chatHandler = context.address.chatHandler
+ val chatHandler = executionContext.address.chatHandler
try {
val result = job.getResult()
- chatHandler.sendMessage(context.sender, EMessageType.RESULT, result)
+ chatHandler.sendMessage(executionContext.sender, EMessageType.RESULT, result)
} catch (ex: Throwable) {
- chatHandler.handleException(context.sender, context, ex)
+ chatHandler.handleException(executionContext.sender, executionContext, ex)
}
}
diff --git a/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java b/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java
index 1cd4e23..c31b96f 100644
--- a/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java
+++ b/dicore3/command/src/test/java/io/dico/dicore/command/example/ParameterInfoObjectExample.java
@@ -1,73 +1,73 @@
-package io.dico.dicore.command.example;
-
-import io.dico.dicore.command.CommandBuilder;
-import io.dico.dicore.command.CommandException;
-import io.dico.dicore.command.Validate;
-import io.dico.dicore.command.annotation.Cmd;
-import io.dico.dicore.command.parameter.ArgumentBuffer;
-import io.dico.dicore.command.parameter.Parameter;
-import io.dico.dicore.command.parameter.type.ParameterConfig;
-import io.dico.dicore.command.parameter.type.ParameterType;
-import org.bukkit.command.CommandSender;
-
-public class ParameterInfoObjectExample {
-
- private @interface ParentPermission {
- String value();
- }
-
- static class MyInfoObject {
- public static final ParameterConfig<ParentPermission, MyInfoObject> config = new ParameterConfig<ParentPermission, MyInfoObject>() {
- @Override
- protected MyInfoObject toParameterInfo(ParentPermission annotation) {
- return new MyInfoObject(annotation.value());
- }
- };
-
- private String permissionParent;
-
- MyInfoObject(String permissionParent) {
- this.permissionParent = permissionParent;
- }
-
- public String getPermissionParent() {
- return permissionParent;
- }
- }
-
- static class MyParameterType extends ParameterType<String, MyInfoObject> {
-
- public MyParameterType() {
- super(String.class, MyInfoObject.config);
- }
-
- @Override
- public String parse(Parameter<String, MyInfoObject> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
- String value = buffer.next();
-
- MyInfoObject mio = parameter.getParamInfo();
- if (mio != null) {
- String permission = mio.permissionParent + "." + value;
- Validate.isAuthorized(sender, permission);
- }
-
- return value;
- }
- }
-
- static class MyCommands {
-
- @Cmd("test")
- Object cmdTest(@ParentPermission("test.permission") String value) {
- return "You have permission to use the argument '" + value + "'!";
- }
-
- }
-
- static void main(String[] args) {
- new CommandBuilder()
- .addParameterType(false, new MyParameterType())
- .registerCommands(new MyCommands());
- }
-
-}
+package io.dico.dicore.command.example;
+
+import io.dico.dicore.command.CommandBuilder;
+import io.dico.dicore.command.CommandException;
+import io.dico.dicore.command.Validate;
+import io.dico.dicore.command.annotation.Cmd;
+import io.dico.dicore.command.parameter.ArgumentBuffer;
+import io.dico.dicore.command.parameter.Parameter;
+import io.dico.dicore.command.parameter.type.ParameterConfig;
+import io.dico.dicore.command.parameter.type.ParameterType;
+import org.bukkit.command.CommandSender;
+
+public class ParameterInfoObjectExample {
+
+ private @interface ParentPermission {
+ String value();
+ }
+
+ static class MyInfoObject {
+ public static final ParameterConfig<ParentPermission, MyInfoObject> config = new ParameterConfig<ParentPermission, MyInfoObject>() {
+ @Override
+ protected MyInfoObject toParameterInfo(ParentPermission annotation) {
+ return new MyInfoObject(annotation.value());
+ }
+ };
+
+ private String permissionParent;
+
+ MyInfoObject(String permissionParent) {
+ this.permissionParent = permissionParent;
+ }
+
+ public String getPermissionParent() {
+ return permissionParent;
+ }
+ }
+
+ static class MyParameterType extends ParameterType<String, MyInfoObject> {
+
+ public MyParameterType() {
+ super(String.class, MyInfoObject.config);
+ }
+
+ @Override
+ public String parse(Parameter<String, MyInfoObject> parameter, CommandSender sender, ArgumentBuffer buffer) throws CommandException {
+ String value = buffer.next();
+
+ MyInfoObject mio = parameter.getParamInfo();
+ if (mio != null) {
+ String permission = mio.permissionParent + "." + value;
+ Validate.isAuthorized(sender, permission);
+ }
+
+ return value;
+ }
+ }
+
+ static class MyCommands {
+
+ @Cmd("test")
+ Object cmdTest(@ParentPermission("test.permission") String value) {
+ return "You have permission to use the argument '" + value + "'!";
+ }
+
+ }
+
+ static void main(String[] args) {
+ new CommandBuilder()
+ .addParameterType(false, new MyParameterType())
+ .registerCommands(new MyCommands());
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/BitModifier.java b/dicore3/core/src/main/java/io/dico/dicore/BitModifier.java
index e4facb1..ae25123 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/BitModifier.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/BitModifier.java
@@ -1,182 +1,182 @@
-package io.dico.dicore;
-
-public interface BitModifier {
-
- long mask();
-
- long get(long x);
-
- long set(long x, long value);
-
- default int lowerBound() {
- return Long.numberOfTrailingZeros(mask());
- }
-
- default int upperBound() {
- return 64 - Long.numberOfLeadingZeros(mask());
- }
-
- default int bitCount() {
- return Long.bitCount(mask());
- }
-
- default boolean getBoolean(long x) {
- return get(x) == 1;
- }
-
- default long setBoolean(long x, boolean value) {
- return set(x, value ? 1 : 0);
- }
-
- default int getInt(long x) {
- return (int) (get(x) & 0xFFFFFFFFL);
- }
-
- default long setInt(long x, int value) {
- return set(x, value & 0xFFFFFFFFL);
- }
-
- default short getShort(long x) {
- return (short) (get(x) & 0xFFFFL);
- }
-
- default long setShort(long x, int value) {
- return set(x, value & 0xFFFFL);
- }
-
- default byte getByte(long x) {
- return (byte) (get(x) & 0xFFL);
- }
-
- default long setByte(long x, int value) {
- return set(x, value & 0xFFL);
- }
-
- final class OfSingle implements BitModifier {
- private final long mask;
-
- public OfSingle(int bit) {
- if (bit < 0 || bit >= 64) {
- throw new IndexOutOfBoundsException();
- }
- this.mask = 1L << bit;
- }
-
- @Override
- public int bitCount() {
- return 1;
- }
-
- @Override
- public long mask() {
- return mask;
- }
-
- public boolean getBoolean(long x) {
- return (x & mask) != 0;
- }
-
- public long setBoolean(long x, boolean value) {
- return value ? (x | mask) : (x & ~mask);
- }
-
- @Override
- public long get(long x) {
- return getBoolean(x) ? 1 : 0;
- }
-
- @Override
- public long set(long x, long value) {
- if (value < 0 || value > 1) {
- throw new IllegalArgumentException();
- }
- return setBoolean(x, value == 1);
- }
- }
-
- final class OfMultiple implements BitModifier {
- private final int lowerBound;
- private final int bitCount;
- private final long mask;
-
- public OfMultiple(int lowerBound, int bitCount) {
- int upperBound = lowerBound + bitCount;
- if (lowerBound < 0 || lowerBound >= 64 || upperBound < 1 || upperBound > 64 || upperBound < lowerBound) {
- throw new IndexOutOfBoundsException();
- }
- this.lowerBound = lowerBound;
- this.bitCount = bitCount;
- this.mask = (Long.MIN_VALUE >> (bitCount - 1)) >>> (64 - bitCount - lowerBound);
- }
-
- @Override
- public int lowerBound() {
- return lowerBound;
- }
-
- @Override
- public int bitCount() {
- return bitCount;
- }
-
- @Override
- public int upperBound() {
- return lowerBound + bitCount;
- }
-
- @Override
- public long mask() {
- return mask;
- }
-
- @Override
- public long get(long x) {
- return (x & mask) >>> lowerBound;
- }
-
- @Override
- public long set(long x, long value) {
- return (x & ~mask) | ((value << lowerBound) & mask);
- }
-
- }
-
- class Builder {
- int currentIndex;
-
- public int getCurrentIndex() {
- return currentIndex;
- }
-
- public int getRemaining() {
- return 64 - currentIndex;
- }
-
- public OfSingle single() {
- checkAvailable(1);
- return new OfSingle(currentIndex++);
- }
-
- public BitModifier size(int size) {
- if (size == 1) {
- return single();
- }
- checkAvailable(size);
- BitModifier result = new OfMultiple(currentIndex, size);
- currentIndex += size;
- return result;
- }
-
- public BitModifier remaining() {
- return size(getRemaining());
- }
-
- private void checkAvailable(int size) {
- if (size <= 0 || currentIndex + size > 64) {
- throw new IllegalStateException("Exceeding bit count of a long");
- }
- }
-
- }
-
-}
+package io.dico.dicore;
+
+public interface BitModifier {
+
+ long mask();
+
+ long get(long x);
+
+ long set(long x, long value);
+
+ default int lowerBound() {
+ return Long.numberOfTrailingZeros(mask());
+ }
+
+ default int upperBound() {
+ return 64 - Long.numberOfLeadingZeros(mask());
+ }
+
+ default int bitCount() {
+ return Long.bitCount(mask());
+ }
+
+ default boolean getBoolean(long x) {
+ return get(x) == 1;
+ }
+
+ default long setBoolean(long x, boolean value) {
+ return set(x, value ? 1 : 0);
+ }
+
+ default int getInt(long x) {
+ return (int) (get(x) & 0xFFFFFFFFL);
+ }
+
+ default long setInt(long x, int value) {
+ return set(x, value & 0xFFFFFFFFL);
+ }
+
+ default short getShort(long x) {
+ return (short) (get(x) & 0xFFFFL);
+ }
+
+ default long setShort(long x, int value) {
+ return set(x, value & 0xFFFFL);
+ }
+
+ default byte getByte(long x) {
+ return (byte) (get(x) & 0xFFL);
+ }
+
+ default long setByte(long x, int value) {
+ return set(x, value & 0xFFL);
+ }
+
+ final class OfSingle implements BitModifier {
+ private final long mask;
+
+ public OfSingle(int bit) {
+ if (bit < 0 || bit >= 64) {
+ throw new IndexOutOfBoundsException();
+ }
+ this.mask = 1L << bit;
+ }
+
+ @Override
+ public int bitCount() {
+ return 1;
+ }
+
+ @Override
+ public long mask() {
+ return mask;
+ }
+
+ public boolean getBoolean(long x) {
+ return (x & mask) != 0;
+ }
+
+ public long setBoolean(long x, boolean value) {
+ return value ? (x | mask) : (x & ~mask);
+ }
+
+ @Override
+ public long get(long x) {
+ return getBoolean(x) ? 1 : 0;
+ }
+
+ @Override
+ public long set(long x, long value) {
+ if (value < 0 || value > 1) {
+ throw new IllegalArgumentException();
+ }
+ return setBoolean(x, value == 1);
+ }
+ }
+
+ final class OfMultiple implements BitModifier {
+ private final int lowerBound;
+ private final int bitCount;
+ private final long mask;
+
+ public OfMultiple(int lowerBound, int bitCount) {
+ int upperBound = lowerBound + bitCount;
+ if (lowerBound < 0 || lowerBound >= 64 || upperBound < 1 || upperBound > 64 || upperBound < lowerBound) {
+ throw new IndexOutOfBoundsException();
+ }
+ this.lowerBound = lowerBound;
+ this.bitCount = bitCount;
+ this.mask = (Long.MIN_VALUE >> (bitCount - 1)) >>> (64 - bitCount - lowerBound);
+ }
+
+ @Override
+ public int lowerBound() {
+ return lowerBound;
+ }
+
+ @Override
+ public int bitCount() {
+ return bitCount;
+ }
+
+ @Override
+ public int upperBound() {
+ return lowerBound + bitCount;
+ }
+
+ @Override
+ public long mask() {
+ return mask;
+ }
+
+ @Override
+ public long get(long x) {
+ return (x & mask) >>> lowerBound;
+ }
+
+ @Override
+ public long set(long x, long value) {
+ return (x & ~mask) | ((value << lowerBound) & mask);
+ }
+
+ }
+
+ class Builder {
+ int currentIndex;
+
+ public int getCurrentIndex() {
+ return currentIndex;
+ }
+
+ public int getRemaining() {
+ return 64 - currentIndex;
+ }
+
+ public OfSingle single() {
+ checkAvailable(1);
+ return new OfSingle(currentIndex++);
+ }
+
+ public BitModifier size(int size) {
+ if (size == 1) {
+ return single();
+ }
+ checkAvailable(size);
+ BitModifier result = new OfMultiple(currentIndex, size);
+ currentIndex += size;
+ return result;
+ }
+
+ public BitModifier remaining() {
+ return size(getRemaining());
+ }
+
+ private void checkAvailable(int size) {
+ if (size <= 0 || currentIndex + size > 64) {
+ throw new IllegalStateException("Exceeding bit count of a long");
+ }
+ }
+
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/Formatting.java b/dicore3/core/src/main/java/io/dico/dicore/Formatting.java
index 9fdfe0e..40afb9b 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/Formatting.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/Formatting.java
@@ -1,295 +1,295 @@
-/*
- * Copyright (c) 2017 ProjectOreville
- *
- * All rights reserved.
- *
- * Author(s):
- * Dico Karssiens
- */
-
-package io.dico.dicore;
-
-import org.jetbrains.annotations.NotNull;
-
-public final class Formatting implements CharSequence {
- public static final char FORMAT_CHAR = '\u00a7';
- private static final String CACHED_CHARS = "0123456789abcdefklmnor";
- private static final Formatting[] singleCharInstances = new Formatting[CACHED_CHARS.length()];
-
- @NotNull
- public static final Formatting
- BLACK = from('0'),
- DARK_BLUE = from('1'),
- DARL_GREEN = from('2'),
- CYAN = from('3'),
- DARK_RED = from('4'),
- PURPLE = from('5'),
- ORANGE = from('6'),
- GRAY = from('7'),
- DARK_GRAY = from('8'),
- BLUE = from('9'),
- GREEN = from('a'),
- AQUA = from('b'),
- RED = from('c'),
- PINK = from('d'),
- YELLOW = from('e'),
- WHITE = from('f'),
- BOLD = from('l'),
- STRIKETHROUGH = from('m'),
- UNDERLINE = from('n'),
- ITALIC = from('o'),
- MAGIC = from('k'),
- RESET = from('r'),
- EMPTY = from('\0');
-
- public static String stripAll(String value) {
- return stripAll(FORMAT_CHAR, value);
- }
-
- public static String stripAll(char alternateChar, String value) {
- int index = value.indexOf(alternateChar);
- int max;
- if (index == -1 || index == (max = value.length() - 1)) {
- return value;
- }
-
- StringBuilder result = new StringBuilder();
- int from = 0;
- do {
- if (isRecognizedChar(value.charAt(index + 1))) {
- result.append(value, from, index);
- from = index + 2;
- } else {
- result.append(value, from, from = index + 2);
- }
-
- index = value.indexOf(alternateChar, index + 1);
- } while (index != -1 && index != max && from <= max);
-
- if (from <= max) {
- result.append(value, from, value.length());
- }
- return result.toString();
- }
-
- public static String stripFirst(String value) {
- return stripFirst(FORMAT_CHAR, value);
- }
-
- public static String stripFirst(char alternateChar, String value) {
- int index = value.indexOf(alternateChar);
- int max;
- if (index == -1 || index == (max = value.length() - 1)) {
- return value;
- }
-
- StringBuilder result = new StringBuilder(value.length());
- int from = 0;
- if (isRecognizedChar(value.charAt(index + 1))) {
- result.append(value, from, index);
- from = index + 2;
- } else {
- result.append(value, from, from = index + 2);
- }
-
- if (from < max) {
- result.append(value, from, value.length());
- }
- return result.toString();
- }
-
- public static Formatting from(char c) {
- if (isRecognizedChar(c)) {
- c = Character.toLowerCase(c);
- int index = CACHED_CHARS.indexOf(c);
- if (index == -1) return EMPTY;
-
- Formatting res = singleCharInstances[index];
- if (res == null) {
- singleCharInstances[index] = res = new Formatting(c);
- }
- return res;
- }
- return EMPTY;
- }
-
- public static Formatting from(String chars) {
- return chars.length() == 1 ? from(chars.charAt(0)) : getFormats(chars, '\0');
- }
-
- public static Formatting getFormats(String input) {
- return getFormats(input, FORMAT_CHAR);
- }
-
- public static Formatting getFormats(String input, char formatChar) {
- return getFormats(input, 0, input.length(), formatChar);
- }
-
- public static Formatting getFormats(String input, int start, int end, char formatChar) {
- if ((start < 0) || (start > end) || (end > input.length())) {
- throw new IndexOutOfBoundsException("start " + start + ", end " + end + ", input.length() " + input.length());
- }
-
- boolean needsFormatChar = formatChar != '\0';
- char[] formats = new char[6];
- // just make sure it's not the same as formatChar
- char previous = (char) (formatChar + 1);
-
- for (int i = start; i < end; i++) {
- char c = input.charAt(i);
-
- if (previous == formatChar || !needsFormatChar) {
- if (isColourChar(c) || isResetChar(c)) {
- formats = new char[6];
- formats[0] = Character.toLowerCase(c);
- } else if (isFormatChar(c)) {
- char format = Character.toLowerCase(c);
- for (int j = 0; j < 6; j++) {
- if (formats[j] == '\0') {
- formats[j] = format;
- break;
- } else if (formats[j] == format) {
- break;
- }
- }
- }
- }
-
- previous = c;
- }
-
- return formats[1] == '\0' ? from(formats[0]) : new Formatting(formats);
- }
-
- public static String translate(String input) {
- return translateChars('&', input);
- }
-
- public static String translateChars(char alternateChar, String input) {
- return translateFormat(alternateChar, FORMAT_CHAR, input);
- }
-
- public static String revert(String input) {
- return revertChars('&', input);
- }
-
- public static String revertChars(char alternateChar, String input) {
- return translateFormat(FORMAT_CHAR, alternateChar, input);
- }
-
- public static String translateFormat(char fromChar, char toChar, String input) {
- if (input == null) {
- return null;
- }
- int n = input.length();
- if (n < 2) {
- return input;
- }
- char[] result = null;
- char previous = input.charAt(0);
- for (int i = 1; i < n; i++) {
- char c = input.charAt(i);
- if (previous == fromChar && isRecognizedChar(c)) {
- if (result == null) {
- result = input.toCharArray();
- }
- result[i - 1] = toChar;
- }
- previous = c;
- }
- return result == null ? input : String.valueOf(result);
- }
-
- public static void translate(StringBuilder input) {
- translateChars('&', input);
- }
-
- public static void translateChars(char alternateChar, StringBuilder input) {
- translateFormat(alternateChar, FORMAT_CHAR, input);
- }
-
- public static void revert(StringBuilder input) {
- revertChars('&', input);
- }
-
- public static void revertChars(char alternateChar, StringBuilder input) {
- translateFormat(FORMAT_CHAR, alternateChar, input);
- }
-
- public static void translateFormat(char fromChar, char toChar, StringBuilder input) {
- if (input == null) {
- return;
- }
- int n = input.length();
- if (n < 2) {
- return;
- }
- char previous = input.charAt(0);
- for (int i = 1; i < n; i++) {
- char c = input.charAt(i);
- if (previous == fromChar && isRecognizedChar(c)) {
- input.setCharAt(i -1, toChar);
- }
- previous = c;
- }
- }
-
- private static boolean isRecognizedChar(char c) {
- return isColourChar(c) || isFormatChar(c) || isResetChar(c);
- }
-
- private static boolean isColourChar(char c) {
- return "0123456789abcdefABCDEF".indexOf(c) >= 0;
- }
-
- private static boolean isResetChar(char c) {
- return c == 'r' || c == 'R';
- }
-
- private static boolean isFormatChar(char c) {
- return "klmnoKLMNO".indexOf(c) >= 0;
- }
-
- private final String format;
-
- private Formatting(char[] formats) {
- StringBuilder format = new StringBuilder(12);
- for (char c : formats) {
- if (c != '\0') {
- format.append(FORMAT_CHAR).append(c);
- } else {
- break;
- }
- }
- this.format = format.toString();
- }
-
- private Formatting(char c) {
- this.format = (c != '\0') ? String.valueOf(new char[]{FORMAT_CHAR, c}) : "";
- }
-
- @Override
- public int length() {
- return format.length();
- }
-
- @Override
- public char charAt(int index) {
- return format.charAt(index);
- }
-
- @Override
- public String subSequence(int start, int end) {
- return format.substring(start, end);
- }
-
- @Override
- public String toString() {
- return format;
- }
-
- public String toString(char formatChar) {
- return format.replace(FORMAT_CHAR, formatChar);
- }
-
+/*
+ * Copyright (c) 2017 ProjectOreville
+ *
+ * All rights reserved.
+ *
+ * Author(s):
+ * Dico Karssiens
+ */
+
+package io.dico.dicore;
+
+import org.jetbrains.annotations.NotNull;
+
+public final class Formatting implements CharSequence {
+ public static final char FORMAT_CHAR = '\u00a7';
+ private static final String CACHED_CHARS = "0123456789abcdefklmnor";
+ private static final Formatting[] singleCharInstances = new Formatting[CACHED_CHARS.length()];
+
+ @NotNull
+ public static final Formatting
+ BLACK = from('0'),
+ DARK_BLUE = from('1'),
+ DARL_GREEN = from('2'),
+ CYAN = from('3'),
+ DARK_RED = from('4'),
+ PURPLE = from('5'),
+ ORANGE = from('6'),
+ GRAY = from('7'),
+ DARK_GRAY = from('8'),
+ BLUE = from('9'),
+ GREEN = from('a'),
+ AQUA = from('b'),
+ RED = from('c'),
+ PINK = from('d'),
+ YELLOW = from('e'),
+ WHITE = from('f'),
+ BOLD = from('l'),
+ STRIKETHROUGH = from('m'),
+ UNDERLINE = from('n'),
+ ITALIC = from('o'),
+ MAGIC = from('k'),
+ RESET = from('r'),
+ EMPTY = from('\0');
+
+ public static String stripAll(String value) {
+ return stripAll(FORMAT_CHAR, value);
+ }
+
+ public static String stripAll(char alternateChar, String value) {
+ int index = value.indexOf(alternateChar);
+ int max;
+ if (index == -1 || index == (max = value.length() - 1)) {
+ return value;
+ }
+
+ StringBuilder result = new StringBuilder();
+ int from = 0;
+ do {
+ if (isRecognizedChar(value.charAt(index + 1))) {
+ result.append(value, from, index);
+ from = index + 2;
+ } else {
+ result.append(value, from, from = index + 2);
+ }
+
+ index = value.indexOf(alternateChar, index + 1);
+ } while (index != -1 && index != max && from <= max);
+
+ if (from <= max) {
+ result.append(value, from, value.length());
+ }
+ return result.toString();
+ }
+
+ public static String stripFirst(String value) {
+ return stripFirst(FORMAT_CHAR, value);
+ }
+
+ public static String stripFirst(char alternateChar, String value) {
+ int index = value.indexOf(alternateChar);
+ int max;
+ if (index == -1 || index == (max = value.length() - 1)) {
+ return value;
+ }
+
+ StringBuilder result = new StringBuilder(value.length());
+ int from = 0;
+ if (isRecognizedChar(value.charAt(index + 1))) {
+ result.append(value, from, index);
+ from = index + 2;
+ } else {
+ result.append(value, from, from = index + 2);
+ }
+
+ if (from < max) {
+ result.append(value, from, value.length());
+ }
+ return result.toString();
+ }
+
+ public static Formatting from(char c) {
+ if (isRecognizedChar(c)) {
+ c = Character.toLowerCase(c);
+ int index = CACHED_CHARS.indexOf(c);
+ if (index == -1) return EMPTY;
+
+ Formatting res = singleCharInstances[index];
+ if (res == null) {
+ singleCharInstances[index] = res = new Formatting(c);
+ }
+ return res;
+ }
+ return EMPTY;
+ }
+
+ public static Formatting from(String chars) {
+ return chars.length() == 1 ? from(chars.charAt(0)) : getFormats(chars, '\0');
+ }
+
+ public static Formatting getFormats(String input) {
+ return getFormats(input, FORMAT_CHAR);
+ }
+
+ public static Formatting getFormats(String input, char formatChar) {
+ return getFormats(input, 0, input.length(), formatChar);
+ }
+
+ public static Formatting getFormats(String input, int start, int end, char formatChar) {
+ if ((start < 0) || (start > end) || (end > input.length())) {
+ throw new IndexOutOfBoundsException("start " + start + ", end " + end + ", input.length() " + input.length());
+ }
+
+ boolean needsFormatChar = formatChar != '\0';
+ char[] formats = new char[6];
+ // just make sure it's not the same as formatChar
+ char previous = (char) (formatChar + 1);
+
+ for (int i = start; i < end; i++) {
+ char c = input.charAt(i);
+
+ if (previous == formatChar || !needsFormatChar) {
+ if (isColourChar(c) || isResetChar(c)) {
+ formats = new char[6];
+ formats[0] = Character.toLowerCase(c);
+ } else if (isFormatChar(c)) {
+ char format = Character.toLowerCase(c);
+ for (int j = 0; j < 6; j++) {
+ if (formats[j] == '\0') {
+ formats[j] = format;
+ break;
+ } else if (formats[j] == format) {
+ break;
+ }
+ }
+ }
+ }
+
+ previous = c;
+ }
+
+ return formats[1] == '\0' ? from(formats[0]) : new Formatting(formats);
+ }
+
+ public static String translate(String input) {
+ return translateChars('&', input);
+ }
+
+ public static String translateChars(char alternateChar, String input) {
+ return translateFormat(alternateChar, FORMAT_CHAR, input);
+ }
+
+ public static String revert(String input) {
+ return revertChars('&', input);
+ }
+
+ public static String revertChars(char alternateChar, String input) {
+ return translateFormat(FORMAT_CHAR, alternateChar, input);
+ }
+
+ public static String translateFormat(char fromChar, char toChar, String input) {
+ if (input == null) {
+ return null;
+ }
+ int n = input.length();
+ if (n < 2) {
+ return input;
+ }
+ char[] result = null;
+ char previous = input.charAt(0);
+ for (int i = 1; i < n; i++) {
+ char c = input.charAt(i);
+ if (previous == fromChar && isRecognizedChar(c)) {
+ if (result == null) {
+ result = input.toCharArray();
+ }
+ result[i - 1] = toChar;
+ }
+ previous = c;
+ }
+ return result == null ? input : String.valueOf(result);
+ }
+
+ public static void translate(StringBuilder input) {
+ translateChars('&', input);
+ }
+
+ public static void translateChars(char alternateChar, StringBuilder input) {
+ translateFormat(alternateChar, FORMAT_CHAR, input);
+ }
+
+ public static void revert(StringBuilder input) {
+ revertChars('&', input);
+ }
+
+ public static void revertChars(char alternateChar, StringBuilder input) {
+ translateFormat(FORMAT_CHAR, alternateChar, input);
+ }
+
+ public static void translateFormat(char fromChar, char toChar, StringBuilder input) {
+ if (input == null) {
+ return;
+ }
+ int n = input.length();
+ if (n < 2) {
+ return;
+ }
+ char previous = input.charAt(0);
+ for (int i = 1; i < n; i++) {
+ char c = input.charAt(i);
+ if (previous == fromChar && isRecognizedChar(c)) {
+ input.setCharAt(i -1, toChar);
+ }
+ previous = c;
+ }
+ }
+
+ private static boolean isRecognizedChar(char c) {
+ return isColourChar(c) || isFormatChar(c) || isResetChar(c);
+ }
+
+ private static boolean isColourChar(char c) {
+ return "0123456789abcdefABCDEF".indexOf(c) >= 0;
+ }
+
+ private static boolean isResetChar(char c) {
+ return c == 'r' || c == 'R';
+ }
+
+ private static boolean isFormatChar(char c) {
+ return "klmnoKLMNO".indexOf(c) >= 0;
+ }
+
+ private final String format;
+
+ private Formatting(char[] formats) {
+ StringBuilder format = new StringBuilder(12);
+ for (char c : formats) {
+ if (c != '\0') {
+ format.append(FORMAT_CHAR).append(c);
+ } else {
+ break;
+ }
+ }
+ this.format = format.toString();
+ }
+
+ private Formatting(char c) {
+ this.format = (c != '\0') ? String.valueOf(new char[]{FORMAT_CHAR, c}) : "";
+ }
+
+ @Override
+ public int length() {
+ return format.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return format.charAt(index);
+ }
+
+ @Override
+ public String subSequence(int start, int end) {
+ return format.substring(start, end);
+ }
+
+ @Override
+ public String toString() {
+ return format;
+ }
+
+ public String toString(char formatChar) {
+ return format.replace(FORMAT_CHAR, formatChar);
+ }
+
} \ No newline at end of file
diff --git a/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java b/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
index b59979a..f92da6b 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/InterfaceChain.java
@@ -1,173 +1,173 @@
-package io.dico.dicore;
-
-/**
- * A chainable object
- * <p>
- * It is not possible to declare another upper bound for type parameter Subtype.
- * However, it is required that it also extends the type parameter Element.
- *
- * @param <Subtype> the interface that is chainable
- * @param <Element> the element of the chain, this is a supertype of the subtype
- */
-@SuppressWarnings("unchecked")
-public interface InterfaceChain<Element, Subtype extends InterfaceChain<Element, Subtype>> {
-
- /**
- * returns the empty InterfaceChain instance.
- *
- * @return the empty InterfaceChain instance
- */
- Subtype getEmptyInstance();
-
- /**
- * returns a InterfaceChain with the last added element detached.
- * <p>
- * if this InterfaceChain is the empty instance, the empty instance is returned.
- *
- * @return a InterfaceChain with the last added element detached
- * @implNote for the purpose of lambdas, the default implementation also returns the empty instance.
- */
- default Subtype withoutLastNode() {
- return getEmptyInstance();
- }
-
- /**
- * returns the element that was inserted as the last element
- * <p>
- * For instance, calling this method on the result of calling {@link InterfaceChain#withElement(Object)}
- * would return the given element.
- *
- * @return the element that was inserted as the last element
- * @implNote for the purpose of lambdas, the default implementation returns this object,
- * which is required to implement the Element type parameter.
- */
- default Element getDelegateOfLastNode() {
- //noinspection unchecked
- return (Element) this;
- }
-
- /**
- * @return The number of elements chained from this InterfaceChain.
- * @implNote for the purpose of lambdas, the default implementation returns 1.
- */
- default int getElementCount() {
- return 1;
- }
-
- /**
- * Get a new InterfaceChain that includes the given Element.
- * <p>
- * The default implementation of the Subtype should look like this:
- * <pre> {@code
- * if (element == null) {
- * return this;
- * }
- *
- * int count = getElementCount() + 1;
- * return new Subtype() {
- * \@Override
- * public void exampleElementMethod() {
- * try {
- * Subtype.this.exampleElementMethod();
- * } finally {
- * element.exampleElementMethod();
- * }
- * }
- *
- * \@Override
- * public Subtype withoutLastNode() {
- * return Subtype.this;
- * }
- *
- * \@Override
- * public Element getDelegateOfLastNode() {
- * return element;
- * }
- *
- * \@Override
- * public int getElementCount() {
- * return count;
- * }
- * };
- * }
- * </pre>
- *
- * @param element A new element to insert at the end of this InterfaceChain.
- * @return a new InterfaceChain that includes the given Element.
- */
- Subtype withElement(Element element);
-
- /**
- * Append each of the elements to this InterfaceChain
- *
- * @param elements the elements to append
- * @return a new InterfaceChain with the elements appended
- */
- default Subtype withElements(Element... elements) {
- Subtype result = (Subtype) this;
- for (Element element : elements) {
- result = result.withElement(element);
- }
- return result;
- }
-
- /*
- Example Subtypes implementation
-
- public class Subtypes {
-
- private Subtypes() {
-
- }
-
- private static final Subtype empty = new Subtype() {
- @Override
- public void exampleElementMethod() {
-
- }
-
- @Override
- public Subtype withElement(Element other) {
- return Subtypes.singleton(other);
- }
-
- @Override
- public int getElementCount() {
- return 0;
- }
-
- @Override
- public Element getDelegateOfLastNode() {
- return null;
- }
- };
-
- public static Subtype empty() {
- return empty;
- }
-
- public static Subtype singleton(Element element) {
- if (element instanceof Subtype) {
- return (Subtype) element;
- }
- if (element == null) {
- return empty();
- }
- return new Subtype() {
- @Override
- public void exampleElementMethod() {
- element.exampleElementMethod();
- }
-
- @Override
- public Element getDelegateOfLastNode() {
- return element;
- }
- };
- }
-
- }
-
- */
-
-}
+package io.dico.dicore;
+
+/**
+ * A chainable object
+ * <p>
+ * It is not possible to declare another upper bound for type parameter Subtype.
+ * However, it is required that it also extends the type parameter Element.
+ *
+ * @param <Subtype> the interface that is chainable
+ * @param <Element> the element of the chain, this is a supertype of the subtype
+ */
+@SuppressWarnings("unchecked")
+public interface InterfaceChain<Element, Subtype extends InterfaceChain<Element, Subtype>> {
+
+ /**
+ * returns the empty InterfaceChain instance.
+ *
+ * @return the empty InterfaceChain instance
+ */
+ Subtype getEmptyInstance();
+
+ /**
+ * returns a InterfaceChain with the last added element detached.
+ * <p>
+ * if this InterfaceChain is the empty instance, the empty instance is returned.
+ *
+ * @return a InterfaceChain with the last added element detached
+ * @implNote for the purpose of lambdas, the default implementation also returns the empty instance.
+ */
+ default Subtype withoutLastNode() {
+ return getEmptyInstance();
+ }
+
+ /**
+ * returns the element that was inserted as the last element
+ * <p>
+ * For instance, calling this method on the result of calling {@link InterfaceChain#withElement(Object)}
+ * would return the given element.
+ *
+ * @return the element that was inserted as the last element
+ * @implNote for the purpose of lambdas, the default implementation returns this object,
+ * which is required to implement the Element type parameter.
+ */
+ default Element getDelegateOfLastNode() {
+ //noinspection unchecked
+ return (Element) this;
+ }
+
+ /**
+ * @return The number of elements chained from this InterfaceChain.
+ * @implNote for the purpose of lambdas, the default implementation returns 1.
+ */
+ default int getElementCount() {
+ return 1;
+ }
+
+ /**
+ * Get a new InterfaceChain that includes the given Element.
+ * <p>
+ * The default implementation of the Subtype should look like this:
+ * <pre> {@code
+ * if (element == null) {
+ * return this;
+ * }
+ *
+ * int count = getElementCount() + 1;
+ * return new Subtype() {
+ * \@Override
+ * public void exampleElementMethod() {
+ * try {
+ * Subtype.this.exampleElementMethod();
+ * } finally {
+ * element.exampleElementMethod();
+ * }
+ * }
+ *
+ * \@Override
+ * public Subtype withoutLastNode() {
+ * return Subtype.this;
+ * }
+ *
+ * \@Override
+ * public Element getDelegateOfLastNode() {
+ * return element;
+ * }
+ *
+ * \@Override
+ * public int getElementCount() {
+ * return count;
+ * }
+ * };
+ * }
+ * </pre>
+ *
+ * @param element A new element to insert at the end of this InterfaceChain.
+ * @return a new InterfaceChain that includes the given Element.
+ */
+ Subtype withElement(Element element);
+
+ /**
+ * Append each of the elements to this InterfaceChain
+ *
+ * @param elements the elements to append
+ * @return a new InterfaceChain with the elements appended
+ */
+ default Subtype withElements(Element... elements) {
+ Subtype result = (Subtype) this;
+ for (Element element : elements) {
+ result = result.withElement(element);
+ }
+ return result;
+ }
+
+ /*
+ Example Subtypes implementation
+
+ public class Subtypes {
+
+ private Subtypes() {
+
+ }
+
+ private static final Subtype empty = new Subtype() {
+ @Override
+ public void exampleElementMethod() {
+
+ }
+
+ @Override
+ public Subtype withElement(Element other) {
+ return Subtypes.singleton(other);
+ }
+
+ @Override
+ public int getElementCount() {
+ return 0;
+ }
+
+ @Override
+ public Element getDelegateOfLastNode() {
+ return null;
+ }
+ };
+
+ public static Subtype empty() {
+ return empty;
+ }
+
+ public static Subtype singleton(Element element) {
+ if (element instanceof Subtype) {
+ return (Subtype) element;
+ }
+ if (element == null) {
+ return empty();
+ }
+ return new Subtype() {
+ @Override
+ public void exampleElementMethod() {
+ element.exampleElementMethod();
+ }
+
+ @Override
+ public Element getDelegateOfLastNode() {
+ return element;
+ }
+ };
+ }
+
+ }
+
+ */
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/InventoryEventUtil.java b/dicore3/core/src/main/java/io/dico/dicore/InventoryEventUtil.java
index 5c19848..3be2179 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/InventoryEventUtil.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/InventoryEventUtil.java
@@ -1,120 +1,120 @@
-package io.dico.dicore;
-
-import org.bukkit.Material;
-import org.bukkit.event.inventory.InventoryClickEvent;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.inventory.PlayerInventory;
-
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-public class InventoryEventUtil {
-
- private InventoryEventUtil() {
-
- }
-
- public static ItemStack getNewItem(InventoryClickEvent event) {
- Inventory clicked = event.getInventory();
- switch (event.getAction()) {
- case SWAP_WITH_CURSOR:
- case PLACE_ALL:
- return event.getCursor();
- case PICKUP_ALL:
- case HOTBAR_MOVE_AND_READD:
- case MOVE_TO_OTHER_INVENTORY:
- case DROP_ALL_SLOT:
- case COLLECT_TO_CURSOR:
- return null;
- case PICKUP_HALF:
- case PICKUP_SOME:
- ItemStack item = clicked.getItem(event.getSlot()).clone();
- item.setAmount(item.getAmount() / 2);
- return item;
- case PICKUP_ONE:
- case DROP_ONE_SLOT:
- item = clicked.getItem(event.getSlot()).clone();
- item.setAmount(Math.max(0, item.getAmount() - 1));
- return item;
- case PLACE_ONE:
- item = event.getView().getCursor().clone();
- item.setAmount(1);
- return item;
- case PLACE_SOME:
- item = event.getView().getCursor().clone();
- item.setAmount(item.getAmount() / 2);
- return item;
- case HOTBAR_SWAP:
- return event.getView().getBottomInventory().getItem(event.getHotbarButton());
- default:
- return clicked.getItem(event.getSlot());
- }
- }
-
-
- public static Map<Integer, ItemStack> deduceChangesIfItemAdded(Inventory inventory, ItemStack added, boolean computeNewItem) {
- int addedAmount = added.getAmount();
- Map<Integer, ItemStack> rv = Collections.emptyMap();
-
- for (int n = inventory.getSize(), i = 0; i < n; i++) {
- if (addedAmount <= 0) break;
-
- ItemStack current = inventory.getItem(i);
- if (current == null || current.getType() == Material.AIR || current.isSimilar(added)) {
- int count = current == null ? 0 : current.getAmount();
- int max = (current == null ? added : current).getType().getMaxStackSize();
- if (count < max) {
- int diff = max - count;
- if (diff > addedAmount) {
- diff = addedAmount;
- }
- addedAmount -= diff;
-
- if (rv.isEmpty()) rv = new LinkedHashMap<>();
-
- if (computeNewItem) {
- current = (current == null ? added : current).clone();
- current.setAmount(count + diff);
- rv.put(i, current);
- } else {
- rv.put(i, null);
- }
- }
- }
- }
-
- return rv;
- }
-
-
- public static ItemStack getNewHeldItemIfPickedUp(PlayerInventory inventory, ItemStack added) {
- int heldItemSlot = inventory.getHeldItemSlot();
- ItemStack heldItem = inventory.getItem(heldItemSlot);
-
- if (SpigotUtil.isItemPresent(heldItem) && !added.isSimilar(heldItem)) {
- return null;
- }
-
- int amt = added.getAmount();
- for (int i = 0; i < heldItemSlot; i++) {
- ItemStack item = inventory.getItem(i);
- if (!SpigotUtil.isItemPresent(item)) {
- return null;
- }
- if (item.isSimilar(item)) {
- amt -= Math.max(0, item.getMaxStackSize() - item.getAmount());
- if (amt <= 0) {
- return null;
- }
- }
- }
-
- added = added.clone();
- added.setAmount(amt + Math.max(0, heldItem == null ? 0 : heldItem.getAmount()));
- return added;
- }
-
-
-}
+package io.dico.dicore;
+
+import org.bukkit.Material;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.PlayerInventory;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+public class InventoryEventUtil {
+
+ private InventoryEventUtil() {
+
+ }
+
+ public static ItemStack getNewItem(InventoryClickEvent event) {
+ Inventory clicked = event.getInventory();
+ switch (event.getAction()) {
+ case SWAP_WITH_CURSOR:
+ case PLACE_ALL:
+ return event.getCursor();
+ case PICKUP_ALL:
+ case HOTBAR_MOVE_AND_READD:
+ case MOVE_TO_OTHER_INVENTORY:
+ case DROP_ALL_SLOT:
+ case COLLECT_TO_CURSOR:
+ return null;
+ case PICKUP_HALF:
+ case PICKUP_SOME:
+ ItemStack item = clicked.getItem(event.getSlot()).clone();
+ item.setAmount(item.getAmount() / 2);
+ return item;
+ case PICKUP_ONE:
+ case DROP_ONE_SLOT:
+ item = clicked.getItem(event.getSlot()).clone();
+ item.setAmount(Math.max(0, item.getAmount() - 1));
+ return item;
+ case PLACE_ONE:
+ item = event.getView().getCursor().clone();
+ item.setAmount(1);
+ return item;
+ case PLACE_SOME:
+ item = event.getView().getCursor().clone();
+ item.setAmount(item.getAmount() / 2);
+ return item;
+ case HOTBAR_SWAP:
+ return event.getView().getBottomInventory().getItem(event.getHotbarButton());
+ default:
+ return clicked.getItem(event.getSlot());
+ }
+ }
+
+
+ public static Map<Integer, ItemStack> deduceChangesIfItemAdded(Inventory inventory, ItemStack added, boolean computeNewItem) {
+ int addedAmount = added.getAmount();
+ Map<Integer, ItemStack> rv = Collections.emptyMap();
+
+ for (int n = inventory.getSize(), i = 0; i < n; i++) {
+ if (addedAmount <= 0) break;
+
+ ItemStack current = inventory.getItem(i);
+ if (current == null || current.getType() == Material.AIR || current.isSimilar(added)) {
+ int count = current == null ? 0 : current.getAmount();
+ int max = (current == null ? added : current).getType().getMaxStackSize();
+ if (count < max) {
+ int diff = max - count;
+ if (diff > addedAmount) {
+ diff = addedAmount;
+ }
+ addedAmount -= diff;
+
+ if (rv.isEmpty()) rv = new LinkedHashMap<>();
+
+ if (computeNewItem) {
+ current = (current == null ? added : current).clone();
+ current.setAmount(count + diff);
+ rv.put(i, current);
+ } else {
+ rv.put(i, null);
+ }
+ }
+ }
+ }
+
+ return rv;
+ }
+
+
+ public static ItemStack getNewHeldItemIfPickedUp(PlayerInventory inventory, ItemStack added) {
+ int heldItemSlot = inventory.getHeldItemSlot();
+ ItemStack heldItem = inventory.getItem(heldItemSlot);
+
+ if (SpigotUtil.isItemPresent(heldItem) && !added.isSimilar(heldItem)) {
+ return null;
+ }
+
+ int amt = added.getAmount();
+ for (int i = 0; i < heldItemSlot; i++) {
+ ItemStack item = inventory.getItem(i);
+ if (!SpigotUtil.isItemPresent(item)) {
+ return null;
+ }
+ if (item.isSimilar(item)) {
+ amt -= Math.max(0, item.getMaxStackSize() - item.getAmount());
+ if (amt <= 0) {
+ return null;
+ }
+ }
+ }
+
+ added = added.clone();
+ added.setAmount(amt + Math.max(0, heldItem == null ? 0 : heldItem.getAmount()));
+ return added;
+ }
+
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/Logging.java b/dicore3/core/src/main/java/io/dico/dicore/Logging.java
index fa2a676..50c4b52 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/Logging.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/Logging.java
@@ -1,116 +1,116 @@
-package io.dico.dicore;
-
-import java.util.logging.Logger;
-
-public interface Logging {
-
- void info(Object o);
-
- void warn(Object o);
-
- void error(Object o);
-
- void debug(Object o);
-
- void setDebugging(boolean debugging);
-
- boolean isDebugging();
-
- class RootLogging implements Logging {
- private final String prefix;
- private final Logger root;
- private boolean debugging;
-
- public RootLogging(String prefix, Logger root, boolean debugging) {
- this.root = root;
- this.prefix = prefix;
- this.debugging = debugging;
- }
-
- @Override
- public void info(Object o) {
- root.info(prefix(o));
- }
-
- @Override
- public void warn(Object o) {
- root.warning(prefix(o));
- }
-
- @Override
- public void error(Object o) {
- root.severe(prefix(o));
- }
-
- @Override
- public void debug(Object o) {
- if (debugging) {
- root.info(String.format("[DEBUG] %s", prefix(o)));
- }
- }
-
- @Override
- public boolean isDebugging() {
- return debugging;
- }
-
- @Override
- public void setDebugging(boolean debugging) {
- this.debugging = debugging;
- }
-
- private String prefix(Object o) {
- return String.format("[%s] %s", prefix, String.valueOf(o));
- }
- }
-
- class SubLogging implements Logging {
- protected String prefix;
- private final Logging superLogger;
- private boolean debugging;
-
- public SubLogging(String prefix, Logging superLogger, boolean debugging) {
- this.superLogger = superLogger;
- this.prefix = prefix;
- this.debugging = debugging;
- }
-
- @Override
- public void info(Object o) {
- superLogger.info(prefix(o));
- }
-
- @Override
- public void warn(Object o) {
- superLogger.warn(prefix(o));
- }
-
- @Override
- public void error(Object o) {
- superLogger.error(prefix(o));
- }
-
- @Override
- public void debug(Object o) {
- if (debugging) {
- superLogger.info(String.format("[DEBUG] %s", prefix(o)));
- }
- }
-
- @Override
- public boolean isDebugging() {
- return debugging;
- }
-
- @Override
- public void setDebugging(boolean debugging) {
- this.debugging = debugging;
- }
-
- private String prefix(Object o) {
- return String.format("[%s] %s", prefix, String.valueOf(o));
- }
-
- }
-
-}
+package io.dico.dicore;
+
+import java.util.logging.Logger;
+
+public interface Logging {
+
+ void info(Object o);
+
+ void warn(Object o);
+
+ void error(Object o);
+
+ void debug(Object o);
+
+ void setDebugging(boolean debugging);
+
+ boolean isDebugging();
+
+ class RootLogging implements Logging {
+ private final String prefix;
+ private final Logger root;
+ private boolean debugging;
+
+ public RootLogging(String prefix, Logger root, boolean debugging) {
+ this.root = root;
+ this.prefix = prefix;
+ this.debugging = debugging;
+ }
+
+ @Override
+ public void info(Object o) {
+ root.info(prefix(o));
+ }
+
+ @Override
+ public void warn(Object o) {
+ root.warning(prefix(o));
+ }
+
+ @Override
+ public void error(Object o) {
+ root.severe(prefix(o));
+ }
+
+ @Override
+ public void debug(Object o) {
+ if (debugging) {
+ root.info(String.format("[DEBUG] %s", prefix(o)));
+ }
+ }
+
+ @Override
+ public boolean isDebugging() {
+ return debugging;
+ }
+
+ @Override
+ public void setDebugging(boolean debugging) {
+ this.debugging = debugging;
+ }
+
+ private String prefix(Object o) {
+ return String.format("[%s] %s", prefix, String.valueOf(o));
+ }
+ }
+
+ class SubLogging implements Logging {
+ protected String prefix;
+ private final Logging superLogger;
+ private boolean debugging;
+
+ public SubLogging(String prefix, Logging superLogger, boolean debugging) {
+ this.superLogger = superLogger;
+ this.prefix = prefix;
+ this.debugging = debugging;
+ }
+
+ @Override
+ public void info(Object o) {
+ superLogger.info(prefix(o));
+ }
+
+ @Override
+ public void warn(Object o) {
+ superLogger.warn(prefix(o));
+ }
+
+ @Override
+ public void error(Object o) {
+ superLogger.error(prefix(o));
+ }
+
+ @Override
+ public void debug(Object o) {
+ if (debugging) {
+ superLogger.info(String.format("[DEBUG] %s", prefix(o)));
+ }
+ }
+
+ @Override
+ public boolean isDebugging() {
+ return debugging;
+ }
+
+ @Override
+ public void setDebugging(boolean debugging) {
+ this.debugging = debugging;
+ }
+
+ private String prefix(Object o) {
+ return String.format("[%s] %s", prefix, String.valueOf(o));
+ }
+
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/Reflection.java b/dicore3/core/src/main/java/io/dico/dicore/Reflection.java
index b7b1ed4..2452d75 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/Reflection.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/Reflection.java
@@ -1,780 +1,780 @@
-package io.dico.dicore;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-/**
- * Reflective utilities
- */
-@SuppressWarnings("unchecked")
-public class Reflection {
- private static final ExceptionHandler exceptionHandler;
- private static final Field fieldModifiersField = restrictedSearchField(Field.class, "modifiers");
- private static Consumer<String> errorTarget;
-
- private Reflection() {
-
- }
-
- static {
- exceptionHandler = new ExceptionHandler() {
- @Override
- public void handle(Throwable ex) {
- handleGenericException(ex);
- }
-
- @Override
- public Object handleGenericException(Throwable ex, Object... args) {
- String action = args.length == 0 || !(args[0] instanceof String) ? "executing a reflective operation" : (String) args[0];
- ExceptionHandler.log(errorTarget, action, ex);
- return null;
- }
- };
-
- // don't use method reference here: the current reference in System.out would be cached.
- setErrorTarget(msg -> System.out.println(msg));
- }
-
- /**
- * Sets the output where ReflectiveOperationException's and similar are sent.
- * This defaults to {@link System#out}.
- *
- * @param target The new output
- * @throws NullPointerException if target is null
- */
- public static void setErrorTarget(Consumer<String> target) {
- errorTarget = Objects.requireNonNull(target);
- }
-
- /**
- * This search modifier tells the implementation that it should subsequently search superclasses for the field/method.
- * Using this modifier means a call to {@link #deepSearchField(Class, String)} will be used instead of {@link #restrictedSearchField(Class, String)}
- * and a call to {@link #deepSearchMethod(Class, String, Class[])} will be used instead of {@link #restrictedSearchMethod(Class, String, Class[])}
- */
- public static final int DEEP_SEARCH = 0x1;
-
- /**
- * This search modifier applies only to fields, and tells the implementation that a final modifier might be present on a found field, and that it should be removed.
- */
- public static final int REMOVE_FINAL = 0x2;
-
- /**
- * This search modifier applies only to methods, and tells the implementation that it should completely ignore parameter types and return the first method with a matching name
- * The implementation uses {@link Class#getDeclaredMethods()} instead of {@link Class#getDeclaredMethod(String, Class[])} if this modifier is set.
- */
- public static final int IGNORE_PARAMS = 0x2;
-
- /*
- ### FIELD METHODS ###
- */
-
- /**
- * Search a field of any accessibility within the class or any of its superclasses.
- * The first field with the given name that is found will be returned.
- * <p>
- * If a field is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the field will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Field is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the field exists, you'll have to use try/catch for that.
- *
- * @param clazz The lowest class in the ladder to start searching from
- * @param fieldName The name of the field
- * //@param fieldType the type of the field, or null if it can be any.
- * @return The field
- * @throws NullPointerException if clazz is null or fieldName is null
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #restrictedSearchField(Class, String)
- */
- public static Field deepSearchField(Class<?> clazz, String fieldName/*, Class<?> fieldType*/) {
- Class<?> currentClass = clazz;
- Field result;
- do {
- // throws NPE if class or fieldName is null
- result = internalSearchField(clazz, fieldName);
- if (result != null) {
- return result;
- }
- currentClass = currentClass.getSuperclass();
- } while (currentClass != null);
-
- throw new IllegalArgumentException("field not found in " + clazz.getCanonicalName() + " and superclasses: " + fieldName);
- }
-
- /**
- * Search a field of any accessibility within the class, but not its superclasses.
- * <p>
- * If a field is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the field will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Field is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the field exists, you'll have to use try/catch for that.
- *
- * @param clazz The only class to search for the field
- * @param fieldName The name of the field
- * @return The field
- * @throws NullPointerException if clazz or fieldName is null
- * @throws IllegalArgumentException if the field does not exist
- */
- public static Field restrictedSearchField(Class<?> clazz, String fieldName) {
- Field result = internalSearchField(clazz, fieldName);
- if (result == null) {
- throw new IllegalArgumentException("field not found in " + clazz.getCanonicalName() + ": " + fieldName);
- }
- return result;
- }
-
- /**
- * Searches for a field using the given search method.
- *
- * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
- * @param clazz The class to search in/from
- * @param fieldName Name of the field
- * @return The field
- * @throws NullPointerException if clazz or fieldName is null
- * @throws IllegalArgumentException if the field is not found
- */
- public static Field searchField(int modifiers, Class<?> clazz, String fieldName) {
- Field result;
- if ((modifiers & DEEP_SEARCH) != 0) {
- result = deepSearchField(clazz, fieldName);
- } else {
- result = restrictedSearchField(clazz, fieldName);
- }
- if ((modifiers & REMOVE_FINAL) != 0) {
- removeFinalModifier(result);
- }
- return result;
- }
-
- /**
- * @return The same as {@link #restrictedSearchField(Class, String)}, but returns null instead of throwing IllegalArgumentException
- * @see #restrictedSearchField(Class, String)
- */
- private static Field internalSearchField(Class<?> clazz, String fieldName) {
- Field result;
- try {
- // throws NullPointerException if either clazz or fieldName are null.
- result = clazz.getDeclaredField(fieldName);
- } catch (NoSuchFieldException | SecurityException ex) {
- return null;
- }
-
- if (!result.isAccessible()) try {
- result.setAccessible(true);
- } catch (SecurityException ignored) {
-
- }
-
- return result;
- }
-
- /**
- * Attempts to remove existing final modifier of the given field
- * This method should always return true.
- *
- * @param field The field whose final modifier to remove
- * @return true if the field most definitely has no final modifier after this call
- * @throws NullPointerException if field is null
- */
- public static boolean removeFinalModifier(Field field) {
- Objects.requireNonNull(field);
- try {
- int modifiers = (int) fieldModifiersField.get(field);
- if (modifiers != (modifiers &= ~Modifier.FINAL)) {
- fieldModifiersField.set(field, modifiers);
- }
- return true;
- } catch (Exception ex) {
- return false;
- }
- }
-
- /**
- * Gets field value of the field named fieldName and the given instance
- * To find the field, {@link #deepSearchField(Class, String)} is used (DEEP search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param instance The instance whose field value to get
- * @param fieldName the name of the field
- * @param <T> The expected/known field type
- * @return The field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #deepSearchField(Class, String)
- * @see #getFieldValue(Class, String, Object)
- */
- public static <T> T getFieldValue(Object instance, String fieldName) {
- return getFieldValue(deepSearchField(instance.getClass(), fieldName), instance);
- }
-
- /**
- * Gets field value of the field named fieldName and the given instance
- * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search for the field
- * @param instance The instance whose field value to get
- * @param fieldName the name of the field
- * @param <T> The expected/known field type
- * @return The field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #restrictedSearchField(Class, String)
- * @see #getFieldValue(Field, Object)
- */
- public static <T> T getFieldValue(Class<?> clazz, String fieldName, Object instance) {
- return getFieldValue(restrictedSearchField(clazz, fieldName), instance);
- }
-
- /**
- * Gets field value of the field named fieldName and the given instance
- * To find the field, {@link #searchField(int, Class, String)} is used.
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
- * @param clazz The class to search for the field
- * @param instance The instance whose field value to get
- * @param fieldName the name of the field
- * @param <T> The expected/known field type
- * @return The field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #searchField(int, Class, String)
- * @see #getFieldValue(Field, Object)
- */
- public static <T> T getFieldValue(int modifiers, Class<?> clazz, String fieldName, Object instance) {
- return getFieldValue(searchField(modifiers, clazz, fieldName), instance);
- }
-
- /**
- * Gets field value of the given field and the given instance
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param field the field
- * @param instance The instance whose field value to get
- * @param <T> The expected/known field type
- * @return The field value
- */
- public static <T> T getFieldValue(Field field, Object instance) {
- return exceptionHandler.supplySafe(() -> (T) field.get(instance));
- }
-
- /**
- * Gets static field value of the field named fieldName
- * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search for the field
- * @param fieldName the name of the field
- * @param <T> The expected/known field type
- * @return The field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #restrictedSearchField(Class, String)
- * @see #getStaticFieldValue(Field)
- */
- public static <T> T getStaticFieldValue(Class<?> clazz, String fieldName) {
- return getStaticFieldValue(restrictedSearchField(clazz, fieldName));
- }
-
- /**
- * Gets static field value of the field named fieldName
- * To find the field, {@link #searchField(int, Class, String)} is used.
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
- * @param clazz The class to search for the field
- * @param fieldName the name of the field
- * @param <T> The expected/known field type
- * @return The field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #deepSearchField(Class, String)
- * @see #getStaticFieldValue(Field)
- */
- public static <T> T getStaticFieldValue(int modifiers, Class<?> clazz, String fieldName) {
- return getStaticFieldValue(searchField(modifiers, clazz, fieldName));
- }
-
- /**
- * Gets static field value
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- * <p>
- * Equivalent to the call {@code getFieldValue(field, (Object) null)}
- *
- * @param field the field
- * @param <T> The expected/known field type
- * @return The field value
- * @see #getFieldValue(Field, Object)
- */
- public static <T> T getStaticFieldValue(Field field) {
- return getFieldValue(field, (Object) null);
- }
-
- /**
- * Sets field value of the field named fieldName and the given instance
- * To find the field, {@link #deepSearchField(Class, String)} is used (DEEP search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param instance The instance whose field value to set
- * @param fieldName the name of the field
- * @param newValue the new field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #deepSearchField(Class, String)
- * @see #setFieldValue(Class, String, Object, Object)
- */
- public static void setFieldValue(Object instance, String fieldName, Object newValue) {
- setFieldValue(deepSearchField(instance.getClass(), fieldName), instance, newValue);
- }
-
- /**
- * Sets field value of the field named fieldName and the given instance
- * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search for the field
- * @param fieldName the name of the field
- * @param instance The field owner
- * @param newValue The new field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #restrictedSearchField(Class, String)
- * @see #setFieldValue(Field, Object, Object)
- */
- public static void setFieldValue(Class<?> clazz, String fieldName, Object instance, Object newValue) {
- setFieldValue(restrictedSearchField(clazz, fieldName), instance, newValue);
- }
-
- /**
- * Sets field value of the field named fieldName and the given instance
- * To find the field, {@link #searchField(int, Class, String)} is used.
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
- * @param clazz The class to search for the field
- * @param instance The instance whose field value to set
- * @param fieldName the name of the field
- * @param newValue The new field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #searchField(int, Class, String)
- * @see #setFieldValue(Field, Object, Object)
- */
- public static void setFieldValue(int modifiers, Class<?> clazz, String fieldName, Object instance, Object newValue) {
- setFieldValue(searchField(modifiers, clazz, fieldName), instance, newValue);
- }
-
- /**
- * Sets a field value
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param field The field
- * @param instance The field owner
- * @param newValue The new field value
- */
- public static void setFieldValue(Field field, Object instance, Object newValue) {
- exceptionHandler.runSafe(() -> field.set(instance, newValue));
- }
-
- /**
- * Sets static field value of the field name fieldName
- * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search for the field
- * @param fieldName the name of the field
- * @param newValue The new field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #restrictedSearchField(Class, String)
- * @see #setStaticFieldValue(Field, Object)
- */
- public static void setStaticFieldValue(Class<?> clazz, String fieldName, Object newValue) {
- setStaticFieldValue(restrictedSearchField(clazz, fieldName), newValue);
- }
-
- /**
- * Sets static field value of the field named fieldName
- * To find the field, {@link #searchField(int, Class, String)} is used.
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
- * @param clazz The class to search for the field
- * @param fieldName the name of the field
- * @param newValue The new field value
- * @throws IllegalArgumentException if the field doesn't exist
- * @see #searchField(int, Class, String)
- * @see #setStaticFieldValue(Field, Object)
- */
- public static void setStaticFieldValue(int modifiers, Class<?> clazz, String fieldName, Object newValue) {
- setStaticFieldValue(searchField(modifiers, clazz, fieldName), newValue);
- }
-
- /**
- * Sets a static field value
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param field The field
- * @param newValue The new field value
- */
- public static void setStaticFieldValue(Field field, Object newValue) {
- setFieldValue(field, (Object) null, newValue);
- }
-
- /*
- ### METHOD METHODS ###
- */
-
- /**
- * Search a method of any accessibility within the class or any of its superclasses.
- * The first method with the given name that is found will be returned.
- * <p>
- * If a method is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
- *
- * @param clazz The lowest class in the ladder to start searching from
- * @param methodName The name of the method
- * @param parameterTypes the parameter types of the sought method.
- * @return The method
- * @throws NullPointerException if clazz is null or methodName is null
- * @throws IllegalArgumentException if the method doesn't exist
- * @see #restrictedSearchMethod(Class, String, Class[])
- */
- public static Method deepSearchMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- return deepSearchMethod(0, clazz, methodName, parameterTypes);
- }
-
- /**
- * Search a method of any accessibility within the class or any of its superclasses.
- * The first method with the given name that is found will be returned.
- * <p>
- * If a method is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
- *
- * @param modifiers The modifiers for method search. Can have {@link #IGNORE_PARAMS}
- * @param clazz The lowest class in the ladder to start searching from
- * @param methodName The name of the method
- * @param parameterTypes the parameter types of the sought method.
- * @return The method
- * @throws NullPointerException if clazz is null or methodName is null
- * @throws IllegalArgumentException if the method doesn't exist
- * @see #restrictedSearchMethod(Class, String, Class[])
- */
- public static Method deepSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- Class<?> currentClass = clazz;
- Method result;
- do {
- // throws NPE if class or methodName is null
- result = internalSearchMethod(modifiers, currentClass, methodName, parameterTypes);
- if (result != null) {
- return result;
- }
- currentClass = currentClass.getSuperclass();
- } while (currentClass != null);
-
- throw new IllegalArgumentException("method not found in " + clazz.getCanonicalName() + " and superclasses: " + methodName);
- }
-
- /**
- * Search a method of any accessibility within the class, but not its superclasses.
- * <p>
- * If a method is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
- *
- * @param clazz The only class to search for the method
- * @param methodName The name of the method
- * @param parameterTypes the parameter types of the sought method.
- * @return The method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method does not exist
- */
- public static Method restrictedSearchMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- return restrictedSearchMethod(0, clazz, methodName, parameterTypes);
- }
-
- /**
- * Search a method of any accessibility within the class, but not its superclasses.
- * <p>
- * If a method is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
- *
- * @param modifiers The modifiers for method search. Can have {@link #IGNORE_PARAMS}
- * @param clazz The only class to search for the method
- * @param methodName The name of the method
- * @param parameterTypes the parameter types of the sought method.
- * @return The method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method does not exist
- */
- public static Method restrictedSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- Method result = internalSearchMethod(modifiers, clazz, methodName, parameterTypes);
- if (result == null) {
- throw new IllegalArgumentException("method not found in " + clazz.getCanonicalName() + ": " + methodName);
- }
- return result;
- }
-
- /**
- * Searches for a method using the given search method.
- * <p>
- * If a method is found and it is not accessible, this method attempts to make it accessible.
- * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
- * <p>
- * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
- * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
- *
- * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
- * @param clazz The class to search in/from
- * @param methodName Name of the method
- * @param parameterTypes the parameter types of the sought method.
- * @return The method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method is not found
- */
- public static Method searchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- if ((modifiers & DEEP_SEARCH) != 0) {
- return deepSearchMethod(modifiers, clazz, methodName, parameterTypes);
- } else {
- return restrictedSearchMethod(modifiers, clazz, methodName, parameterTypes);
- }
- }
-
- /**
- * @return The same as {@link #restrictedSearchMethod(Class, String, Class[]) }, but returns null instead of throwing IllegalArgumentException
- * @see #restrictedSearchMethod(Class, String, Class[])
- */
- private static Method internalSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
- Method result = null;
-
- if ((modifiers & IGNORE_PARAMS) != 0) {
-
- // throws NullPointerException if either clazz or methodName are null.
- methodName = methodName.intern();
- for (Method method : clazz.getDeclaredMethods()) {
- // all method names are interned. Identity comparison is much faster.
- if (method.getName() == methodName) {
- result = method;
- break;
- }
- }
-
- if (result == null) {
- return null;
- }
-
- } else {
-
- try {
- // throws NullPointerException if either clazz or methodName are null.
- result = clazz.getDeclaredMethod(methodName, parameterTypes);
- } catch (NoSuchMethodException | SecurityException ex) {
- return null;
- }
-
- }
-
- if (!result.isAccessible()) try {
- result.setAccessible(true);
- } catch (SecurityException ignored) {
-
- }
-
- return result;
- }
-
- /**
- * Invokes the method named methodName with the given instance and arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
- * modifiers {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}, and the class {@link Object#getClass() instance.getClass()}
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param methodName Name of the method
- * @param instance The instance to invoke the method on
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if instance or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeMethod(Method, Object, Object...)
- */
- public static <T> T invokeMethod(Object instance, String methodName, Object... args) {
- return invokeMethod(searchMethod(DEEP_SEARCH | IGNORE_PARAMS, instance.getClass(), methodName), instance, args);
- }
-
- /**
- * Invokes the method named methodName with the given instance and arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
- * as well as the modifier {@link #IGNORE_PARAMS}
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search in/from
- * @param methodName Name of the method
- * @param instance The instance to invoke the method on
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeMethod(Method, Object, Object...)
- */
- public static <T> T invokeMethod(Class<?> clazz, String methodName, Object instance, Object... args) {
- return invokeMethod(searchMethod(IGNORE_PARAMS, clazz, methodName), instance, args);
- }
-
- /**
- * Invokes the method named methodName with the given instance and arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
- * For this search, the result of calling {@link Object#getClass() instance.getClass()} is used.
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
- * @param methodName Name of the method
- * @param instance The instance to invoke the method on
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if instance or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeMethod(Method, Object, Object...)
- */
- public static <T> T invokeMethod(int modifiers, Object instance, String methodName, Object... args) {
- return invokeMethod(searchMethod(modifiers, instance.getClass(), methodName), instance, args);
- }
-
- /**
- * Invokes the method named methodName with the given instance and arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
- * @param clazz The class to search in/from
- * @param methodName Name of the method
- * @param instance The instance to invoke the method on
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeMethod(Method, Object, Object...)
- */
- public static <T> T invokeMethod(int modifiers, Class<?> clazz, String methodName, Object instance, Object... args) {
- return invokeMethod(searchMethod(modifiers, clazz, methodName), instance, args);
- }
-
- /**
- * Invokes the method with the given instance and arguments
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param method The method to invoke
- * @param instance The instance to invoke the method on
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- */
- public static <T> T invokeMethod(Method method, Object instance, Object... args) {
- return exceptionHandler.supplySafe(() -> (T) method.invoke(instance, args));
- }
-
- /**
- * Invokes the static method named methodName with the given arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
- * as well as the modifier {@link #IGNORE_PARAMS}
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param clazz The class to search in/from
- * @param methodName Name of the method
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeStaticMethod(Method, Object...)
- */
- public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Object... args) {
- return invokeStaticMethod(searchMethod(IGNORE_PARAMS, clazz, methodName), args);
- }
-
- /**
- * Invokes the static method named methodName with the given arguments
- * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
- * <p>
- * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
- * and call {@link #invokeMethod(Method, Object, Object...)}
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
- * @param clazz The class to search in/from
- * @param methodName Name of the method
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @throws NullPointerException if clazz or methodName is null
- * @throws IllegalArgumentException if the method is not found
- * @see #invokeStaticMethod(Method, Object...)
- */
- public static <T> T invokeStaticMethod(int modifiers, Class<?> clazz, String methodName, Object... args) {
- return invokeStaticMethod(searchMethod(modifiers, clazz, methodName), args);
- }
-
- /**
- * Invokes the static method with the given arguments
- * <p>
- * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
- *
- * @param method The method to invoke
- * @param args The arguments to use in the method call
- * @param <T> The expected/known method return type
- * @return The result of calling the method
- * @see #invokeMethod(Method, Object, Object...)
- */
- public static <T> T invokeStaticMethod(Method method, Object... args) {
- return invokeMethod(method, (Object) null, args);
- }
-
-}
+package io.dico.dicore;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ * Reflective utilities
+ */
+@SuppressWarnings("unchecked")
+public class Reflection {
+ private static final ExceptionHandler exceptionHandler;
+ private static final Field fieldModifiersField = restrictedSearchField(Field.class, "modifiers");
+ private static Consumer<String> errorTarget;
+
+ private Reflection() {
+
+ }
+
+ static {
+ exceptionHandler = new ExceptionHandler() {
+ @Override
+ public void handle(Throwable ex) {
+ handleGenericException(ex);
+ }
+
+ @Override
+ public Object handleGenericException(Throwable ex, Object... args) {
+ String action = args.length == 0 || !(args[0] instanceof String) ? "executing a reflective operation" : (String) args[0];
+ ExceptionHandler.log(errorTarget, action, ex);
+ return null;
+ }
+ };
+
+ // don't use method reference here: the current reference in System.out would be cached.
+ setErrorTarget(msg -> System.out.println(msg));
+ }
+
+ /**
+ * Sets the output where ReflectiveOperationException's and similar are sent.
+ * This defaults to {@link System#out}.
+ *
+ * @param target The new output
+ * @throws NullPointerException if target is null
+ */
+ public static void setErrorTarget(Consumer<String> target) {
+ errorTarget = Objects.requireNonNull(target);
+ }
+
+ /**
+ * This search modifier tells the implementation that it should subsequently search superclasses for the field/method.
+ * Using this modifier means a call to {@link #deepSearchField(Class, String)} will be used instead of {@link #restrictedSearchField(Class, String)}
+ * and a call to {@link #deepSearchMethod(Class, String, Class[])} will be used instead of {@link #restrictedSearchMethod(Class, String, Class[])}
+ */
+ public static final int DEEP_SEARCH = 0x1;
+
+ /**
+ * This search modifier applies only to fields, and tells the implementation that a final modifier might be present on a found field, and that it should be removed.
+ */
+ public static final int REMOVE_FINAL = 0x2;
+
+ /**
+ * This search modifier applies only to methods, and tells the implementation that it should completely ignore parameter types and return the first method with a matching name
+ * The implementation uses {@link Class#getDeclaredMethods()} instead of {@link Class#getDeclaredMethod(String, Class[])} if this modifier is set.
+ */
+ public static final int IGNORE_PARAMS = 0x2;
+
+ /*
+ ### FIELD METHODS ###
+ */
+
+ /**
+ * Search a field of any accessibility within the class or any of its superclasses.
+ * The first field with the given name that is found will be returned.
+ * <p>
+ * If a field is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the field will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Field is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the field exists, you'll have to use try/catch for that.
+ *
+ * @param clazz The lowest class in the ladder to start searching from
+ * @param fieldName The name of the field
+ * //@param fieldType the type of the field, or null if it can be any.
+ * @return The field
+ * @throws NullPointerException if clazz is null or fieldName is null
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #restrictedSearchField(Class, String)
+ */
+ public static Field deepSearchField(Class<?> clazz, String fieldName/*, Class<?> fieldType*/) {
+ Class<?> currentClass = clazz;
+ Field result;
+ do {
+ // throws NPE if class or fieldName is null
+ result = internalSearchField(clazz, fieldName);
+ if (result != null) {
+ return result;
+ }
+ currentClass = currentClass.getSuperclass();
+ } while (currentClass != null);
+
+ throw new IllegalArgumentException("field not found in " + clazz.getCanonicalName() + " and superclasses: " + fieldName);
+ }
+
+ /**
+ * Search a field of any accessibility within the class, but not its superclasses.
+ * <p>
+ * If a field is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the field will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Field is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the field exists, you'll have to use try/catch for that.
+ *
+ * @param clazz The only class to search for the field
+ * @param fieldName The name of the field
+ * @return The field
+ * @throws NullPointerException if clazz or fieldName is null
+ * @throws IllegalArgumentException if the field does not exist
+ */
+ public static Field restrictedSearchField(Class<?> clazz, String fieldName) {
+ Field result = internalSearchField(clazz, fieldName);
+ if (result == null) {
+ throw new IllegalArgumentException("field not found in " + clazz.getCanonicalName() + ": " + fieldName);
+ }
+ return result;
+ }
+
+ /**
+ * Searches for a field using the given search method.
+ *
+ * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
+ * @param clazz The class to search in/from
+ * @param fieldName Name of the field
+ * @return The field
+ * @throws NullPointerException if clazz or fieldName is null
+ * @throws IllegalArgumentException if the field is not found
+ */
+ public static Field searchField(int modifiers, Class<?> clazz, String fieldName) {
+ Field result;
+ if ((modifiers & DEEP_SEARCH) != 0) {
+ result = deepSearchField(clazz, fieldName);
+ } else {
+ result = restrictedSearchField(clazz, fieldName);
+ }
+ if ((modifiers & REMOVE_FINAL) != 0) {
+ removeFinalModifier(result);
+ }
+ return result;
+ }
+
+ /**
+ * @return The same as {@link #restrictedSearchField(Class, String)}, but returns null instead of throwing IllegalArgumentException
+ * @see #restrictedSearchField(Class, String)
+ */
+ private static Field internalSearchField(Class<?> clazz, String fieldName) {
+ Field result;
+ try {
+ // throws NullPointerException if either clazz or fieldName are null.
+ result = clazz.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException | SecurityException ex) {
+ return null;
+ }
+
+ if (!result.isAccessible()) try {
+ result.setAccessible(true);
+ } catch (SecurityException ignored) {
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Attempts to remove existing final modifier of the given field
+ * This method should always return true.
+ *
+ * @param field The field whose final modifier to remove
+ * @return true if the field most definitely has no final modifier after this call
+ * @throws NullPointerException if field is null
+ */
+ public static boolean removeFinalModifier(Field field) {
+ Objects.requireNonNull(field);
+ try {
+ int modifiers = (int) fieldModifiersField.get(field);
+ if (modifiers != (modifiers &= ~Modifier.FINAL)) {
+ fieldModifiersField.set(field, modifiers);
+ }
+ return true;
+ } catch (Exception ex) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets field value of the field named fieldName and the given instance
+ * To find the field, {@link #deepSearchField(Class, String)} is used (DEEP search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param instance The instance whose field value to get
+ * @param fieldName the name of the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #deepSearchField(Class, String)
+ * @see #getFieldValue(Class, String, Object)
+ */
+ public static <T> T getFieldValue(Object instance, String fieldName) {
+ return getFieldValue(deepSearchField(instance.getClass(), fieldName), instance);
+ }
+
+ /**
+ * Gets field value of the field named fieldName and the given instance
+ * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search for the field
+ * @param instance The instance whose field value to get
+ * @param fieldName the name of the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #restrictedSearchField(Class, String)
+ * @see #getFieldValue(Field, Object)
+ */
+ public static <T> T getFieldValue(Class<?> clazz, String fieldName, Object instance) {
+ return getFieldValue(restrictedSearchField(clazz, fieldName), instance);
+ }
+
+ /**
+ * Gets field value of the field named fieldName and the given instance
+ * To find the field, {@link #searchField(int, Class, String)} is used.
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
+ * @param clazz The class to search for the field
+ * @param instance The instance whose field value to get
+ * @param fieldName the name of the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #searchField(int, Class, String)
+ * @see #getFieldValue(Field, Object)
+ */
+ public static <T> T getFieldValue(int modifiers, Class<?> clazz, String fieldName, Object instance) {
+ return getFieldValue(searchField(modifiers, clazz, fieldName), instance);
+ }
+
+ /**
+ * Gets field value of the given field and the given instance
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param field the field
+ * @param instance The instance whose field value to get
+ * @param <T> The expected/known field type
+ * @return The field value
+ */
+ public static <T> T getFieldValue(Field field, Object instance) {
+ return exceptionHandler.supplySafe(() -> (T) field.get(instance));
+ }
+
+ /**
+ * Gets static field value of the field named fieldName
+ * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search for the field
+ * @param fieldName the name of the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #restrictedSearchField(Class, String)
+ * @see #getStaticFieldValue(Field)
+ */
+ public static <T> T getStaticFieldValue(Class<?> clazz, String fieldName) {
+ return getStaticFieldValue(restrictedSearchField(clazz, fieldName));
+ }
+
+ /**
+ * Gets static field value of the field named fieldName
+ * To find the field, {@link #searchField(int, Class, String)} is used.
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
+ * @param clazz The class to search for the field
+ * @param fieldName the name of the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #deepSearchField(Class, String)
+ * @see #getStaticFieldValue(Field)
+ */
+ public static <T> T getStaticFieldValue(int modifiers, Class<?> clazz, String fieldName) {
+ return getStaticFieldValue(searchField(modifiers, clazz, fieldName));
+ }
+
+ /**
+ * Gets static field value
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ * <p>
+ * Equivalent to the call {@code getFieldValue(field, (Object) null)}
+ *
+ * @param field the field
+ * @param <T> The expected/known field type
+ * @return The field value
+ * @see #getFieldValue(Field, Object)
+ */
+ public static <T> T getStaticFieldValue(Field field) {
+ return getFieldValue(field, (Object) null);
+ }
+
+ /**
+ * Sets field value of the field named fieldName and the given instance
+ * To find the field, {@link #deepSearchField(Class, String)} is used (DEEP search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param instance The instance whose field value to set
+ * @param fieldName the name of the field
+ * @param newValue the new field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #deepSearchField(Class, String)
+ * @see #setFieldValue(Class, String, Object, Object)
+ */
+ public static void setFieldValue(Object instance, String fieldName, Object newValue) {
+ setFieldValue(deepSearchField(instance.getClass(), fieldName), instance, newValue);
+ }
+
+ /**
+ * Sets field value of the field named fieldName and the given instance
+ * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search for the field
+ * @param fieldName the name of the field
+ * @param instance The field owner
+ * @param newValue The new field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #restrictedSearchField(Class, String)
+ * @see #setFieldValue(Field, Object, Object)
+ */
+ public static void setFieldValue(Class<?> clazz, String fieldName, Object instance, Object newValue) {
+ setFieldValue(restrictedSearchField(clazz, fieldName), instance, newValue);
+ }
+
+ /**
+ * Sets field value of the field named fieldName and the given instance
+ * To find the field, {@link #searchField(int, Class, String)} is used.
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
+ * @param clazz The class to search for the field
+ * @param instance The instance whose field value to set
+ * @param fieldName the name of the field
+ * @param newValue The new field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #searchField(int, Class, String)
+ * @see #setFieldValue(Field, Object, Object)
+ */
+ public static void setFieldValue(int modifiers, Class<?> clazz, String fieldName, Object instance, Object newValue) {
+ setFieldValue(searchField(modifiers, clazz, fieldName), instance, newValue);
+ }
+
+ /**
+ * Sets a field value
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param field The field
+ * @param instance The field owner
+ * @param newValue The new field value
+ */
+ public static void setFieldValue(Field field, Object instance, Object newValue) {
+ exceptionHandler.runSafe(() -> field.set(instance, newValue));
+ }
+
+ /**
+ * Sets static field value of the field name fieldName
+ * To find the field, {@link #restrictedSearchField(Class, String)} is used (RESTRICTED search method).
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search for the field
+ * @param fieldName the name of the field
+ * @param newValue The new field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #restrictedSearchField(Class, String)
+ * @see #setStaticFieldValue(Field, Object)
+ */
+ public static void setStaticFieldValue(Class<?> clazz, String fieldName, Object newValue) {
+ setStaticFieldValue(restrictedSearchField(clazz, fieldName), newValue);
+ }
+
+ /**
+ * Sets static field value of the field named fieldName
+ * To find the field, {@link #searchField(int, Class, String)} is used.
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for field search. Can have {@link #DEEP_SEARCH} and {@link #REMOVE_FINAL}
+ * @param clazz The class to search for the field
+ * @param fieldName the name of the field
+ * @param newValue The new field value
+ * @throws IllegalArgumentException if the field doesn't exist
+ * @see #searchField(int, Class, String)
+ * @see #setStaticFieldValue(Field, Object)
+ */
+ public static void setStaticFieldValue(int modifiers, Class<?> clazz, String fieldName, Object newValue) {
+ setStaticFieldValue(searchField(modifiers, clazz, fieldName), newValue);
+ }
+
+ /**
+ * Sets a static field value
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param field The field
+ * @param newValue The new field value
+ */
+ public static void setStaticFieldValue(Field field, Object newValue) {
+ setFieldValue(field, (Object) null, newValue);
+ }
+
+ /*
+ ### METHOD METHODS ###
+ */
+
+ /**
+ * Search a method of any accessibility within the class or any of its superclasses.
+ * The first method with the given name that is found will be returned.
+ * <p>
+ * If a method is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
+ *
+ * @param clazz The lowest class in the ladder to start searching from
+ * @param methodName The name of the method
+ * @param parameterTypes the parameter types of the sought method.
+ * @return The method
+ * @throws NullPointerException if clazz is null or methodName is null
+ * @throws IllegalArgumentException if the method doesn't exist
+ * @see #restrictedSearchMethod(Class, String, Class[])
+ */
+ public static Method deepSearchMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ return deepSearchMethod(0, clazz, methodName, parameterTypes);
+ }
+
+ /**
+ * Search a method of any accessibility within the class or any of its superclasses.
+ * The first method with the given name that is found will be returned.
+ * <p>
+ * If a method is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #IGNORE_PARAMS}
+ * @param clazz The lowest class in the ladder to start searching from
+ * @param methodName The name of the method
+ * @param parameterTypes the parameter types of the sought method.
+ * @return The method
+ * @throws NullPointerException if clazz is null or methodName is null
+ * @throws IllegalArgumentException if the method doesn't exist
+ * @see #restrictedSearchMethod(Class, String, Class[])
+ */
+ public static Method deepSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ Class<?> currentClass = clazz;
+ Method result;
+ do {
+ // throws NPE if class or methodName is null
+ result = internalSearchMethod(modifiers, currentClass, methodName, parameterTypes);
+ if (result != null) {
+ return result;
+ }
+ currentClass = currentClass.getSuperclass();
+ } while (currentClass != null);
+
+ throw new IllegalArgumentException("method not found in " + clazz.getCanonicalName() + " and superclasses: " + methodName);
+ }
+
+ /**
+ * Search a method of any accessibility within the class, but not its superclasses.
+ * <p>
+ * If a method is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
+ *
+ * @param clazz The only class to search for the method
+ * @param methodName The name of the method
+ * @param parameterTypes the parameter types of the sought method.
+ * @return The method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method does not exist
+ */
+ public static Method restrictedSearchMethod(Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ return restrictedSearchMethod(0, clazz, methodName, parameterTypes);
+ }
+
+ /**
+ * Search a method of any accessibility within the class, but not its superclasses.
+ * <p>
+ * If a method is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #IGNORE_PARAMS}
+ * @param clazz The only class to search for the method
+ * @param methodName The name of the method
+ * @param parameterTypes the parameter types of the sought method.
+ * @return The method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method does not exist
+ */
+ public static Method restrictedSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ Method result = internalSearchMethod(modifiers, clazz, methodName, parameterTypes);
+ if (result == null) {
+ throw new IllegalArgumentException("method not found in " + clazz.getCanonicalName() + ": " + methodName);
+ }
+ return result;
+ }
+
+ /**
+ * Searches for a method using the given search method.
+ * <p>
+ * If a method is found and it is not accessible, this method attempts to make it accessible.
+ * If a {@link SecurityException} is thrown in the process, that is ignored and the method will be returned nonetheless.
+ * <p>
+ * This method throws IllegalArgumentException if the Method is not found, because, in most cases, that should never happen,
+ * and it should simplify debugging. In some cases, if you want to know if the method exists, you'll have to use try/catch for that.
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
+ * @param clazz The class to search in/from
+ * @param methodName Name of the method
+ * @param parameterTypes the parameter types of the sought method.
+ * @return The method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ */
+ public static Method searchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ if ((modifiers & DEEP_SEARCH) != 0) {
+ return deepSearchMethod(modifiers, clazz, methodName, parameterTypes);
+ } else {
+ return restrictedSearchMethod(modifiers, clazz, methodName, parameterTypes);
+ }
+ }
+
+ /**
+ * @return The same as {@link #restrictedSearchMethod(Class, String, Class[]) }, but returns null instead of throwing IllegalArgumentException
+ * @see #restrictedSearchMethod(Class, String, Class[])
+ */
+ private static Method internalSearchMethod(int modifiers, Class<?> clazz, String methodName, Class<?>... parameterTypes) {
+ Method result = null;
+
+ if ((modifiers & IGNORE_PARAMS) != 0) {
+
+ // throws NullPointerException if either clazz or methodName are null.
+ methodName = methodName.intern();
+ for (Method method : clazz.getDeclaredMethods()) {
+ // all method names are interned. Identity comparison is much faster.
+ if (method.getName() == methodName) {
+ result = method;
+ break;
+ }
+ }
+
+ if (result == null) {
+ return null;
+ }
+
+ } else {
+
+ try {
+ // throws NullPointerException if either clazz or methodName are null.
+ result = clazz.getDeclaredMethod(methodName, parameterTypes);
+ } catch (NoSuchMethodException | SecurityException ex) {
+ return null;
+ }
+
+ }
+
+ if (!result.isAccessible()) try {
+ result.setAccessible(true);
+ } catch (SecurityException ignored) {
+
+ }
+
+ return result;
+ }
+
+ /**
+ * Invokes the method named methodName with the given instance and arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
+ * modifiers {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}, and the class {@link Object#getClass() instance.getClass()}
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param methodName Name of the method
+ * @param instance The instance to invoke the method on
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if instance or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeMethod(Method, Object, Object...)
+ */
+ public static <T> T invokeMethod(Object instance, String methodName, Object... args) {
+ return invokeMethod(searchMethod(DEEP_SEARCH | IGNORE_PARAMS, instance.getClass(), methodName), instance, args);
+ }
+
+ /**
+ * Invokes the method named methodName with the given instance and arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
+ * as well as the modifier {@link #IGNORE_PARAMS}
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search in/from
+ * @param methodName Name of the method
+ * @param instance The instance to invoke the method on
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeMethod(Method, Object, Object...)
+ */
+ public static <T> T invokeMethod(Class<?> clazz, String methodName, Object instance, Object... args) {
+ return invokeMethod(searchMethod(IGNORE_PARAMS, clazz, methodName), instance, args);
+ }
+
+ /**
+ * Invokes the method named methodName with the given instance and arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
+ * For this search, the result of calling {@link Object#getClass() instance.getClass()} is used.
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
+ * @param methodName Name of the method
+ * @param instance The instance to invoke the method on
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if instance or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeMethod(Method, Object, Object...)
+ */
+ public static <T> T invokeMethod(int modifiers, Object instance, String methodName, Object... args) {
+ return invokeMethod(searchMethod(modifiers, instance.getClass(), methodName), instance, args);
+ }
+
+ /**
+ * Invokes the method named methodName with the given instance and arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
+ * @param clazz The class to search in/from
+ * @param methodName Name of the method
+ * @param instance The instance to invoke the method on
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeMethod(Method, Object, Object...)
+ */
+ public static <T> T invokeMethod(int modifiers, Class<?> clazz, String methodName, Object instance, Object... args) {
+ return invokeMethod(searchMethod(modifiers, clazz, methodName), instance, args);
+ }
+
+ /**
+ * Invokes the method with the given instance and arguments
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param method The method to invoke
+ * @param instance The instance to invoke the method on
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ */
+ public static <T> T invokeMethod(Method method, Object instance, Object... args) {
+ return exceptionHandler.supplySafe(() -> (T) method.invoke(instance, args));
+ }
+
+ /**
+ * Invokes the static method named methodName with the given arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters,
+ * as well as the modifier {@link #IGNORE_PARAMS}
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param clazz The class to search in/from
+ * @param methodName Name of the method
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeStaticMethod(Method, Object...)
+ */
+ public static <T> T invokeStaticMethod(Class<?> clazz, String methodName, Object... args) {
+ return invokeStaticMethod(searchMethod(IGNORE_PARAMS, clazz, methodName), args);
+ }
+
+ /**
+ * Invokes the static method named methodName with the given arguments
+ * To find the method, {@link #searchMethod(int, Class, String, Class[])} is used with no type parameters.
+ * <p>
+ * To search the method with type parameters, you should search the method using {@link #searchMethod(int, Class, String, Class[])} or similar,
+ * and call {@link #invokeMethod(Method, Object, Object...)}
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param modifiers The modifiers for method search. Can have {@link #DEEP_SEARCH} and {@link #IGNORE_PARAMS}
+ * @param clazz The class to search in/from
+ * @param methodName Name of the method
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @throws NullPointerException if clazz or methodName is null
+ * @throws IllegalArgumentException if the method is not found
+ * @see #invokeStaticMethod(Method, Object...)
+ */
+ public static <T> T invokeStaticMethod(int modifiers, Class<?> clazz, String methodName, Object... args) {
+ return invokeStaticMethod(searchMethod(modifiers, clazz, methodName), args);
+ }
+
+ /**
+ * Invokes the static method with the given arguments
+ * <p>
+ * If a {@link ReflectiveOperationException} occurs, this is printed to {@link System#out}
+ *
+ * @param method The method to invoke
+ * @param args The arguments to use in the method call
+ * @param <T> The expected/known method return type
+ * @return The result of calling the method
+ * @see #invokeMethod(Method, Object, Object...)
+ */
+ public static <T> T invokeStaticMethod(Method method, Object... args) {
+ return invokeMethod(method, (Object) null, args);
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/SetBasedWhitelist.java b/dicore3/core/src/main/java/io/dico/dicore/SetBasedWhitelist.java
index 6596b65..d4486ed 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/SetBasedWhitelist.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/SetBasedWhitelist.java
@@ -1,59 +1,59 @@
-package io.dico.dicore;
-
-import org.bukkit.configuration.ConfigurationSection;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-public class SetBasedWhitelist implements Whitelist {
- private final Set set;
- private final boolean blacklist;
-
- public SetBasedWhitelist(Object[] array, boolean blacklist) {
- this(Arrays.asList(array), blacklist);
- }
-
- public SetBasedWhitelist(ConfigurationSection section, Function<String, ?> parser) {
- this(section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toList()),
- section.getBoolean("blacklist", false));
- }
-
- @SuppressWarnings("unchecked")
- public SetBasedWhitelist(Collection collection, boolean blacklist) {
- Set set;
- if (collection.isEmpty()) {
- set = Collections.emptySet();
- } else if (collection.iterator().next() instanceof Enum) {
- set = EnumSet.copyOf(collection);
- } else if (collection instanceof Set) {
- set = (Set) collection;
- } else {
- set = new HashSet<>(collection);
- }
-
- this.set = set;
- this.blacklist = blacklist;
- }
-
- @Override
- public boolean isWhitelisted(Object o) {
- return blacklist != set.contains(o);
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public String toString() {
- return (blacklist ? "Blacklist" : "Whitelist") + "{"
- + String.join(", ", (CharSequence[]) set.stream().map(String::valueOf).toArray(String[]::new)) + "}";
- }
-
- public Set getSet() {
- return set;
- }
-
- public boolean isBlacklist() {
- return blacklist;
- }
-
-}
+package io.dico.dicore;
+
+import org.bukkit.configuration.ConfigurationSection;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+public class SetBasedWhitelist implements Whitelist {
+ private final Set set;
+ private final boolean blacklist;
+
+ public SetBasedWhitelist(Object[] array, boolean blacklist) {
+ this(Arrays.asList(array), blacklist);
+ }
+
+ public SetBasedWhitelist(ConfigurationSection section, Function<String, ?> parser) {
+ this(section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toList()),
+ section.getBoolean("blacklist", false));
+ }
+
+ @SuppressWarnings("unchecked")
+ public SetBasedWhitelist(Collection collection, boolean blacklist) {
+ Set set;
+ if (collection.isEmpty()) {
+ set = Collections.emptySet();
+ } else if (collection.iterator().next() instanceof Enum) {
+ set = EnumSet.copyOf(collection);
+ } else if (collection instanceof Set) {
+ set = (Set) collection;
+ } else {
+ set = new HashSet<>(collection);
+ }
+
+ this.set = set;
+ this.blacklist = blacklist;
+ }
+
+ @Override
+ public boolean isWhitelisted(Object o) {
+ return blacklist != set.contains(o);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toString() {
+ return (blacklist ? "Blacklist" : "Whitelist") + "{"
+ + String.join(", ", (CharSequence[]) set.stream().map(String::valueOf).toArray(String[]::new)) + "}";
+ }
+
+ public Set getSet() {
+ return set;
+ }
+
+ public boolean isBlacklist() {
+ return blacklist;
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/SpigotUtil.java b/dicore3/core/src/main/java/io/dico/dicore/SpigotUtil.java
index 44659fa..afcae02 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/SpigotUtil.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/SpigotUtil.java
@@ -1,408 +1,408 @@
-package io.dico.dicore;
-
-import org.bukkit.Bukkit;
-import org.bukkit.Location;
-import org.bukkit.Material;
-import org.bukkit.World;
-import org.bukkit.block.Block;
-import org.bukkit.block.BlockFace;
-import org.bukkit.block.BlockState;
-import org.bukkit.configuration.serialization.ConfigurationSerializable;
-import org.bukkit.entity.*;
-import org.bukkit.inventory.Inventory;
-import org.bukkit.inventory.InventoryHolder;
-import org.bukkit.inventory.ItemStack;
-import org.bukkit.material.Attachable;
-import org.bukkit.material.MaterialData;
-import org.bukkit.projectiles.ProjectileSource;
-
-import java.util.*;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-public class SpigotUtil {
-
- private SpigotUtil() {
- throw new UnsupportedOperationException();
- }
-
- public static World matchWorld(String input) {
- try {
- UUID uid = UUID.fromString(input);
- World world = Bukkit.getWorld(uid);
- if (world != null) {
- return world;
- }
- } catch (IllegalArgumentException ignored) {
- }
-
- World result = Bukkit.getWorld(input);
- if (result == null) {
- input = input.toLowerCase().replace("_", "").replaceAll("[-_]", "");
- for (World world : Bukkit.getWorlds()) {
- if (world.getName().toLowerCase().equals(input)) {
- result = world;
- break;
- }
- }
- }
-
- return result;
- }
-
- public static Block getSupportingBlock(Block block) {
- MaterialData data = block.getState().getData();
- if (data instanceof Attachable) {
- BlockFace attachedOn = ((Attachable) data).getAttachedFace();
- return block.getRelative(attachedOn);
- }
- return null;
- }
-
- public static boolean isItemPresent(ItemStack stack) {
- return stack != null && stack.getType() != Material.AIR && stack.getAmount() > 0;
- }
-
- public static boolean removeItems(Inventory from, ItemStack item, int amount) {
- for (Map.Entry<Integer, ? extends ItemStack> entry : from.all(item.getType()).entrySet()) {
- ItemStack stack = entry.getValue();
- if (item.isSimilar(stack)) {
- amount -= stack.getAmount();
- int stackAmount = -Math.min(0, amount);
- if (stackAmount == 0) {
- from.setItem(entry.getKey(), null);
- } else {
- stack.setAmount(stackAmount);
- }
- }
- }
- return amount <= 0;
- }
-
- public static BlockFace yawToFace(float yaw) {
- if ((yaw %= 360) < 0)
- yaw += 360;
- if (45 <= yaw && yaw < 135)
- return BlockFace.WEST;
- if (135 <= yaw && yaw < 225)
- return BlockFace.NORTH;
- if (225 <= yaw && yaw < 315)
- return BlockFace.EAST;
- return BlockFace.SOUTH;
- }
-
- public static void addItems(InventoryHolder entity, ItemStack... items) {
- Location dropLocation;
- if (entity instanceof Entity) {
- dropLocation = ((Entity) entity).getLocation();
- } else if (entity instanceof BlockState) {
- dropLocation = ((BlockState) entity).getLocation().add(0.5, 1, 0.5);
- } else {
- throw new IllegalArgumentException("Can't find location of this InventoryHolder: " + entity);
- }
- World world = dropLocation.getWorld();
- for (ItemStack toDrop : entity.getInventory().addItem(items).values()) {
- world.dropItemNaturally(dropLocation, toDrop);
- }
- }
-
- public static String asJsonString(Object object) {
- return asJsonString(null, object, 0);
- }
-
- public static String asJsonString(String key, Object object, int indentation) {
- String indent = new String(new char[indentation * 2]).replace('\0', ' ');
- StringBuilder builder = new StringBuilder(indent);
- if (key != null) {
- builder.append(key).append(": ");
- }
- if (object instanceof ConfigurationSerializable) {
- object = ((ConfigurationSerializable) object).serialize();
- }
- if (object instanceof Map) {
- builder.append("{\n");
- Map<?, ?> map = (Map) object;
- for (Map.Entry entry : map.entrySet()) {
- builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1));
- }
- builder.append(indent).append("}");
- } else if (object instanceof List) {
- builder.append("[\n");
- List list = (List) object;
- for (Object entry : list) {
- builder.append(asJsonString(null, entry, indentation + 1));
- }
- builder.append(indent).append("]");
- } else {
- builder.append(String.valueOf(object));
- }
- return builder.append(",\n").toString();
- }
-
- public static String asJsonString(String key, Object object, int indentation, BiConsumer<List<?>, StringBuilder> listHeader) {
- String indent = new String(new char[indentation * 2]).replace('\0', ' ');
- StringBuilder builder = new StringBuilder(indent);
- if (key != null) {
- builder.append(key).append(": ");
- }
- if (object instanceof ConfigurationSerializable) {
- object = ((ConfigurationSerializable) object).serialize();
- }
- if (object instanceof Map) {
- builder.append("{\n");
- Map<?, ?> map = (Map) object;
- for (Map.Entry entry : map.entrySet()) {
- builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1, listHeader));
- }
- builder.append(indent).append("}");
- } else if (object instanceof List) {
- builder.append("[");
- List list = (List) object;
- listHeader.accept(list, builder);
- builder.append("\n");
- for (Object entry : list) {
- builder.append(asJsonString(null, entry, indentation + 1, listHeader));
- }
- builder.append(indent).append("]");
- } else {
- builder.append(String.valueOf(object));
- }
- return builder.append(",\n").toString();
- }
-
- public static BlockFace estimateDirectionTo(Location from, Location to) {
- double dx = from.getX() - to.getX();
- double dz = from.getZ() - to.getZ();
-
- boolean xGreater = Math.abs(dx) - Math.abs(dz) > 0;
- double f = xGreater ? 2 / Math.abs(dx) : 2 / Math.abs(dz);
- dx *= f;
- dz *= f;
-
- double other = Math.abs(xGreater ? dz : dx);
-
- if (other <= .5) {
- return xGreater ? (dx < 0 ? BlockFace.WEST : BlockFace.EAST) : (dz < 0 ? BlockFace.NORTH : BlockFace.SOUTH);
- }
-
- if (other < 1.5) {
- if (xGreater) {
- return dx < 0 ? (dz < 0 ? BlockFace.WEST_NORTH_WEST : BlockFace.WEST_SOUTH_WEST) : (dz < 0 ? BlockFace.EAST_NORTH_EAST : BlockFace.EAST_SOUTH_EAST);
- }
- return dx < 0 ? (dz < 0 ? BlockFace.NORTH_NORTH_WEST : BlockFace.SOUTH_SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_NORTH_EAST : BlockFace.SOUTH_SOUTH_EAST);
- }
-
- return dx < 0 ? (dz < 0 ? BlockFace.NORTH_WEST : BlockFace.SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_EAST : BlockFace.SOUTH_EAST);
- }
-
- public static Entity findEntityFromDamager(Entity damager, EntityType searched) {
- if (damager.getType() == searched) {
- return damager;
- }
-
- if (damager instanceof Projectile) {
- ProjectileSource shooter = ((Projectile) damager).getShooter();
- if (shooter instanceof Entity && ((Entity) shooter).getType() == searched) {
- return (Entity) shooter;
- }
- return null;
- }
-
- if (damager.getType() == EntityType.PRIMED_TNT) {
- Entity source = ((TNTPrimed) damager).getSource();
- if (source.getType() == searched) {
- return source;
- }
- }
-
- return null;
- }
-
- public static int xpForNextLevel(int currentLevel) {
- if (currentLevel >= 30) {
- return 112 + (currentLevel - 30) * 9;
- }
-
- if (currentLevel >= 15) {
- return 37 + (currentLevel - 15) * 5;
- }
-
- return 7 + currentLevel * 2;
- }
-
- public static int removeExp(Player entity, int xp) {
- int total = entity.getTotalExperience();
- if (xp > total) {
- xp = total;
- }
-
- int level = entity.getLevel();
- if (level < 0) {
- return 0;
- }
-
- int removed = 0;
- int xpForNextLevel = xpForNextLevel(level);
- int current = (int) entity.getExp() * xpForNextLevel;
-
- if (xp > current) {
- xp -= current;
- total -= current;
- removed += current;
-
- if (level == 0) {
- entity.setExp(0F);
- entity.setTotalExperience(total);
- return removed;
- }
- } else {
- current -= xp;
- total -= xp;
- removed += xp;
-
- entity.setExp((float) current / xpForNextLevel);
- entity.setTotalExperience(total);
- return removed;
- }
-
- do {
- xpForNextLevel = xpForNextLevel(--level);
- if (xpForNextLevel >= xp) {
- total -= xp;
- removed += xp;
-
- entity.setExp(1F / xpForNextLevel * (xpForNextLevel - xp));
- entity.setTotalExperience(total);
- entity.setLevel(level);
- return removed;
- }
-
- xp -= xpForNextLevel;
- total -= xpForNextLevel;
- removed += xpForNextLevel;
- } while (level > 0);
-
- entity.setExp(0F);
- entity.setTotalExperience(0);
- entity.setLevel(0);
- return removed;
- }
-
- public static int getTotalExp(Player entity) {
- int rv = 0;
- int level = Math.min(entity.getLevel(), 20000);
- for (int i = 0; i < level; i++) {
- rv += xpForNextLevel(i);
- }
- rv += Math.min(1F, Math.max(0F, entity.getExp())) * xpForNextLevel(level);
- return rv;
- }
-
- public static double getTotalExpLevels(Player entity) {
- int xp = entity.getTotalExperience();
-
- int level = 0;
- while (xp > 0 && level < 20000) {
- int needed = xpForNextLevel(level);
- if (needed > xp) {
- return level + ((double) xp / needed);
- }
- xp -= needed;
- level++;
- }
-
- return level;
- }
-
- public static int getNearbyPlayerCount(Player origin, double range, Predicate<Player> predicate) {
- List<Entity> entities = origin.getNearbyEntities(range, range, range);
- int result = 0;
- for (Entity entity : entities) {
- if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
- result++;
- }
- }
- return result;
- }
-
- public static void getNearbyPlayers(Player origin, double range, Collection<Player> collection, Predicate<Player> predicate) {
- List<Entity> entities = origin.getNearbyEntities(range, range, range);
- for (Entity entity : entities) {
- if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
- collection.add((Player) entity);
- }
- }
- }
-
- public static void forEachNearbyPlayer(Player origin, double range, Consumer<Player> action) {
- List<Entity> entities = origin.getNearbyEntities(range, range, range);
- for (Entity entity : entities) {
- if (entity.getType() == EntityType.PLAYER) {
- action.accept((Player) entity);
- }
- }
- }
-
- public static double distanceSquared(Location first, Location second) {
- double dx = first.getX() - second.getX();
- double dy = first.getY() - second.getY();
- double dz = first.getZ() - second.getZ();
-
- return dx * dx + dy * dy + dz * dz;
- }
-
-
- public static <T extends Entity> Iterator<T> findNearbyEntities(Entity origin, boolean includeSelf, Predicate<Entity> predicate, double horizontalRange, double verticalRange) {
- Objects.requireNonNull(origin);
- return new Iterator<T>() {
- Entity next;
- List<Entity> nearby;
- int index = 0;
- int size;
-
- {
- if (includeSelf) {
- next = origin;
- } else {
- next = findNext();
- }
- }
-
- Entity findNext() {
- if (nearby == null) {
- nearby = origin.getNearbyEntities(horizontalRange, verticalRange, horizontalRange);
- size = nearby.size();
- }
-
- while (index < size) {
- Entity e = nearby.get(index++);
- if (predicate.test(e)) {
- return e;
- }
- }
-
- return null;
- }
-
- @Override
- public boolean hasNext() {
- return next != null;
- }
-
- @Override
- public T next() {
- if (next == null) {
- throw new NoSuchElementException();
- }
- Entity result = next;
- next = findNext();
- //noinspection unchecked
- return (T) result;
- }
-
- };
- }
-
-
-}
+package io.dico.dicore;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockFace;
+import org.bukkit.block.BlockState;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.entity.*;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.material.Attachable;
+import org.bukkit.material.MaterialData;
+import org.bukkit.projectiles.ProjectileSource;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public class SpigotUtil {
+
+ private SpigotUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ public static World matchWorld(String input) {
+ try {
+ UUID uid = UUID.fromString(input);
+ World world = Bukkit.getWorld(uid);
+ if (world != null) {
+ return world;
+ }
+ } catch (IllegalArgumentException ignored) {
+ }
+
+ World result = Bukkit.getWorld(input);
+ if (result == null) {
+ input = input.toLowerCase().replace("_", "").replaceAll("[-_]", "");
+ for (World world : Bukkit.getWorlds()) {
+ if (world.getName().toLowerCase().equals(input)) {
+ result = world;
+ break;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ public static Block getSupportingBlock(Block block) {
+ MaterialData data = block.getState().getData();
+ if (data instanceof Attachable) {
+ BlockFace attachedOn = ((Attachable) data).getAttachedFace();
+ return block.getRelative(attachedOn);
+ }
+ return null;
+ }
+
+ public static boolean isItemPresent(ItemStack stack) {
+ return stack != null && stack.getType() != Material.AIR && stack.getAmount() > 0;
+ }
+
+ public static boolean removeItems(Inventory from, ItemStack item, int amount) {
+ for (Map.Entry<Integer, ? extends ItemStack> entry : from.all(item.getType()).entrySet()) {
+ ItemStack stack = entry.getValue();
+ if (item.isSimilar(stack)) {
+ amount -= stack.getAmount();
+ int stackAmount = -Math.min(0, amount);
+ if (stackAmount == 0) {
+ from.setItem(entry.getKey(), null);
+ } else {
+ stack.setAmount(stackAmount);
+ }
+ }
+ }
+ return amount <= 0;
+ }
+
+ public static BlockFace yawToFace(float yaw) {
+ if ((yaw %= 360) < 0)
+ yaw += 360;
+ if (45 <= yaw && yaw < 135)
+ return BlockFace.WEST;
+ if (135 <= yaw && yaw < 225)
+ return BlockFace.NORTH;
+ if (225 <= yaw && yaw < 315)
+ return BlockFace.EAST;
+ return BlockFace.SOUTH;
+ }
+
+ public static void addItems(InventoryHolder entity, ItemStack... items) {
+ Location dropLocation;
+ if (entity instanceof Entity) {
+ dropLocation = ((Entity) entity).getLocation();
+ } else if (entity instanceof BlockState) {
+ dropLocation = ((BlockState) entity).getLocation().add(0.5, 1, 0.5);
+ } else {
+ throw new IllegalArgumentException("Can't find location of this InventoryHolder: " + entity);
+ }
+ World world = dropLocation.getWorld();
+ for (ItemStack toDrop : entity.getInventory().addItem(items).values()) {
+ world.dropItemNaturally(dropLocation, toDrop);
+ }
+ }
+
+ public static String asJsonString(Object object) {
+ return asJsonString(null, object, 0);
+ }
+
+ public static String asJsonString(String key, Object object, int indentation) {
+ String indent = new String(new char[indentation * 2]).replace('\0', ' ');
+ StringBuilder builder = new StringBuilder(indent);
+ if (key != null) {
+ builder.append(key).append(": ");
+ }
+ if (object instanceof ConfigurationSerializable) {
+ object = ((ConfigurationSerializable) object).serialize();
+ }
+ if (object instanceof Map) {
+ builder.append("{\n");
+ Map<?, ?> map = (Map) object;
+ for (Map.Entry entry : map.entrySet()) {
+ builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1));
+ }
+ builder.append(indent).append("}");
+ } else if (object instanceof List) {
+ builder.append("[\n");
+ List list = (List) object;
+ for (Object entry : list) {
+ builder.append(asJsonString(null, entry, indentation + 1));
+ }
+ builder.append(indent).append("]");
+ } else {
+ builder.append(String.valueOf(object));
+ }
+ return builder.append(",\n").toString();
+ }
+
+ public static String asJsonString(String key, Object object, int indentation, BiConsumer<List<?>, StringBuilder> listHeader) {
+ String indent = new String(new char[indentation * 2]).replace('\0', ' ');
+ StringBuilder builder = new StringBuilder(indent);
+ if (key != null) {
+ builder.append(key).append(": ");
+ }
+ if (object instanceof ConfigurationSerializable) {
+ object = ((ConfigurationSerializable) object).serialize();
+ }
+ if (object instanceof Map) {
+ builder.append("{\n");
+ Map<?, ?> map = (Map) object;
+ for (Map.Entry entry : map.entrySet()) {
+ builder.append(asJsonString(String.valueOf(entry.getKey()), entry.getValue(), indentation + 1, listHeader));
+ }
+ builder.append(indent).append("}");
+ } else if (object instanceof List) {
+ builder.append("[");
+ List list = (List) object;
+ listHeader.accept(list, builder);
+ builder.append("\n");
+ for (Object entry : list) {
+ builder.append(asJsonString(null, entry, indentation + 1, listHeader));
+ }
+ builder.append(indent).append("]");
+ } else {
+ builder.append(String.valueOf(object));
+ }
+ return builder.append(",\n").toString();
+ }
+
+ public static BlockFace estimateDirectionTo(Location from, Location to) {
+ double dx = from.getX() - to.getX();
+ double dz = from.getZ() - to.getZ();
+
+ boolean xGreater = Math.abs(dx) - Math.abs(dz) > 0;
+ double f = xGreater ? 2 / Math.abs(dx) : 2 / Math.abs(dz);
+ dx *= f;
+ dz *= f;
+
+ double other = Math.abs(xGreater ? dz : dx);
+
+ if (other <= .5) {
+ return xGreater ? (dx < 0 ? BlockFace.WEST : BlockFace.EAST) : (dz < 0 ? BlockFace.NORTH : BlockFace.SOUTH);
+ }
+
+ if (other < 1.5) {
+ if (xGreater) {
+ return dx < 0 ? (dz < 0 ? BlockFace.WEST_NORTH_WEST : BlockFace.WEST_SOUTH_WEST) : (dz < 0 ? BlockFace.EAST_NORTH_EAST : BlockFace.EAST_SOUTH_EAST);
+ }
+ return dx < 0 ? (dz < 0 ? BlockFace.NORTH_NORTH_WEST : BlockFace.SOUTH_SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_NORTH_EAST : BlockFace.SOUTH_SOUTH_EAST);
+ }
+
+ return dx < 0 ? (dz < 0 ? BlockFace.NORTH_WEST : BlockFace.SOUTH_WEST) : (dz < 0 ? BlockFace.NORTH_EAST : BlockFace.SOUTH_EAST);
+ }
+
+ public static Entity findEntityFromDamager(Entity damager, EntityType searched) {
+ if (damager.getType() == searched) {
+ return damager;
+ }
+
+ if (damager instanceof Projectile) {
+ ProjectileSource shooter = ((Projectile) damager).getShooter();
+ if (shooter instanceof Entity && ((Entity) shooter).getType() == searched) {
+ return (Entity) shooter;
+ }
+ return null;
+ }
+
+ if (damager.getType() == EntityType.PRIMED_TNT) {
+ Entity source = ((TNTPrimed) damager).getSource();
+ if (source.getType() == searched) {
+ return source;
+ }
+ }
+
+ return null;
+ }
+
+ public static int xpForNextLevel(int currentLevel) {
+ if (currentLevel >= 30) {
+ return 112 + (currentLevel - 30) * 9;
+ }
+
+ if (currentLevel >= 15) {
+ return 37 + (currentLevel - 15) * 5;
+ }
+
+ return 7 + currentLevel * 2;
+ }
+
+ public static int removeExp(Player entity, int xp) {
+ int total = entity.getTotalExperience();
+ if (xp > total) {
+ xp = total;
+ }
+
+ int level = entity.getLevel();
+ if (level < 0) {
+ return 0;
+ }
+
+ int removed = 0;
+ int xpForNextLevel = xpForNextLevel(level);
+ int current = (int) entity.getExp() * xpForNextLevel;
+
+ if (xp > current) {
+ xp -= current;
+ total -= current;
+ removed += current;
+
+ if (level == 0) {
+ entity.setExp(0F);
+ entity.setTotalExperience(total);
+ return removed;
+ }
+ } else {
+ current -= xp;
+ total -= xp;
+ removed += xp;
+
+ entity.setExp((float) current / xpForNextLevel);
+ entity.setTotalExperience(total);
+ return removed;
+ }
+
+ do {
+ xpForNextLevel = xpForNextLevel(--level);
+ if (xpForNextLevel >= xp) {
+ total -= xp;
+ removed += xp;
+
+ entity.setExp(1F / xpForNextLevel * (xpForNextLevel - xp));
+ entity.setTotalExperience(total);
+ entity.setLevel(level);
+ return removed;
+ }
+
+ xp -= xpForNextLevel;
+ total -= xpForNextLevel;
+ removed += xpForNextLevel;
+ } while (level > 0);
+
+ entity.setExp(0F);
+ entity.setTotalExperience(0);
+ entity.setLevel(0);
+ return removed;
+ }
+
+ public static int getTotalExp(Player entity) {
+ int rv = 0;
+ int level = Math.min(entity.getLevel(), 20000);
+ for (int i = 0; i < level; i++) {
+ rv += xpForNextLevel(i);
+ }
+ rv += Math.min(1F, Math.max(0F, entity.getExp())) * xpForNextLevel(level);
+ return rv;
+ }
+
+ public static double getTotalExpLevels(Player entity) {
+ int xp = entity.getTotalExperience();
+
+ int level = 0;
+ while (xp > 0 && level < 20000) {
+ int needed = xpForNextLevel(level);
+ if (needed > xp) {
+ return level + ((double) xp / needed);
+ }
+ xp -= needed;
+ level++;
+ }
+
+ return level;
+ }
+
+ public static int getNearbyPlayerCount(Player origin, double range, Predicate<Player> predicate) {
+ List<Entity> entities = origin.getNearbyEntities(range, range, range);
+ int result = 0;
+ for (Entity entity : entities) {
+ if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
+ result++;
+ }
+ }
+ return result;
+ }
+
+ public static void getNearbyPlayers(Player origin, double range, Collection<Player> collection, Predicate<Player> predicate) {
+ List<Entity> entities = origin.getNearbyEntities(range, range, range);
+ for (Entity entity : entities) {
+ if (entity.getType() == EntityType.PLAYER && predicate.test((Player) entity)) {
+ collection.add((Player) entity);
+ }
+ }
+ }
+
+ public static void forEachNearbyPlayer(Player origin, double range, Consumer<Player> action) {
+ List<Entity> entities = origin.getNearbyEntities(range, range, range);
+ for (Entity entity : entities) {
+ if (entity.getType() == EntityType.PLAYER) {
+ action.accept((Player) entity);
+ }
+ }
+ }
+
+ public static double distanceSquared(Location first, Location second) {
+ double dx = first.getX() - second.getX();
+ double dy = first.getY() - second.getY();
+ double dz = first.getZ() - second.getZ();
+
+ return dx * dx + dy * dy + dz * dz;
+ }
+
+
+ public static <T extends Entity> Iterator<T> findNearbyEntities(Entity origin, boolean includeSelf, Predicate<Entity> predicate, double horizontalRange, double verticalRange) {
+ Objects.requireNonNull(origin);
+ return new Iterator<T>() {
+ Entity next;
+ List<Entity> nearby;
+ int index = 0;
+ int size;
+
+ {
+ if (includeSelf) {
+ next = origin;
+ } else {
+ next = findNext();
+ }
+ }
+
+ Entity findNext() {
+ if (nearby == null) {
+ nearby = origin.getNearbyEntities(horizontalRange, verticalRange, horizontalRange);
+ size = nearby.size();
+ }
+
+ while (index < size) {
+ Entity e = nearby.get(index++);
+ if (predicate.test(e)) {
+ return e;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ @Override
+ public T next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ Entity result = next;
+ next = findNext();
+ //noinspection unchecked
+ return (T) result;
+ }
+
+ };
+ }
+
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/StringUtil.java b/dicore3/core/src/main/java/io/dico/dicore/StringUtil.java
index 62a389e..fb76755 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/StringUtil.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/StringUtil.java
@@ -1,473 +1,473 @@
-package io.dico.dicore;
-
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.IntStream;
-
-public class StringUtil {
-
- public static String capitalize(String input) {
- if (input.length() > 0) {
- char first = input.charAt(0);
- if (first != (first = Character.toUpperCase(first))) {
- char[] result = input.toCharArray();
- result[0] = first;
- return String.valueOf(result);
- }
- }
- return input;
- }
-
- /**
- * Capitalizes the first character of the string or the first character of each word
- *
- * @param input the string to capitalize
- * @param spaceChar the character separating each word. If @code '\0' is passed, only the first character of
- * the input is capitalized.
- * @return the capitalized string
- */
- public static String capitalize(String input, char spaceChar) {
- if (spaceChar == '\0') {
- return capitalize(input);
- }
-
- char[] result = null;
- boolean capitalize = true;
- for (int n = input.length(), i = 0; i < n; i++) {
- char c = input.charAt(i);
- if (capitalize && c != (c = Character.toUpperCase(c))) {
- if (result == null) result = input.toCharArray();
- result[i] = c;
- }
- capitalize = c == spaceChar;
- }
- return result != null ? String.valueOf(result) : input;
- }
-
- public static String capitalize(String input, char spaceChar, char newSpaceChar) {
- if (newSpaceChar == '\0') {
- return capitalize(input, spaceChar);
- }
-
- char[] result = null;
- boolean capitalize = true;
- for (int n = input.length(), i = 0; i < n; i++) {
- char c = input.charAt(i);
- if (capitalize && c != (c = Character.toUpperCase(c))) {
- if (result == null) result = input.toCharArray();
- result[i] = c;
- }
- if (capitalize = c == spaceChar) {
- if (result == null) result = input.toCharArray();
- result[i] = newSpaceChar;
- }
- }
- return result != null ? String.valueOf(result) : input;
- }
-
- /**
- * Returns a lowercase version of the input with _ replaced with a space.
- * Mainly used for making names of enum constants readable.
- *
- * @param input
- * @return a humanified version of @code input
- */
- public static String humanify(String input) {
- return input == null ? null : input.toLowerCase().replace('_', ' ');
- }
-
- /**
- * Enumerate the given items, separating them by ", " and finally by " and "
- *
- * @param words the items to enumerate (it's not really enumerating....)
- * @return the enumerated string
- */
- public static String enumerate(String... words) {
- StringBuilder result = new StringBuilder();
- int size = words.length;
- int secondLastIndex = size - 2;
- for (int i = 0; i < size; i++) {
- String word = words[i];
- if (word.isEmpty())
- continue;
- result.append(word);
- if (i < secondLastIndex)
- result.append(", ");
- else if (i == secondLastIndex)
- result.append(" and ");
- }
- return result.toString();
- }
-
- public static String enumerate(String list, String regex) {
- return enumerate(list.split(regex));
- }
-
- /**
- * Return a formatted string of the length in millis, containing days, hours and minutes.
- *
- * @param length The delay in milliseconds
- * @return the formatted string
- */
- public static String getTimeLength(long length) {
- int minute = 60000; // in millis
- int hour = 60 * minute;
- int day = 24 * hour;
-
- int minutes = (int) ((length / minute) % 60);
- int hours = (int) ((length / hour) % 24);
- int days = (int) (length / day); //returns floor
-
- String result = ""; // It will be splitted at "|"
- if (days != 0)
- result += days + " days|";
- if (hours != 0)
- result += hours + " hours|";
- if (minutes != 0)
- result += minutes + " minutes|";
- return enumerate(result.split("\\|"));
- }
-
- /**
- * Return a formatted String to represent the given time length, in the given units
- *
- * @param sourceAmount Amount of delay
- * @param sourceUnit Unit of delay
- * @param ifEmpty the String to return if the
- * @param displayedUnits units displayed
- * @return the formatted string
- * @throws IllegalArgumentException if there are no displayed units
- */
- public static String getTimeLength(long sourceAmount, TimeUnit sourceUnit, String ifEmpty, TimeUnit... displayedUnits) {
- if (displayedUnits.length == 0) {
- throw new IllegalArgumentException("No displayed units");
- }
- Arrays.sort(displayedUnits, Collections.reverseOrder(TimeUnit::compareTo)); // sort by opposite of enum declaration order (largest -> smallest)
- List<String> segments = new ArrayList<>(displayedUnits.length);
- for (TimeUnit unit : displayedUnits) {
- long displayedAmount = unit.convert(sourceAmount, sourceUnit);
- sourceAmount -= sourceUnit.convert(displayedAmount, unit);
- if (displayedAmount > 0) {
- String unitWord = unit.name().toLowerCase(); // plural
- if (displayedAmount == 1) {
- unitWord = unitWord.substring(0, unitWord.length() - 1); // remove s at the end
- }
- segments.add(displayedAmount + " " + unitWord);
- }
- }
- return segments.isEmpty() ? ifEmpty : enumerate(segments.toArray(new String[segments.size()]));
- }
-
- /**
- * Returns the delay represented by a ban-like delay representation, in milliseconds
- * Example: "5d2h5m3s" for 5 days, 2 hours, 5 minutes and 3 seconds.
- * <p>
- * Supported characters are s, m, h, d, w.
- * Negative numbers are supported.
- *
- * @param input The input string
- * @return The delay in milliseconds
- * @throws IllegalArgumentException if the input string isn't properly formatted, or any non-digit character isn't recognized (capitals are not recognized).
- */
- public static long getTimeLength(String input) { //if -1: error
- long count = 0;
- int i = 0;
- while (i < input.length()) {
- int num = 0;
- char unit = '\0';
- boolean negate;
- if (negate = input.charAt(i) == '-') {
- i++;
- }
- do {
- char c = input.charAt(i);
- int digit = c - '0';
- if (0 <= digit && digit < 10) {
- num = 10 * num + digit;
- } else {
- unit = c;
- break;
- }
- } while (i < input.length());
-
- long unitTime = getUnitTime(unit);
- if (unitTime == -1)
- throw new IllegalArgumentException();
- if (negate) {
- unitTime = -unitTime;
- }
- count += (num * unitTime);
- }
- return count;
- }
-
- /**
- * Returns the time represented by the given unit character in milliseconds.
- * <p>
- * 's' -> 1000
- * 'm' -> 1000 * 60
- * 'h' -> 1000 * 60 * 60
- * 'd' -> 1000 * 60 * 60 * 24
- * 'w' -> 1000 * 60 * 60 * 24 * 7
- * anything else -> -1
- *
- * @param unit The unit character, as shown above
- * @return the millisecond delay represented by the unit
- */
- public static long getUnitTime(char unit) { //if -1: no value found
- switch (Character.toLowerCase(unit)) {
- case 's':
- return 1000;
- case 'm':
- return 1000 * 60;
- case 'h':
- return 1000 * 60 * 60;
- case 'd':
- return 1000 * 60 * 60 * 24;
- case 'w':
- return 1000 * 60 * 60 * 24 * 7;
- default:
- return -1;
- }
- }
-
- /**
- * Computes a binary representation of the value.
- * The returned representation always displays 64 bits.
- * Every 8 bits, the digits are seperated by an _
- * The representation is prefixed by 0b.
- * <p>
- * Example: 0b00000000_11111111_00000001_11110000_00001111_11001100_00001111_10111010
- *
- * @param entry the value to represent in binary
- * @return A binary representation of the long value
- */
- public static String toBinaryString(long entry) {
- String binary = Long.toBinaryString(entry);
- String binary64 = String.valueOf(new char[64 - binary.length()]).replace('\0', '0') + binary;
- String withUnderscores = String.join("_", IntStream.range(0, 8).mapToObj(x -> binary64.substring(x * 8, x * 8 + 8)).toArray(String[]::new));
- return "0b" + withUnderscores;
- }
-
- /**
- * Turns a generic java classname into a name formatted properly to be an enum constant.
- *
- * @param name The string value I'd describe as a generic java classname (so we have CapitalCase)
- * @return An enum constant version of it (ENUM_FORMAT: CAPITAL_CASE)
- */
- public static String toEnumFormat(String name) {
- StringBuilder result = new StringBuilder(name.length() + 2);
-
- boolean capital = true;
- for (int i = 0, n = name.length(); i < n; i++) {
- char c = name.charAt(i);
- if (capital) {
- capital = Character.isUpperCase(c);
- } else if (Character.isUpperCase(c)) {
- capital = true;
- result.append('_');
- }
- result.append(capital ? c : Character.toUpperCase(c));
- }
-
- return result.toString();
- }
-
- /**
- * Replaces any occurrence of toReplace with another string.
- * Any colours that occured before the occurence of toReplace, are copied to the end of the replacement.
- *
- * @param target The String to query
- * @param toReplace The sequence to replace
- * @param with the replacing sequence
- * @return the result
- */
- public static String replaceKeepColours(String target, String toReplace, String with) {
- int index = -toReplace.length();
- while ((index = target.indexOf(toReplace, index + toReplace.length())) != -1) {
- String start = target.substring(0, index);
- Formatting coloursBefore = Formatting.getFormats(start);
- String after;
- try {
- after = target.substring(index + toReplace.length());
- } catch (IndexOutOfBoundsException e) {
- after = "";
- }
- target = start + with + coloursBefore + after;
- }
- return target;
- }
-
- public static String replParam(String target, String param, Object repl) {
- return replParam(target, param, repl, false);
- }
-
- public static String replParams(String target, String[] params, Object[] repls) {
- return replParams(target, params, repls, false, false);
- }
-
- public static boolean replParams(String[] target, String[] params, Object[] repls) {
- return replParams(target, 0, target.length, params, repls);
- }
-
- public static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls) {
- return replParams(target, from, to, params, repls, false);
- }
-
- public static boolean replParams(List<String> target, String[] params, Object[] repls) {
- return replParams(target, 0, target.size(), params, repls);
- }
-
- public static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls) {
- return replParams(target, from, to, params, repls, false);
- }
-
- public static String replParamAndTranslate(String target, String param, Object repl) {
- return replParam(target, param, repl, true);
- }
-
- public static String replParamsAndTranslate(String target, String[] params, Object[] repls) {
- return replParams(target, params, repls, false, true);
- }
-
- public static boolean replParamsAndTranslate(String[] target, String[] params, Object[] repls) {
- return replParamsAndTranslate(target, 0, target.length, params, repls);
- }
-
- public static boolean replParamsAndTranslate(String[] target, int from, int to, String[] params, Object[] repls) {
- return replParams(target, from, to, params, repls, true);
- }
-
- public static boolean replParamsAndTranslate(List<String> target, String[] params, Object[] repls) {
- return replParamsAndTranslate(target, 0, target.size(), params, repls);
- }
-
- public static boolean replParamsAndTranslate(List<String> target, int from, int to, String[] params, Object[] repls) {
- return replParams(target, from, to, params, repls, true);
- }
-
- private static String replParam(String target, String param, Object replacementObj, boolean translate) {
- int idx = target.indexOf(param, 0);
- if (idx == -1) {
- return translate ? Formatting.translate(target) : target;
- }
-
- String rep = replacementObj.toString();
- StringBuilder builder = new StringBuilder(target);
- do {
- builder.replace(idx, idx + param.length(), rep);
- idx = builder.indexOf(param, idx + rep.length());
- } while (idx != -1);
-
- if (translate) {
- Formatting.translate(builder);
- }
-
- return builder.toString();
- }
-
- @SuppressWarnings("StringEquality")
- private static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls, boolean translate) {
- if (from < 0 || to < from || to > target.length) {
- throw new IllegalArgumentException("Invalid from-to for array size " + target.length + ": " + from + "-" + to);
- }
-
- boolean change = false;
- for (int i = from; i < to; i++) {
- String val = target[i];
- if (val != (val = replParams(val, params, repls, true, translate))) {
- target[i] = val;
- change = true;
- }
- }
- return change;
- }
-
- @SuppressWarnings("StringEquality")
- private static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls, boolean translate) {
- if (from < 0 || to < from || to > target.size()) {
- throw new IllegalArgumentException("Invalid from-to for list size " + target.size() + ": " + from + "-" + to);
- }
-
- boolean change = false;
- if (target instanceof RandomAccess) {
- for (int i = from; i < to; i++) {
- String val = target.get(i);
- if (val != (val = replParams(val, params, repls, true, translate))) {
- target.set(i, val);
- change = true;
- }
- }
- } else {
- ListIterator<String> itr = target.listIterator(from);
- for (int n = to - from, i = 0; i < n && itr.hasNext(); i++) {
- String val = itr.next();
- if (val != (val = replParams(val, params, repls, true, translate))) {
- itr.set(val);
- change = true;
- }
- }
- }
- return change;
- }
-
- private static String replParams(String target, String[] params, Object[] repls, boolean updateRepls, boolean translate) {
- int n = params.length;
- if (n != repls.length) {
- throw new IllegalArgumentException();
- }
-
- String param = null;
- int idx = -1;
- int i;
- for (i = 0; i < n; i++) {
- param = params[i];
- if (param == null) {
- continue;
- }
- idx = target.indexOf(param, 0);
- if (idx != -1) {
- break;
- }
- }
-
- if (idx == -1) {
- return translate ? Formatting.translate(target) : target;
- }
-
- String repl = repls[i].toString();
- if (updateRepls) {
- repls[i] = repl;
- }
-
- StringBuilder builder = new StringBuilder(target);
- do {
- builder.replace(idx, idx + param.length(), repl);
- idx = builder.indexOf(param, idx + repl.length());
- } while (idx != -1);
-
- for (i++; i < n; i++) {
- param = params[i];
- if (param == null || (idx = builder.indexOf(param, 0)) == -1) {
- continue;
- }
-
- repl = repls[i].toString();
- if (updateRepls) {
- repls[i] = repl;
- }
-
- do {
- builder.replace(idx, idx + param.length(), repl);
- idx = builder.indexOf(param, idx + repl.length());
- } while (idx != -1);
- }
-
- if (translate) {
- Formatting.translate(builder);
- }
-
- return builder.toString();
- }
-
-}
+package io.dico.dicore;
+
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+public class StringUtil {
+
+ public static String capitalize(String input) {
+ if (input.length() > 0) {
+ char first = input.charAt(0);
+ if (first != (first = Character.toUpperCase(first))) {
+ char[] result = input.toCharArray();
+ result[0] = first;
+ return String.valueOf(result);
+ }
+ }
+ return input;
+ }
+
+ /**
+ * Capitalizes the first character of the string or the first character of each word
+ *
+ * @param input the string to capitalize
+ * @param spaceChar the character separating each word. If @code '\0' is passed, only the first character of
+ * the input is capitalized.
+ * @return the capitalized string
+ */
+ public static String capitalize(String input, char spaceChar) {
+ if (spaceChar == '\0') {
+ return capitalize(input);
+ }
+
+ char[] result = null;
+ boolean capitalize = true;
+ for (int n = input.length(), i = 0; i < n; i++) {
+ char c = input.charAt(i);
+ if (capitalize && c != (c = Character.toUpperCase(c))) {
+ if (result == null) result = input.toCharArray();
+ result[i] = c;
+ }
+ capitalize = c == spaceChar;
+ }
+ return result != null ? String.valueOf(result) : input;
+ }
+
+ public static String capitalize(String input, char spaceChar, char newSpaceChar) {
+ if (newSpaceChar == '\0') {
+ return capitalize(input, spaceChar);
+ }
+
+ char[] result = null;
+ boolean capitalize = true;
+ for (int n = input.length(), i = 0; i < n; i++) {
+ char c = input.charAt(i);
+ if (capitalize && c != (c = Character.toUpperCase(c))) {
+ if (result == null) result = input.toCharArray();
+ result[i] = c;
+ }
+ if (capitalize = c == spaceChar) {
+ if (result == null) result = input.toCharArray();
+ result[i] = newSpaceChar;
+ }
+ }
+ return result != null ? String.valueOf(result) : input;
+ }
+
+ /**
+ * Returns a lowercase version of the input with _ replaced with a space.
+ * Mainly used for making names of enum constants readable.
+ *
+ * @param input
+ * @return a humanified version of @code input
+ */
+ public static String humanify(String input) {
+ return input == null ? null : input.toLowerCase().replace('_', ' ');
+ }
+
+ /**
+ * Enumerate the given items, separating them by ", " and finally by " and "
+ *
+ * @param words the items to enumerate (it's not really enumerating....)
+ * @return the enumerated string
+ */
+ public static String enumerate(String... words) {
+ StringBuilder result = new StringBuilder();
+ int size = words.length;
+ int secondLastIndex = size - 2;
+ for (int i = 0; i < size; i++) {
+ String word = words[i];
+ if (word.isEmpty())
+ continue;
+ result.append(word);
+ if (i < secondLastIndex)
+ result.append(", ");
+ else if (i == secondLastIndex)
+ result.append(" and ");
+ }
+ return result.toString();
+ }
+
+ public static String enumerate(String list, String regex) {
+ return enumerate(list.split(regex));
+ }
+
+ /**
+ * Return a formatted string of the length in millis, containing days, hours and minutes.
+ *
+ * @param length The delay in milliseconds
+ * @return the formatted string
+ */
+ public static String getTimeLength(long length) {
+ int minute = 60000; // in millis
+ int hour = 60 * minute;
+ int day = 24 * hour;
+
+ int minutes = (int) ((length / minute) % 60);
+ int hours = (int) ((length / hour) % 24);
+ int days = (int) (length / day); //returns floor
+
+ String result = ""; // It will be splitted at "|"
+ if (days != 0)
+ result += days + " days|";
+ if (hours != 0)
+ result += hours + " hours|";
+ if (minutes != 0)
+ result += minutes + " minutes|";
+ return enumerate(result.split("\\|"));
+ }
+
+ /**
+ * Return a formatted String to represent the given time length, in the given units
+ *
+ * @param sourceAmount Amount of delay
+ * @param sourceUnit Unit of delay
+ * @param ifEmpty the String to return if the
+ * @param displayedUnits units displayed
+ * @return the formatted string
+ * @throws IllegalArgumentException if there are no displayed units
+ */
+ public static String getTimeLength(long sourceAmount, TimeUnit sourceUnit, String ifEmpty, TimeUnit... displayedUnits) {
+ if (displayedUnits.length == 0) {
+ throw new IllegalArgumentException("No displayed units");
+ }
+ Arrays.sort(displayedUnits, Collections.reverseOrder(TimeUnit::compareTo)); // sort by opposite of enum declaration order (largest -> smallest)
+ List<String> segments = new ArrayList<>(displayedUnits.length);
+ for (TimeUnit unit : displayedUnits) {
+ long displayedAmount = unit.convert(sourceAmount, sourceUnit);
+ sourceAmount -= sourceUnit.convert(displayedAmount, unit);
+ if (displayedAmount > 0) {
+ String unitWord = unit.name().toLowerCase(); // plural
+ if (displayedAmount == 1) {
+ unitWord = unitWord.substring(0, unitWord.length() - 1); // remove s at the end
+ }
+ segments.add(displayedAmount + " " + unitWord);
+ }
+ }
+ return segments.isEmpty() ? ifEmpty : enumerate(segments.toArray(new String[segments.size()]));
+ }
+
+ /**
+ * Returns the delay represented by a ban-like delay representation, in milliseconds
+ * Example: "5d2h5m3s" for 5 days, 2 hours, 5 minutes and 3 seconds.
+ * <p>
+ * Supported characters are s, m, h, d, w.
+ * Negative numbers are supported.
+ *
+ * @param input The input string
+ * @return The delay in milliseconds
+ * @throws IllegalArgumentException if the input string isn't properly formatted, or any non-digit character isn't recognized (capitals are not recognized).
+ */
+ public static long getTimeLength(String input) { //if -1: error
+ long count = 0;
+ int i = 0;
+ while (i < input.length()) {
+ int num = 0;
+ char unit = '\0';
+ boolean negate;
+ if (negate = input.charAt(i) == '-') {
+ i++;
+ }
+ do {
+ char c = input.charAt(i);
+ int digit = c - '0';
+ if (0 <= digit && digit < 10) {
+ num = 10 * num + digit;
+ } else {
+ unit = c;
+ break;
+ }
+ } while (i < input.length());
+
+ long unitTime = getUnitTime(unit);
+ if (unitTime == -1)
+ throw new IllegalArgumentException();
+ if (negate) {
+ unitTime = -unitTime;
+ }
+ count += (num * unitTime);
+ }
+ return count;
+ }
+
+ /**
+ * Returns the time represented by the given unit character in milliseconds.
+ * <p>
+ * 's' -> 1000
+ * 'm' -> 1000 * 60
+ * 'h' -> 1000 * 60 * 60
+ * 'd' -> 1000 * 60 * 60 * 24
+ * 'w' -> 1000 * 60 * 60 * 24 * 7
+ * anything else -> -1
+ *
+ * @param unit The unit character, as shown above
+ * @return the millisecond delay represented by the unit
+ */
+ public static long getUnitTime(char unit) { //if -1: no value found
+ switch (Character.toLowerCase(unit)) {
+ case 's':
+ return 1000;
+ case 'm':
+ return 1000 * 60;
+ case 'h':
+ return 1000 * 60 * 60;
+ case 'd':
+ return 1000 * 60 * 60 * 24;
+ case 'w':
+ return 1000 * 60 * 60 * 24 * 7;
+ default:
+ return -1;
+ }
+ }
+
+ /**
+ * Computes a binary representation of the value.
+ * The returned representation always displays 64 bits.
+ * Every 8 bits, the digits are seperated by an _
+ * The representation is prefixed by 0b.
+ * <p>
+ * Example: 0b00000000_11111111_00000001_11110000_00001111_11001100_00001111_10111010
+ *
+ * @param entry the value to represent in binary
+ * @return A binary representation of the long value
+ */
+ public static String toBinaryString(long entry) {
+ String binary = Long.toBinaryString(entry);
+ String binary64 = String.valueOf(new char[64 - binary.length()]).replace('\0', '0') + binary;
+ String withUnderscores = String.join("_", IntStream.range(0, 8).mapToObj(x -> binary64.substring(x * 8, x * 8 + 8)).toArray(String[]::new));
+ return "0b" + withUnderscores;
+ }
+
+ /**
+ * Turns a generic java classname into a name formatted properly to be an enum constant.
+ *
+ * @param name The string value I'd describe as a generic java classname (so we have CapitalCase)
+ * @return An enum constant version of it (ENUM_FORMAT: CAPITAL_CASE)
+ */
+ public static String toEnumFormat(String name) {
+ StringBuilder result = new StringBuilder(name.length() + 2);
+
+ boolean capital = true;
+ for (int i = 0, n = name.length(); i < n; i++) {
+ char c = name.charAt(i);
+ if (capital) {
+ capital = Character.isUpperCase(c);
+ } else if (Character.isUpperCase(c)) {
+ capital = true;
+ result.append('_');
+ }
+ result.append(capital ? c : Character.toUpperCase(c));
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Replaces any occurrence of toReplace with another string.
+ * Any colours that occured before the occurence of toReplace, are copied to the end of the replacement.
+ *
+ * @param target The String to query
+ * @param toReplace The sequence to replace
+ * @param with the replacing sequence
+ * @return the result
+ */
+ public static String replaceKeepColours(String target, String toReplace, String with) {
+ int index = -toReplace.length();
+ while ((index = target.indexOf(toReplace, index + toReplace.length())) != -1) {
+ String start = target.substring(0, index);
+ Formatting coloursBefore = Formatting.getFormats(start);
+ String after;
+ try {
+ after = target.substring(index + toReplace.length());
+ } catch (IndexOutOfBoundsException e) {
+ after = "";
+ }
+ target = start + with + coloursBefore + after;
+ }
+ return target;
+ }
+
+ public static String replParam(String target, String param, Object repl) {
+ return replParam(target, param, repl, false);
+ }
+
+ public static String replParams(String target, String[] params, Object[] repls) {
+ return replParams(target, params, repls, false, false);
+ }
+
+ public static boolean replParams(String[] target, String[] params, Object[] repls) {
+ return replParams(target, 0, target.length, params, repls);
+ }
+
+ public static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls) {
+ return replParams(target, from, to, params, repls, false);
+ }
+
+ public static boolean replParams(List<String> target, String[] params, Object[] repls) {
+ return replParams(target, 0, target.size(), params, repls);
+ }
+
+ public static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls) {
+ return replParams(target, from, to, params, repls, false);
+ }
+
+ public static String replParamAndTranslate(String target, String param, Object repl) {
+ return replParam(target, param, repl, true);
+ }
+
+ public static String replParamsAndTranslate(String target, String[] params, Object[] repls) {
+ return replParams(target, params, repls, false, true);
+ }
+
+ public static boolean replParamsAndTranslate(String[] target, String[] params, Object[] repls) {
+ return replParamsAndTranslate(target, 0, target.length, params, repls);
+ }
+
+ public static boolean replParamsAndTranslate(String[] target, int from, int to, String[] params, Object[] repls) {
+ return replParams(target, from, to, params, repls, true);
+ }
+
+ public static boolean replParamsAndTranslate(List<String> target, String[] params, Object[] repls) {
+ return replParamsAndTranslate(target, 0, target.size(), params, repls);
+ }
+
+ public static boolean replParamsAndTranslate(List<String> target, int from, int to, String[] params, Object[] repls) {
+ return replParams(target, from, to, params, repls, true);
+ }
+
+ private static String replParam(String target, String param, Object replacementObj, boolean translate) {
+ int idx = target.indexOf(param, 0);
+ if (idx == -1) {
+ return translate ? Formatting.translate(target) : target;
+ }
+
+ String rep = replacementObj.toString();
+ StringBuilder builder = new StringBuilder(target);
+ do {
+ builder.replace(idx, idx + param.length(), rep);
+ idx = builder.indexOf(param, idx + rep.length());
+ } while (idx != -1);
+
+ if (translate) {
+ Formatting.translate(builder);
+ }
+
+ return builder.toString();
+ }
+
+ @SuppressWarnings("StringEquality")
+ private static boolean replParams(String[] target, int from, int to, String[] params, Object[] repls, boolean translate) {
+ if (from < 0 || to < from || to > target.length) {
+ throw new IllegalArgumentException("Invalid from-to for array size " + target.length + ": " + from + "-" + to);
+ }
+
+ boolean change = false;
+ for (int i = from; i < to; i++) {
+ String val = target[i];
+ if (val != (val = replParams(val, params, repls, true, translate))) {
+ target[i] = val;
+ change = true;
+ }
+ }
+ return change;
+ }
+
+ @SuppressWarnings("StringEquality")
+ private static boolean replParams(List<String> target, int from, int to, String[] params, Object[] repls, boolean translate) {
+ if (from < 0 || to < from || to > target.size()) {
+ throw new IllegalArgumentException("Invalid from-to for list size " + target.size() + ": " + from + "-" + to);
+ }
+
+ boolean change = false;
+ if (target instanceof RandomAccess) {
+ for (int i = from; i < to; i++) {
+ String val = target.get(i);
+ if (val != (val = replParams(val, params, repls, true, translate))) {
+ target.set(i, val);
+ change = true;
+ }
+ }
+ } else {
+ ListIterator<String> itr = target.listIterator(from);
+ for (int n = to - from, i = 0; i < n && itr.hasNext(); i++) {
+ String val = itr.next();
+ if (val != (val = replParams(val, params, repls, true, translate))) {
+ itr.set(val);
+ change = true;
+ }
+ }
+ }
+ return change;
+ }
+
+ private static String replParams(String target, String[] params, Object[] repls, boolean updateRepls, boolean translate) {
+ int n = params.length;
+ if (n != repls.length) {
+ throw new IllegalArgumentException();
+ }
+
+ String param = null;
+ int idx = -1;
+ int i;
+ for (i = 0; i < n; i++) {
+ param = params[i];
+ if (param == null) {
+ continue;
+ }
+ idx = target.indexOf(param, 0);
+ if (idx != -1) {
+ break;
+ }
+ }
+
+ if (idx == -1) {
+ return translate ? Formatting.translate(target) : target;
+ }
+
+ String repl = repls[i].toString();
+ if (updateRepls) {
+ repls[i] = repl;
+ }
+
+ StringBuilder builder = new StringBuilder(target);
+ do {
+ builder.replace(idx, idx + param.length(), repl);
+ idx = builder.indexOf(param, idx + repl.length());
+ } while (idx != -1);
+
+ for (i++; i < n; i++) {
+ param = params[i];
+ if (param == null || (idx = builder.indexOf(param, 0)) == -1) {
+ continue;
+ }
+
+ repl = repls[i].toString();
+ if (updateRepls) {
+ repls[i] = repl;
+ }
+
+ do {
+ builder.replace(idx, idx + param.length(), repl);
+ idx = builder.indexOf(param, idx + repl.length());
+ } while (idx != -1);
+ }
+
+ if (translate) {
+ Formatting.translate(builder);
+ }
+
+ return builder.toString();
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/Whitelist.java b/dicore3/core/src/main/java/io/dico/dicore/Whitelist.java
index 5f8f4e2..e467d91 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/Whitelist.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/Whitelist.java
@@ -1,91 +1,91 @@
-package io.dico.dicore;
-
-import org.bukkit.configuration.ConfigurationSection;
-
-import java.util.*;
-import java.util.function.Function;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-
-@FunctionalInterface
-public interface Whitelist extends Predicate {
-
- Whitelist EVERYTHING = item -> true;
- Whitelist NOTHING = item -> false;
- Whitelist NOT_NULL = Objects::nonNull;
-
- static <T> Predicate<T> everythingAsPredicate() {
- return (Predicate<T>) EVERYTHING;
- }
-
- static <T> Predicate<T> nothingAsPredicate() {
- return (Predicate<T>) NOTHING;
- }
-
- static <T> Predicate<T> notNullAsPredicate() {
- return (Predicate<T>) NOT_NULL;
- }
-
- static Whitelist only(Object item) {
- return item::equals;
- }
-
- static Whitelist not(Object item) {
- return o -> !item.equals(o);
- }
-
- static Whitelist only(Object item1, Object item2) {
- return item -> item1.equals(item) || item2.equals(item);
- }
-
- static Whitelist not(Object item1, Object item2) {
- return item -> !(item1.equals(item) || item2.equals(item));
- }
-
- static Whitelist only(Object[] objects) {
- return new SetBasedWhitelist(objects, false);
- }
-
- static Whitelist not(Object[] objects) {
- return new SetBasedWhitelist(objects, true);
- }
-
- static Whitelist fromConfig(ConfigurationSection section, Function<String, ?> parser) {
- if (section == null) {
- return NOTHING;
- }
- boolean blacklist = section.getBoolean("blacklist", false);
- Set list = section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toSet());
- switch (list.size()) {
- case 0:
- return blacklist ? EVERYTHING : NOTHING;
- case 1: {
- Iterator iterator = list.iterator();
- return blacklist ? not(iterator.next()) : only(iterator.next());
- }
- case 2: {
- Iterator iterator = list.iterator();
- return blacklist ? not(iterator.next(), iterator.next()) : only(iterator.next(), iterator.next());
- }
- default:
- Object item = list.iterator().next();
- if (item instanceof Enum) {
- list = EnumSet.copyOf(list);
- }
- return new SetBasedWhitelist(list, blacklist);
- }
- }
-
- static void copyIntoConfig(ConfigurationSection target, Function<Object, String> mapper, boolean blacklist, Object... objects) {
- target.set("blacklist", blacklist);
- target.set("listed", Arrays.stream(objects).map(mapper).unordered().distinct().collect(Collectors.toList()));
- }
-
- @Override
- default boolean test(Object o) {
- return isWhitelisted(o);
- }
-
- boolean isWhitelisted(Object o);
-}
-
+package io.dico.dicore;
+
+import org.bukkit.configuration.ConfigurationSection;
+
+import java.util.*;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+@FunctionalInterface
+public interface Whitelist extends Predicate {
+
+ Whitelist EVERYTHING = item -> true;
+ Whitelist NOTHING = item -> false;
+ Whitelist NOT_NULL = Objects::nonNull;
+
+ static <T> Predicate<T> everythingAsPredicate() {
+ return (Predicate<T>) EVERYTHING;
+ }
+
+ static <T> Predicate<T> nothingAsPredicate() {
+ return (Predicate<T>) NOTHING;
+ }
+
+ static <T> Predicate<T> notNullAsPredicate() {
+ return (Predicate<T>) NOT_NULL;
+ }
+
+ static Whitelist only(Object item) {
+ return item::equals;
+ }
+
+ static Whitelist not(Object item) {
+ return o -> !item.equals(o);
+ }
+
+ static Whitelist only(Object item1, Object item2) {
+ return item -> item1.equals(item) || item2.equals(item);
+ }
+
+ static Whitelist not(Object item1, Object item2) {
+ return item -> !(item1.equals(item) || item2.equals(item));
+ }
+
+ static Whitelist only(Object[] objects) {
+ return new SetBasedWhitelist(objects, false);
+ }
+
+ static Whitelist not(Object[] objects) {
+ return new SetBasedWhitelist(objects, true);
+ }
+
+ static Whitelist fromConfig(ConfigurationSection section, Function<String, ?> parser) {
+ if (section == null) {
+ return NOTHING;
+ }
+ boolean blacklist = section.getBoolean("blacklist", false);
+ Set list = section.getStringList("listed").stream().map(parser).filter(Objects::nonNull).collect(Collectors.toSet());
+ switch (list.size()) {
+ case 0:
+ return blacklist ? EVERYTHING : NOTHING;
+ case 1: {
+ Iterator iterator = list.iterator();
+ return blacklist ? not(iterator.next()) : only(iterator.next());
+ }
+ case 2: {
+ Iterator iterator = list.iterator();
+ return blacklist ? not(iterator.next(), iterator.next()) : only(iterator.next(), iterator.next());
+ }
+ default:
+ Object item = list.iterator().next();
+ if (item instanceof Enum) {
+ list = EnumSet.copyOf(list);
+ }
+ return new SetBasedWhitelist(list, blacklist);
+ }
+ }
+
+ static void copyIntoConfig(ConfigurationSection target, Function<Object, String> mapper, boolean blacklist, Object... objects) {
+ target.set("blacklist", blacklist);
+ target.set("listed", Arrays.stream(objects).map(mapper).unordered().distinct().collect(Collectors.toList()));
+ }
+
+ @Override
+ default boolean test(Object o) {
+ return isWhitelisted(o);
+ }
+
+ boolean isWhitelisted(Object o);
+}
+
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListener.java b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListener.java
index 93584ea..378424d 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListener.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListener.java
@@ -1,46 +1,46 @@
-package io.dico.dicore.event;
-
-import io.dico.dicore.InterfaceChain;
-
-public interface ChainedListener<T> extends InterfaceChain<SimpleListener<T>, ChainedListener<T>>, SimpleListener<T> {
-
- @Override
- default ChainedListener<T> getEmptyInstance() {
- return ChainedListeners.empty();
- }
-
- @Override
- default ChainedListener<T> withElement(SimpleListener<T> element) {
- if (element == null) {
- return this;
- }
-
- int count = getElementCount() + 1;
- return new ChainedListener<T>() {
- @Override
- public void accept(T event) {
- try {
- ChainedListener.this.accept(event);
- } finally {
- element.accept(event);
- }
- }
-
- @Override
- public ChainedListener<T> withoutLastNode() {
- return ChainedListener.this;
- }
-
- @Override
- public SimpleListener<T> getDelegateOfLastNode() {
- return element;
- }
-
- @Override
- public int getElementCount() {
- return count;
- }
- };
- }
-
-}
+package io.dico.dicore.event;
+
+import io.dico.dicore.InterfaceChain;
+
+public interface ChainedListener<T> extends InterfaceChain<SimpleListener<T>, ChainedListener<T>>, SimpleListener<T> {
+
+ @Override
+ default ChainedListener<T> getEmptyInstance() {
+ return ChainedListeners.empty();
+ }
+
+ @Override
+ default ChainedListener<T> withElement(SimpleListener<T> element) {
+ if (element == null) {
+ return this;
+ }
+
+ int count = getElementCount() + 1;
+ return new ChainedListener<T>() {
+ @Override
+ public void accept(T event) {
+ try {
+ ChainedListener.this.accept(event);
+ } finally {
+ element.accept(event);
+ }
+ }
+
+ @Override
+ public ChainedListener<T> withoutLastNode() {
+ return ChainedListener.this;
+ }
+
+ @Override
+ public SimpleListener<T> getDelegateOfLastNode() {
+ return element;
+ }
+
+ @Override
+ public int getElementCount() {
+ return count;
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandle.java b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandle.java
index 86b8448..875c131 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandle.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandle.java
@@ -1,55 +1,55 @@
-package io.dico.dicore.event;
-
-import io.dico.dicore.InterfaceChain;
-
-public interface ChainedListenerHandle extends InterfaceChain<ListenerHandle, ChainedListenerHandle>, ListenerHandle {
-
- @Override
- default ChainedListenerHandle getEmptyInstance() {
- return ChainedListenerHandles.empty();
- }
-
- @Override
- default ChainedListenerHandle withElement(ListenerHandle element) {
- if (element == null) {
- return this;
- }
-
- int count = getElementCount() + 1;
- return new ChainedListenerHandle() {
- @Override
- public void register() {
- try {
- ChainedListenerHandle.this.register();
- } finally {
- element.register();
- }
- }
-
- @Override
- public void unregister() {
- try {
- ChainedListenerHandle.this.unregister();
- } finally {
- element.unregister();
- }
- }
-
- @Override
- public ChainedListenerHandle withoutLastNode() {
- return ChainedListenerHandle.this;
- }
-
- @Override
- public ListenerHandle getDelegateOfLastNode() {
- return element;
- }
-
- @Override
- public int getElementCount() {
- return count;
- }
- };
- }
-
-}
+package io.dico.dicore.event;
+
+import io.dico.dicore.InterfaceChain;
+
+public interface ChainedListenerHandle extends InterfaceChain<ListenerHandle, ChainedListenerHandle>, ListenerHandle {
+
+ @Override
+ default ChainedListenerHandle getEmptyInstance() {
+ return ChainedListenerHandles.empty();
+ }
+
+ @Override
+ default ChainedListenerHandle withElement(ListenerHandle element) {
+ if (element == null) {
+ return this;
+ }
+
+ int count = getElementCount() + 1;
+ return new ChainedListenerHandle() {
+ @Override
+ public void register() {
+ try {
+ ChainedListenerHandle.this.register();
+ } finally {
+ element.register();
+ }
+ }
+
+ @Override
+ public void unregister() {
+ try {
+ ChainedListenerHandle.this.unregister();
+ } finally {
+ element.unregister();
+ }
+ }
+
+ @Override
+ public ChainedListenerHandle withoutLastNode() {
+ return ChainedListenerHandle.this;
+ }
+
+ @Override
+ public ListenerHandle getDelegateOfLastNode() {
+ return element;
+ }
+
+ @Override
+ public int getElementCount() {
+ return count;
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandles.java b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandles.java
index 0be0508..15c4553 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandles.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListenerHandles.java
@@ -1,63 +1,63 @@
-package io.dico.dicore.event;
-
-public class ChainedListenerHandles {
-
- private ChainedListenerHandles() {
-
- }
-
- private static final ChainedListenerHandle empty = new ChainedListenerHandle() {
- @Override
- public void register() {
-
- }
-
- public void unregister() {
-
- }
-
- @Override
- public ChainedListenerHandle withElement(ListenerHandle other) {
- return ChainedListenerHandles.singleton(other);
- }
-
- @Override
- public int getElementCount() {
- return 0;
- }
-
- @Override
- public ListenerHandle getDelegateOfLastNode() {
- return null;
- }
- };
-
- public static ChainedListenerHandle empty() {
- return empty;
- }
-
- public static ChainedListenerHandle singleton(ListenerHandle element) {
- if (element instanceof ChainedListenerHandle) {
- return (ChainedListenerHandle) element;
- }
- if (element == null) {
- return empty();
- }
- return new ChainedListenerHandle() {
- @Override
- public void register() {
- element.register();
- }
-
- public void unregister() {
- element.unregister();
- }
-
- @Override
- public ListenerHandle getDelegateOfLastNode() {
- return element;
- }
- };
- }
-
-}
+package io.dico.dicore.event;
+
+public class ChainedListenerHandles {
+
+ private ChainedListenerHandles() {
+
+ }
+
+ private static final ChainedListenerHandle empty = new ChainedListenerHandle() {
+ @Override
+ public void register() {
+
+ }
+
+ public void unregister() {
+
+ }
+
+ @Override
+ public ChainedListenerHandle withElement(ListenerHandle other) {
+ return ChainedListenerHandles.singleton(other);
+ }
+
+ @Override
+ public int getElementCount() {
+ return 0;
+ }
+
+ @Override
+ public ListenerHandle getDelegateOfLastNode() {
+ return null;
+ }
+ };
+
+ public static ChainedListenerHandle empty() {
+ return empty;
+ }
+
+ public static ChainedListenerHandle singleton(ListenerHandle element) {
+ if (element instanceof ChainedListenerHandle) {
+ return (ChainedListenerHandle) element;
+ }
+ if (element == null) {
+ return empty();
+ }
+ return new ChainedListenerHandle() {
+ @Override
+ public void register() {
+ element.register();
+ }
+
+ public void unregister() {
+ element.unregister();
+ }
+
+ @Override
+ public ListenerHandle getDelegateOfLastNode() {
+ return element;
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListeners.java b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListeners.java
index 1d2bcd4..44050a2 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListeners.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/ChainedListeners.java
@@ -1,56 +1,56 @@
-package io.dico.dicore.event;
-
-@SuppressWarnings("unchecked")
-public class ChainedListeners {
-
- private static final ChainedListener<?> empty = new ChainedListener<Object>() {
- @Override
- public void accept(Object event) {
-
- }
-
- @Override
- public ChainedListener<Object> withElement(SimpleListener other) {
- return ChainedListeners.singleton(other);
- }
-
- @Override
- public int getElementCount() {
- return 0;
- }
-
- @Override
- public SimpleListener<Object> getDelegateOfLastNode() {
- return null;
- }
- };
-
- private ChainedListeners() {
-
- }
-
- public static <T> ChainedListener<T> empty() {
- return (ChainedListener<T>) empty;
- }
-
- public static <T> ChainedListener<T> singleton(SimpleListener<T> element) {
- if (element instanceof ChainedListener) {
- return (ChainedListener<T>) element;
- }
- if (element == null) {
- return empty();
- }
- return new ChainedListener<T>() {
- @Override
- public void accept(T event) {
- element.accept(event);
- }
-
- @Override
- public SimpleListener getDelegateOfLastNode() {
- return element;
- }
- };
- }
-
-}
+package io.dico.dicore.event;
+
+@SuppressWarnings("unchecked")
+public class ChainedListeners {
+
+ private static final ChainedListener<?> empty = new ChainedListener<Object>() {
+ @Override
+ public void accept(Object event) {
+
+ }
+
+ @Override
+ public ChainedListener<Object> withElement(SimpleListener other) {
+ return ChainedListeners.singleton(other);
+ }
+
+ @Override
+ public int getElementCount() {
+ return 0;
+ }
+
+ @Override
+ public SimpleListener<Object> getDelegateOfLastNode() {
+ return null;
+ }
+ };
+
+ private ChainedListeners() {
+
+ }
+
+ public static <T> ChainedListener<T> empty() {
+ return (ChainedListener<T>) empty;
+ }
+
+ public static <T> ChainedListener<T> singleton(SimpleListener<T> element) {
+ if (element instanceof ChainedListener) {
+ return (ChainedListener<T>) element;
+ }
+ if (element == null) {
+ return empty();
+ }
+ return new ChainedListener<T>() {
+ @Override
+ public void accept(T event) {
+ element.accept(event);
+ }
+
+ @Override
+ public SimpleListener getDelegateOfLastNode() {
+ return element;
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/HandlerList.java b/dicore3/core/src/main/java/io/dico/dicore/event/HandlerList.java
index 56265bb..fa290c0 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/HandlerList.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/HandlerList.java
@@ -1,91 +1,91 @@
-package io.dico.dicore.event;
-
-import org.bukkit.event.Cancellable;
-import org.bukkit.event.EventPriority;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.function.Consumer;
-
-public final class HandlerList<T> {
- private final List<Listener<T>> source = new ArrayList<>();
- private Listener<T>[] listeners = newArray(0);
-
- public void refresh() {
- source.sort(Comparator.comparingInt(l -> l.getPriority().ordinal()));
- listeners = source.toArray(newArray(source.size()));
- }
-
- @SuppressWarnings("unchecked")
- private static <T> Listener<T>[] newArray(int length) {
- return new Listener[length];
- }
-
- public void register(Listener<T> listener) {
- if (!source.contains(listener) && source.add(listener)) {
- refresh();
- }
- }
-
- public ListenerHandle getListenerHandle(Listener<T> listener) {
- return new ListenerHandle() {
- @Override
- public void register() {
- HandlerList.this.register(listener);
- }
-
- @Override
- public void unregister() {
- HandlerList.this.unregister(listener);
- }
- };
- }
-
- public void register(EventPriority priority, Consumer<T> listener) {
- register(new Listener<T>() {
- @Override
- public EventPriority getPriority() {
- return priority;
- }
-
- @Override
- public void accept(T event) {
- listener.accept(event);
- }
- });
- }
-
- public List<Listener<T>> getRegistrations() {
- return Collections.unmodifiableList(source);
- }
-
- public void unregister(Listener<T> listener) {
- if (source.remove(listener)) {
- refresh();
- }
- }
-
- public void callEvent(T event) {
- if (event instanceof Cancellable) {
- Cancellable c = (Cancellable) event;
- boolean cancelled = c.isCancelled();
- for (Listener<T> listener : listeners) {
- if (listener.listensToCancelledState(cancelled)) {
- //EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
- listener.accept(event);
- cancelled = c.isCancelled();
- } /*else {
- EnchantsPlugin.getInstance().debug("Listener does not listen to cancelled state of " + cancelled + ": " + listener.getClass().getSimpleName());
- }*/
- }
- } else {
- for (Listener<T> listener : listeners) {
- //EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
- listener.accept(event);
- }
- }
- }
-
-}
+package io.dico.dicore.event;
+
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.EventPriority;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.function.Consumer;
+
+public final class HandlerList<T> {
+ private final List<Listener<T>> source = new ArrayList<>();
+ private Listener<T>[] listeners = newArray(0);
+
+ public void refresh() {
+ source.sort(Comparator.comparingInt(l -> l.getPriority().ordinal()));
+ listeners = source.toArray(newArray(source.size()));
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> Listener<T>[] newArray(int length) {
+ return new Listener[length];
+ }
+
+ public void register(Listener<T> listener) {
+ if (!source.contains(listener) && source.add(listener)) {
+ refresh();
+ }
+ }
+
+ public ListenerHandle getListenerHandle(Listener<T> listener) {
+ return new ListenerHandle() {
+ @Override
+ public void register() {
+ HandlerList.this.register(listener);
+ }
+
+ @Override
+ public void unregister() {
+ HandlerList.this.unregister(listener);
+ }
+ };
+ }
+
+ public void register(EventPriority priority, Consumer<T> listener) {
+ register(new Listener<T>() {
+ @Override
+ public EventPriority getPriority() {
+ return priority;
+ }
+
+ @Override
+ public void accept(T event) {
+ listener.accept(event);
+ }
+ });
+ }
+
+ public List<Listener<T>> getRegistrations() {
+ return Collections.unmodifiableList(source);
+ }
+
+ public void unregister(Listener<T> listener) {
+ if (source.remove(listener)) {
+ refresh();
+ }
+ }
+
+ public void callEvent(T event) {
+ if (event instanceof Cancellable) {
+ Cancellable c = (Cancellable) event;
+ boolean cancelled = c.isCancelled();
+ for (Listener<T> listener : listeners) {
+ if (listener.listensToCancelledState(cancelled)) {
+ //EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
+ listener.accept(event);
+ cancelled = c.isCancelled();
+ } /*else {
+ EnchantsPlugin.getInstance().debug("Listener does not listen to cancelled state of " + cancelled + ": " + listener.getClass().getSimpleName());
+ }*/
+ }
+ } else {
+ for (Listener<T> listener : listeners) {
+ //EnchantsPlugin.getInstance().debug("Listener acceptance: " + listener.getClass().getSimpleName());
+ listener.accept(event);
+ }
+ }
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/Listener.java b/dicore3/core/src/main/java/io/dico/dicore/event/Listener.java
index c3e5413..064cd28 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/Listener.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/Listener.java
@@ -1,17 +1,17 @@
-package io.dico.dicore.event;
-
-import org.bukkit.event.EventPriority;
-
-public interface Listener<T> {
-
- default EventPriority getPriority() {
- return EventPriority.NORMAL;
- }
-
- default boolean listensToCancelledState(boolean cancelled) {
- return !cancelled;
- }
-
- void accept(T event);
-
-}
+package io.dico.dicore.event;
+
+import org.bukkit.event.EventPriority;
+
+public interface Listener<T> {
+
+ default EventPriority getPriority() {
+ return EventPriority.NORMAL;
+ }
+
+ default boolean listensToCancelledState(boolean cancelled) {
+ return !cancelled;
+ }
+
+ void accept(T event);
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/ListenerHandle.java b/dicore3/core/src/main/java/io/dico/dicore/event/ListenerHandle.java
index 6042954..fbedd9f 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/ListenerHandle.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/ListenerHandle.java
@@ -1,9 +1,9 @@
-package io.dico.dicore.event;
-
-public interface ListenerHandle {
-
- void register();
-
- void unregister();
-
-}
+package io.dico.dicore.event;
+
+public interface ListenerHandle {
+
+ void register();
+
+ void unregister();
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/event/SimpleListener.java b/dicore3/core/src/main/java/io/dico/dicore/event/SimpleListener.java
index 9688975..4e49a55 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/event/SimpleListener.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/event/SimpleListener.java
@@ -1,7 +1,7 @@
-package io.dico.dicore.event;
-
-public interface SimpleListener<T> {
-
- void accept(T event);
-
-}
+package io.dico.dicore.event;
+
+public interface SimpleListener<T> {
+
+ void accept(T event);
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/ExceptionHandler.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/ExceptionHandler.java
index e95b65e..2777125 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/ExceptionHandler.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/ExceptionHandler.java
@@ -1,203 +1,203 @@
-package io.dico.dicore.exceptions;
-
-import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
-import io.dico.dicore.exceptions.checkedfunctions.CheckedSupplier;
-import io.dico.dicore.exceptions.checkedfunctions.CheckedFunctionalObject;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.sql.SQLException;
-import java.util.Objects;
-import java.util.function.Consumer;
-import java.util.function.Supplier;
-
-@FunctionalInterface
-public interface ExceptionHandler {
-
- /**
- * Handle the given exception according to this handler's implementation
- *
- * @param ex The exception to be handled
- * @throws NullPointerException if ex is null, unless the implementation specifies otherwise
- * @throws Error ex if ex is an instance of Error, unless the implementation specifies otherwise
- */
- void handle(Throwable ex);
-
- /**
- * Handle the given exception according to this handler's implementation
- * This method is intended for use by {@link CheckedFunctionalObject} and subinterfaces.
- * It supplies exception handlers the option to acquire more information, by overriding this method and calling it from {@link #handle(Throwable)}
- *
- * @param ex The exception to be handled
- * @param args Any arguments passed, this is used by {@link CheckedFunctionalObject} and subinterfaces.
- * @return {@code null} (unless specified otherwise by the implementation)
- * @throws NullPointerException if ex is null, unless the implementation specifies otherwise
- * @throws Error ex if ex is an instance of Error, unless the implementation specifies otherwise
- */
- default Object handleGenericException(Throwable ex, Object... args) {
- handle(ex);
- return null;
- }
-
- /**
- * @return true if this {@link ExceptionHandler}'s {@link #handleGenericException(Throwable, Object...)} method is <b>never</b> expected to throw
- * an unchecked exception other than {@link Error}
- */
- default boolean isSafe() {
- return true;
- }
-
- /**
- * Runs the given checked action, handling any thrown exceptions using this exception handler.
- * <p>
- * Any exceptions thrown by this handler are delegated to the caller.
- *
- * @param action The action to run
- * @throws NullPointerException if action is null
- */
- default void runSafe(CheckedRunnable<? extends Throwable> action) {
- Objects.requireNonNull(action);
- try {
- action.checkedRun();
- } catch (Throwable ex) {
- handle(ex);
- }
- }
-
- /**
- * Computes the result of the given checked supplier, handling any thrown exceptions using this exception handler.
- * <p>
- * Any exceptions thrown by this handler are delegated to the caller.
- *
- * @param action The supplier whose result to compute
- * @param <T> generic type parameter for the supplier and the result type of this method
- * @return The result of this computation, or null if an error occurred
- * @throws NullPointerException if action is null
- */
-
- default <T> T supplySafe(CheckedSupplier<T, ? extends Throwable> action) {
- Objects.requireNonNull(action);
- try {
- return action.checkedGet();
- } catch (Throwable ex) {
- handle(ex);
- return null;
- }
- }
-
- /**
- * @param action The action to wrap
- * @return A runnable that wraps the given action using this handler's {@link #runSafe(CheckedRunnable)} method.
- * @see #runSafe(CheckedRunnable)
- */
- default Runnable safeRunnable(CheckedRunnable<? extends Throwable> action) {
- return () -> runSafe(action);
- }
-
- /**
- * @param supplier The computation to wrap
- * @return A supplier that wraps the given computation using this handler's {@link #supplySafe(CheckedSupplier)} method.
- * @see #supplySafe(CheckedSupplier)
- */
- default <T> Supplier<T> safeSupplier(CheckedSupplier<T, ? extends Throwable> supplier) {
- return () -> supplySafe(supplier);
- }
-
- /**
- * Logs the given exception as an error to {@code out}
- * <p>
- * Format: Error occurred while {@code failedActivityDescription}, followed by additional details and a stack trace
- *
- * @param out The consumer to accept the error message, for instance {@code {@link java.util.logging.Logger logger}::warning}.
- * @param failedActivityDescription A description of the activity that was being executed when the exception was thrown
- * @param ex The exception that was thrown
- * @throws NullPointerException if any argument is null
- */
- static void log(Consumer<String> out, String failedActivityDescription, Throwable ex) {
- if (out == null || failedActivityDescription == null || ex == null) {
- throw new NullPointerException();
- }
-
- StringWriter msg = new StringWriter(1024);
- msg.append("Error occurred while ").append(failedActivityDescription).append(':');
-
- if (ex instanceof SQLException) {
- SQLException sqlex = (SQLException) ex;
- msg.append('\n').append("Error code: ").append(Integer.toString(sqlex.getErrorCode()));
- msg.append('\n').append("SQL State: ").append(sqlex.getSQLState());
- }
-
- msg.append('\n').append("=======START STACK=======");
- try (PrintWriter pw = new PrintWriter(msg)) {
- ex.printStackTrace(pw);
- }
- msg.append('\n').append("========END STACK========");
-
- out.accept(msg.toString());
- }
-
- /**
- * @param activityDescription The activity description
- * @return An ExceptionHandler that prints to {@link System#out}
- * @see #log(Consumer, String)
- */
- static ExceptionHandler log(String activityDescription) {
- // A method reference would cache the current value in System.out
- // This would update if the value in System.out is changed (by for example, applying a PrintStream that handles colours).
- return log(msg -> System.out.println(msg), activityDescription);
- }
-
- /**
- * @param out The Consumer to be passed to {@link #log(Consumer, String, Throwable)}
- * @param activityDescription The activity description to be passed to {@link #log(Consumer, String, Throwable)}
- * @return An ExceptionHandler that passes exceptions with given arguments to {@link #log(Consumer, String, Throwable)}
- * @see #log(Consumer, String, Throwable)
- */
- static ExceptionHandler log(Consumer<String> out, String activityDescription) {
- return ex -> log(out, activityDescription, ex);
- }
-
- /**
- * This ExceptionHandler turns any Throwable into an unchecked exception, then throws it again.
- */
- ExceptionHandler UNCHECKED = new ExceptionHandler() {
- @Override
- public void handle(Throwable ex) {
- errorFilter(ex);
- if (ex instanceof RuntimeException) {
- throw (RuntimeException) ex;
- }
- throw new RuntimeException(ex);
- }
-
- @Override
- public boolean isSafe() {
- return false;
- }
- };
-
- /**
- * This ExceptionHandler suppresses all exceptions,
- * apart from {@link Error} because that is not usually supposed to be caught
- */
- ExceptionHandler SUPPRESS = ExceptionHandler::errorFilter;
-
- /**
- * This ExceptionHandler calls {@link Throwable#printStackTrace()} unless it is a {@link NullPointerException} or {@link Error}.
- */
- ExceptionHandler PRINT_UNLESS_NP = ex -> {
- errorFilter(ex);
- if (!(ex instanceof NullPointerException)) {
- ex.printStackTrace();
- }
- };
-
- static void errorFilter(Throwable ex) {
- if (ex instanceof Error) {
- throw (Error) ex;
- } else if (ex == null) {
- throw new NullPointerException();
- }
- }
-
-}
+package io.dico.dicore.exceptions;
+
+import io.dico.dicore.exceptions.checkedfunctions.CheckedRunnable;
+import io.dico.dicore.exceptions.checkedfunctions.CheckedSupplier;
+import io.dico.dicore.exceptions.checkedfunctions.CheckedFunctionalObject;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.SQLException;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+@FunctionalInterface
+public interface ExceptionHandler {
+
+ /**
+ * Handle the given exception according to this handler's implementation
+ *
+ * @param ex The exception to be handled
+ * @throws NullPointerException if ex is null, unless the implementation specifies otherwise
+ * @throws Error ex if ex is an instance of Error, unless the implementation specifies otherwise
+ */
+ void handle(Throwable ex);
+
+ /**
+ * Handle the given exception according to this handler's implementation
+ * This method is intended for use by {@link CheckedFunctionalObject} and subinterfaces.
+ * It supplies exception handlers the option to acquire more information, by overriding this method and calling it from {@link #handle(Throwable)}
+ *
+ * @param ex The exception to be handled
+ * @param args Any arguments passed, this is used by {@link CheckedFunctionalObject} and subinterfaces.
+ * @return {@code null} (unless specified otherwise by the implementation)
+ * @throws NullPointerException if ex is null, unless the implementation specifies otherwise
+ * @throws Error ex if ex is an instance of Error, unless the implementation specifies otherwise
+ */
+ default Object handleGenericException(Throwable ex, Object... args) {
+ handle(ex);
+ return null;
+ }
+
+ /**
+ * @return true if this {@link ExceptionHandler}'s {@link #handleGenericException(Throwable, Object...)} method is <b>never</b> expected to throw
+ * an unchecked exception other than {@link Error}
+ */
+ default boolean isSafe() {
+ return true;
+ }
+
+ /**
+ * Runs the given checked action, handling any thrown exceptions using this exception handler.
+ * <p>
+ * Any exceptions thrown by this handler are delegated to the caller.
+ *
+ * @param action The action to run
+ * @throws NullPointerException if action is null
+ */
+ default void runSafe(CheckedRunnable<? extends Throwable> action) {
+ Objects.requireNonNull(action);
+ try {
+ action.checkedRun();
+ } catch (Throwable ex) {
+ handle(ex);
+ }
+ }
+
+ /**
+ * Computes the result of the given checked supplier, handling any thrown exceptions using this exception handler.
+ * <p>
+ * Any exceptions thrown by this handler are delegated to the caller.
+ *
+ * @param action The supplier whose result to compute
+ * @param <T> generic type parameter for the supplier and the result type of this method
+ * @return The result of this computation, or null if an error occurred
+ * @throws NullPointerException if action is null
+ */
+
+ default <T> T supplySafe(CheckedSupplier<T, ? extends Throwable> action) {
+ Objects.requireNonNull(action);
+ try {
+ return action.checkedGet();
+ } catch (Throwable ex) {
+ handle(ex);
+ return null;
+ }
+ }
+
+ /**
+ * @param action The action to wrap
+ * @return A runnable that wraps the given action using this handler's {@link #runSafe(CheckedRunnable)} method.
+ * @see #runSafe(CheckedRunnable)
+ */
+ default Runnable safeRunnable(CheckedRunnable<? extends Throwable> action) {
+ return () -> runSafe(action);
+ }
+
+ /**
+ * @param supplier The computation to wrap
+ * @return A supplier that wraps the given computation using this handler's {@link #supplySafe(CheckedSupplier)} method.
+ * @see #supplySafe(CheckedSupplier)
+ */
+ default <T> Supplier<T> safeSupplier(CheckedSupplier<T, ? extends Throwable> supplier) {
+ return () -> supplySafe(supplier);
+ }
+
+ /**
+ * Logs the given exception as an error to {@code out}
+ * <p>
+ * Format: Error occurred while {@code failedActivityDescription}, followed by additional details and a stack trace
+ *
+ * @param out The consumer to accept the error message, for instance {@code {@link java.util.logging.Logger logger}::warning}.
+ * @param failedActivityDescription A description of the activity that was being executed when the exception was thrown
+ * @param ex The exception that was thrown
+ * @throws NullPointerException if any argument is null
+ */
+ static void log(Consumer<String> out, String failedActivityDescription, Throwable ex) {
+ if (out == null || failedActivityDescription == null || ex == null) {
+ throw new NullPointerException();
+ }
+
+ StringWriter msg = new StringWriter(1024);
+ msg.append("Error occurred while ").append(failedActivityDescription).append(':');
+
+ if (ex instanceof SQLException) {
+ SQLException sqlex = (SQLException) ex;
+ msg.append('\n').append("Error code: ").append(Integer.toString(sqlex.getErrorCode()));
+ msg.append('\n').append("SQL State: ").append(sqlex.getSQLState());
+ }
+
+ msg.append('\n').append("=======START STACK=======");
+ try (PrintWriter pw = new PrintWriter(msg)) {
+ ex.printStackTrace(pw);
+ }
+ msg.append('\n').append("========END STACK========");
+
+ out.accept(msg.toString());
+ }
+
+ /**
+ * @param activityDescription The activity description
+ * @return An ExceptionHandler that prints to {@link System#out}
+ * @see #log(Consumer, String)
+ */
+ static ExceptionHandler log(String activityDescription) {
+ // A method reference would cache the current value in System.out
+ // This would update if the value in System.out is changed (by for example, applying a PrintStream that handles colours).
+ return log(msg -> System.out.println(msg), activityDescription);
+ }
+
+ /**
+ * @param out The Consumer to be passed to {@link #log(Consumer, String, Throwable)}
+ * @param activityDescription The activity description to be passed to {@link #log(Consumer, String, Throwable)}
+ * @return An ExceptionHandler that passes exceptions with given arguments to {@link #log(Consumer, String, Throwable)}
+ * @see #log(Consumer, String, Throwable)
+ */
+ static ExceptionHandler log(Consumer<String> out, String activityDescription) {
+ return ex -> log(out, activityDescription, ex);
+ }
+
+ /**
+ * This ExceptionHandler turns any Throwable into an unchecked exception, then throws it again.
+ */
+ ExceptionHandler UNCHECKED = new ExceptionHandler() {
+ @Override
+ public void handle(Throwable ex) {
+ errorFilter(ex);
+ if (ex instanceof RuntimeException) {
+ throw (RuntimeException) ex;
+ }
+ throw new RuntimeException(ex);
+ }
+
+ @Override
+ public boolean isSafe() {
+ return false;
+ }
+ };
+
+ /**
+ * This ExceptionHandler suppresses all exceptions,
+ * apart from {@link Error} because that is not usually supposed to be caught
+ */
+ ExceptionHandler SUPPRESS = ExceptionHandler::errorFilter;
+
+ /**
+ * This ExceptionHandler calls {@link Throwable#printStackTrace()} unless it is a {@link NullPointerException} or {@link Error}.
+ */
+ ExceptionHandler PRINT_UNLESS_NP = ex -> {
+ errorFilter(ex);
+ if (!(ex instanceof NullPointerException)) {
+ ex.printStackTrace();
+ }
+ };
+
+ static void errorFilter(Throwable ex) {
+ if (ex instanceof Error) {
+ throw (Error) ex;
+ } else if (ex == null) {
+ throw new NullPointerException();
+ }
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiConsumer.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiConsumer.java
index badf05b..bfcafe8 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiConsumer.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiConsumer.java
@@ -1,69 +1,69 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.util.function.BiConsumer;
-
-/**
- * checked mimic of {@link BiConsumer}
- *
- * @param <TParam1>
- * @param <TParam2>
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedBiConsumer<TParam1, TParam2, TException extends Throwable>
- extends CheckedFunctionalObject<Void, TException>, BiConsumer<TParam1, TParam2> {
-
- /**
- * The consuming action
- *
- * @param t the first argument to consume
- * @param u the second argument to consume
- * @throws TException if an exception occurs
- */
- void checkedAccept(TParam1 t, TParam2 u) throws TException;
-
- /**
- * unchecked wrapper for {@link #checkedAccept(Object, Object)}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @param t the first input
- * @param u the second input
- * @see #checkedAccept(Object, Object)
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default void accept(TParam1 t, TParam2 u) {
- try {
- checkedAccept(t, u);
- } catch (Throwable ex) {
- handleGenericException(ex, t, u);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedBiConsumer<TParam1, TParam2, TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedBiConsumer<TParam1, TParam2, TException>() {
- @Override
- public void checkedAccept(TParam1 t, TParam2 u) throws TException {
- CheckedBiConsumer.this.checkedAccept(t, u);
- }
-
- @Override
- public Void handleGenericException(Throwable thrown, Object... args) {
- handler.handleGenericException(thrown, args);
- return null;
- }
-
- @Override
- public CheckedBiConsumer<TParam1, TParam2, TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedBiConsumer.this.handleExceptionsWith(handler);
- }
- };
- }
-
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.util.function.BiConsumer;
+
+/**
+ * checked mimic of {@link BiConsumer}
+ *
+ * @param <TParam1>
+ * @param <TParam2>
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedBiConsumer<TParam1, TParam2, TException extends Throwable>
+ extends CheckedFunctionalObject<Void, TException>, BiConsumer<TParam1, TParam2> {
+
+ /**
+ * The consuming action
+ *
+ * @param t the first argument to consume
+ * @param u the second argument to consume
+ * @throws TException if an exception occurs
+ */
+ void checkedAccept(TParam1 t, TParam2 u) throws TException;
+
+ /**
+ * unchecked wrapper for {@link #checkedAccept(Object, Object)}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @param t the first input
+ * @param u the second input
+ * @see #checkedAccept(Object, Object)
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default void accept(TParam1 t, TParam2 u) {
+ try {
+ checkedAccept(t, u);
+ } catch (Throwable ex) {
+ handleGenericException(ex, t, u);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedBiConsumer<TParam1, TParam2, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedBiConsumer<TParam1, TParam2, TException>() {
+ @Override
+ public void checkedAccept(TParam1 t, TParam2 u) throws TException {
+ CheckedBiConsumer.this.checkedAccept(t, u);
+ }
+
+ @Override
+ public Void handleGenericException(Throwable thrown, Object... args) {
+ handler.handleGenericException(thrown, args);
+ return null;
+ }
+
+ @Override
+ public CheckedBiConsumer<TParam1, TParam2, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedBiConsumer.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiFunction.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiFunction.java
index 9b39325..11fca3f 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiFunction.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedBiFunction.java
@@ -1,76 +1,76 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.util.function.BiFunction;
-
-/**
- * checked mimic of {@link BiFunction}
- *
- * @param <TParam1>
- * @param <TParam2>
- * @param <TResult>
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedBiFunction<TParam1, TParam2, TResult, TException extends Throwable>
- extends CheckedFunctionalObject<TResult, TException>, BiFunction<TParam1, TParam2, TResult> {
-
- /**
- * the functional method
- *
- * @param t the first input
- * @param u the second input
- * @return the function output
- * @throws TException if an exception occurs
- */
- TResult checkedApply(TParam1 t, TParam2 u) throws TException;
-
- /**
- * unchecked wrapper for {@link #checkedApply(Object, Object)}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @param t the first input
- * @param u the second input
- * @return the function output, or the result from {@link #resultOnError(Throwable, Object...)} if an exception was thrown
- * @see #checkedApply(Object, Object)
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default TResult apply(TParam1 t, TParam2 u) {
- try {
- return checkedApply(t, u);
- } catch (Throwable ex) {
- return handleGenericException(ex, t, u);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedBiFunction<TParam1, TParam2, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedBiFunction<TParam1, TParam2, TResult, TException>() {
- @Override
- public TResult checkedApply(TParam1 t, TParam2 u) throws TException {
- return CheckedBiFunction.this.checkedApply(t, u);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public TResult handleGenericException(Throwable thrown, Object... args) {
- Object result = handler.handleGenericException(thrown, args);
- try {
- return (TResult) result;
- } catch (Exception ex) {
- return null;
- }
- }
-
- @Override
- public CheckedBiFunction<TParam1, TParam2, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedBiFunction.this.handleExceptionsWith(handler);
- }
- };
- }
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.util.function.BiFunction;
+
+/**
+ * checked mimic of {@link BiFunction}
+ *
+ * @param <TParam1>
+ * @param <TParam2>
+ * @param <TResult>
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedBiFunction<TParam1, TParam2, TResult, TException extends Throwable>
+ extends CheckedFunctionalObject<TResult, TException>, BiFunction<TParam1, TParam2, TResult> {
+
+ /**
+ * the functional method
+ *
+ * @param t the first input
+ * @param u the second input
+ * @return the function output
+ * @throws TException if an exception occurs
+ */
+ TResult checkedApply(TParam1 t, TParam2 u) throws TException;
+
+ /**
+ * unchecked wrapper for {@link #checkedApply(Object, Object)}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @param t the first input
+ * @param u the second input
+ * @return the function output, or the result from {@link #resultOnError(Throwable, Object...)} if an exception was thrown
+ * @see #checkedApply(Object, Object)
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default TResult apply(TParam1 t, TParam2 u) {
+ try {
+ return checkedApply(t, u);
+ } catch (Throwable ex) {
+ return handleGenericException(ex, t, u);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedBiFunction<TParam1, TParam2, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedBiFunction<TParam1, TParam2, TResult, TException>() {
+ @Override
+ public TResult checkedApply(TParam1 t, TParam2 u) throws TException {
+ return CheckedBiFunction.this.checkedApply(t, u);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public TResult handleGenericException(Throwable thrown, Object... args) {
+ Object result = handler.handleGenericException(thrown, args);
+ try {
+ return (TResult) result;
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ @Override
+ public CheckedBiFunction<TParam1, TParam2, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedBiFunction.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedConsumer.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedConsumer.java
index fa48ae8..abe6d53 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedConsumer.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedConsumer.java
@@ -1,67 +1,67 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.util.function.Consumer;
-
-/**
- * checked mimic of {@link Consumer}
- *
- * @param <TParam>
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedConsumer<TParam, TException extends Throwable>
- extends CheckedFunctionalObject<Void, TException>, Consumer<TParam> {
-
- /**
- * The consuming action
- *
- * @param t the argument to consume
- * @throws TException if an error occurs
- */
- void checkedAccept(TParam t) throws TException;
-
- /**
- * Unchecked version of {@link #checkedAccept(Object)}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @param t the argument to consume
- * @see #checkedAccept(Object)
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default void accept(TParam t) {
- try {
- checkedAccept(t);
- } catch (Throwable ex) {
- handleGenericException(ex, t);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedConsumer<TParam, TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedConsumer<TParam, TException>() {
- @Override
- public void checkedAccept(TParam t) throws TException {
- CheckedConsumer.this.checkedAccept(t);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Void handleGenericException(Throwable thrown, Object... args) {
- handler.handleGenericException(thrown, args);
- return null;
- }
-
- @Override
- public CheckedConsumer<TParam, TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedConsumer.this.handleExceptionsWith(handler);
- }
- };
- }
-
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.util.function.Consumer;
+
+/**
+ * checked mimic of {@link Consumer}
+ *
+ * @param <TParam>
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedConsumer<TParam, TException extends Throwable>
+ extends CheckedFunctionalObject<Void, TException>, Consumer<TParam> {
+
+ /**
+ * The consuming action
+ *
+ * @param t the argument to consume
+ * @throws TException if an error occurs
+ */
+ void checkedAccept(TParam t) throws TException;
+
+ /**
+ * Unchecked version of {@link #checkedAccept(Object)}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @param t the argument to consume
+ * @see #checkedAccept(Object)
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default void accept(TParam t) {
+ try {
+ checkedAccept(t);
+ } catch (Throwable ex) {
+ handleGenericException(ex, t);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedConsumer<TParam, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedConsumer<TParam, TException>() {
+ @Override
+ public void checkedAccept(TParam t) throws TException {
+ CheckedConsumer.this.checkedAccept(t);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Void handleGenericException(Throwable thrown, Object... args) {
+ handler.handleGenericException(thrown, args);
+ return null;
+ }
+
+ @Override
+ public CheckedConsumer<TParam, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedConsumer.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunction.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunction.java
index 9ff806a..48ac207 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunction.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunction.java
@@ -1,74 +1,74 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.util.function.Function;
-
-/**
- * checked mimic of {@link Function}
- *
- * @param <TParam>
- * @param <TResult>
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedFunction<TParam, TResult, TException extends Throwable>
- extends CheckedFunctionalObject<TResult, TException>, Function<TParam, TResult> {
-
- /**
- * the functional method
- *
- * @param t the input
- * @return the function output
- * @throws TException if an exception occurs
- */
- TResult checkedApply(TParam t) throws TException;
-
- /**
- * unchecked wrapper for {@link #checkedApply(Object)}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @param t the input
- * @return the function output, or the result from {@link #resultOnError(Throwable, Object...)} if an exception was thrown
- * @see #checkedApply(Object)
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default TResult apply(TParam t) {
- try {
- return checkedApply(t);
- } catch (Throwable ex) {
- return handleGenericException(ex, t);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedFunction<TParam, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedFunction<TParam, TResult, TException>() {
- @Override
- public TResult checkedApply(TParam t) throws TException {
- return CheckedFunction.this.checkedApply(t);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public TResult handleGenericException(Throwable thrown, Object... args) {
- Object result = handler.handleGenericException(thrown, args);
- try {
- return (TResult) result;
- } catch (Exception ex) {
- return null;
- }
- }
-
- @Override
- public CheckedFunction<TParam, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedFunction.this.handleExceptionsWith(handler);
- }
- };
- }
-
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.util.function.Function;
+
+/**
+ * checked mimic of {@link Function}
+ *
+ * @param <TParam>
+ * @param <TResult>
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedFunction<TParam, TResult, TException extends Throwable>
+ extends CheckedFunctionalObject<TResult, TException>, Function<TParam, TResult> {
+
+ /**
+ * the functional method
+ *
+ * @param t the input
+ * @return the function output
+ * @throws TException if an exception occurs
+ */
+ TResult checkedApply(TParam t) throws TException;
+
+ /**
+ * unchecked wrapper for {@link #checkedApply(Object)}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @param t the input
+ * @return the function output, or the result from {@link #resultOnError(Throwable, Object...)} if an exception was thrown
+ * @see #checkedApply(Object)
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default TResult apply(TParam t) {
+ try {
+ return checkedApply(t);
+ } catch (Throwable ex) {
+ return handleGenericException(ex, t);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedFunction<TParam, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedFunction<TParam, TResult, TException>() {
+ @Override
+ public TResult checkedApply(TParam t) throws TException {
+ return CheckedFunction.this.checkedApply(t);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public TResult handleGenericException(Throwable thrown, Object... args) {
+ Object result = handler.handleGenericException(thrown, args);
+ try {
+ return (TResult) result;
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ @Override
+ public CheckedFunction<TParam, TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedFunction.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunctionalObject.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunctionalObject.java
index e84b33d..d9d7a53 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunctionalObject.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedFunctionalObject.java
@@ -1,85 +1,85 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-/**
- * Base interface for all checked functional interfaces
- * Most subinterfaces will mimic interfaces in the package {@link java.util.function}
- * <p>
- * Checked functional interfaces are functions with throws declarations.
- * The name comes from the fact that they can throw <b>checked</b> exceptions.
- * <p>
- * They extend their non-checked counterparts, whose methods are implemented by
- * returning the result of {@link #resultOnError(TException, Object...)} when an exception is thrown
- * <p>
- * Made public to allow more specialized checked functional interfaces to subclass it.
- * Making primitive versions shouldn't provide a significant performance increase because we're checking for exceptions,
- * the performance impact of which is probably a few magnitudes larger. Don't quote me on this.
- *
- * @param <TResult> The return type of this functional interface's method
- * @param <TException> The type of exception that might be thrown
- */
-public interface CheckedFunctionalObject<TResult, TException extends Throwable> extends ExceptionHandler {
-
- /**
- * {@inheritDoc}
- *
- * @param ex The exception to be handled
- */
- @Override
- default void handle(Throwable ex) {
- handleGenericException(ex);
- }
-
- /**
- * {@inheritDoc}
- * <p>
- * Method to handle exceptions thrown by the default implementations of subinterfaces.
- * Since you can't catch a type parameter as exception, this code is in place to take care of it.
- * <p>
- * If the thrown exception is not a TException, an unchecked version is thrown by calling this method.
- *
- * @param thrown The thrown exception
- * @param args the arguments supplied to the method that threw the exception, if any. These are not guaranteed to be given if parameters are present.
- * @return The result computed by {@link #resultOnError(Throwable, Object...)}
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- @SuppressWarnings("unchecked")
- default TResult handleGenericException(Throwable thrown, Object... args) {
-
- // check if the throwable is a TException
- TException castedException;
- try {
- castedException = (TException) thrown;
- } catch (ClassCastException ex) {
- // if not, throw an unchecked version of it
- ExceptionHandler.UNCHECKED.handleGenericException(thrown);
- // this code is never reached.
- return null;
- }
-
- // if it is a TException, use resultOnError to compute result.
- return resultOnError(castedException, args);
- }
-
- /**
- * This method handles the exceptions thrown by the checked method of this object, when called by its unchecked wrapper.
- *
- * @param ex The exception thrown
- * @param args The (typed) arguments passed, if any
- * @return The result to return, if any
- */
- default TResult resultOnError(TException ex, Object... args) {
- return null;
- }
-
- /**
- * Creates a new functional object that uses the given exception handler to handle exceptions.
- *
- * @param handler The handler to handle exceptions
- * @return a new functional object that uses the given exception handler to handle exceptions
- */
- CheckedFunctionalObject<TResult, TException> handleExceptionsWith(ExceptionHandler handler);
-
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+/**
+ * Base interface for all checked functional interfaces
+ * Most subinterfaces will mimic interfaces in the package {@link java.util.function}
+ * <p>
+ * Checked functional interfaces are functions with throws declarations.
+ * The name comes from the fact that they can throw <b>checked</b> exceptions.
+ * <p>
+ * They extend their non-checked counterparts, whose methods are implemented by
+ * returning the result of {@link #resultOnError(TException, Object...)} when an exception is thrown
+ * <p>
+ * Made public to allow more specialized checked functional interfaces to subclass it.
+ * Making primitive versions shouldn't provide a significant performance increase because we're checking for exceptions,
+ * the performance impact of which is probably a few magnitudes larger. Don't quote me on this.
+ *
+ * @param <TResult> The return type of this functional interface's method
+ * @param <TException> The type of exception that might be thrown
+ */
+public interface CheckedFunctionalObject<TResult, TException extends Throwable> extends ExceptionHandler {
+
+ /**
+ * {@inheritDoc}
+ *
+ * @param ex The exception to be handled
+ */
+ @Override
+ default void handle(Throwable ex) {
+ handleGenericException(ex);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Method to handle exceptions thrown by the default implementations of subinterfaces.
+ * Since you can't catch a type parameter as exception, this code is in place to take care of it.
+ * <p>
+ * If the thrown exception is not a TException, an unchecked version is thrown by calling this method.
+ *
+ * @param thrown The thrown exception
+ * @param args the arguments supplied to the method that threw the exception, if any. These are not guaranteed to be given if parameters are present.
+ * @return The result computed by {@link #resultOnError(Throwable, Object...)}
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ default TResult handleGenericException(Throwable thrown, Object... args) {
+
+ // check if the throwable is a TException
+ TException castedException;
+ try {
+ castedException = (TException) thrown;
+ } catch (ClassCastException ex) {
+ // if not, throw an unchecked version of it
+ ExceptionHandler.UNCHECKED.handleGenericException(thrown);
+ // this code is never reached.
+ return null;
+ }
+
+ // if it is a TException, use resultOnError to compute result.
+ return resultOnError(castedException, args);
+ }
+
+ /**
+ * This method handles the exceptions thrown by the checked method of this object, when called by its unchecked wrapper.
+ *
+ * @param ex The exception thrown
+ * @param args The (typed) arguments passed, if any
+ * @return The result to return, if any
+ */
+ default TResult resultOnError(TException ex, Object... args) {
+ return null;
+ }
+
+ /**
+ * Creates a new functional object that uses the given exception handler to handle exceptions.
+ *
+ * @param handler The handler to handle exceptions
+ * @return a new functional object that uses the given exception handler to handle exceptions
+ */
+ CheckedFunctionalObject<TResult, TException> handleExceptionsWith(ExceptionHandler handler);
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedRunnable.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedRunnable.java
index 55de6f8..110c988 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedRunnable.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedRunnable.java
@@ -1,62 +1,62 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-/**
- * checked mimic of {@link Runnable}
- *
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedRunnable<TException extends Throwable>
- extends CheckedFunctionalObject<Void, TException>, Runnable {
-
- /**
- * The runnable action
- *
- * @throws TException if an exception occurs
- */
- void checkedRun() throws TException;
-
- /**
- * Unchecked version of {@link #checkedRun()}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @see #checkedRun()
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default void run() {
- try {
- checkedRun();
- } catch (Throwable ex) {
- handleGenericException(ex);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedRunnable<TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedRunnable<TException>() {
- @Override
- public void checkedRun() throws TException {
- CheckedRunnable.this.checkedRun();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public Void handleGenericException(Throwable thrown, Object... args) {
- handler.handleGenericException(thrown, args);
- return null;
- }
-
- @Override
- public CheckedRunnable<TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedRunnable.this.handleExceptionsWith(handler);
- }
- };
- }
-
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+/**
+ * checked mimic of {@link Runnable}
+ *
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedRunnable<TException extends Throwable>
+ extends CheckedFunctionalObject<Void, TException>, Runnable {
+
+ /**
+ * The runnable action
+ *
+ * @throws TException if an exception occurs
+ */
+ void checkedRun() throws TException;
+
+ /**
+ * Unchecked version of {@link #checkedRun()}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @see #checkedRun()
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default void run() {
+ try {
+ checkedRun();
+ } catch (Throwable ex) {
+ handleGenericException(ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedRunnable<TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedRunnable<TException>() {
+ @Override
+ public void checkedRun() throws TException {
+ CheckedRunnable.this.checkedRun();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Void handleGenericException(Throwable thrown, Object... args) {
+ handler.handleGenericException(thrown, args);
+ return null;
+ }
+
+ @Override
+ public CheckedRunnable<TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedRunnable.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedSupplier.java b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedSupplier.java
index dec2e7e..7820428 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedSupplier.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/exceptions/checkedfunctions/CheckedSupplier.java
@@ -1,70 +1,70 @@
-package io.dico.dicore.exceptions.checkedfunctions;
-
-import io.dico.dicore.exceptions.ExceptionHandler;
-
-import java.util.function.Supplier;
-
-/**
- * checked mimic of {@link Supplier}
- *
- * @param <TResult>
- * @param <TException>
- */
-@FunctionalInterface
-public interface CheckedSupplier<TResult, TException extends Throwable>
- extends CheckedFunctionalObject<TResult, TException>, Supplier<TResult> {
-
- /**
- * The computation
- *
- * @return the result of this computation
- * @throws TException if an error occurs
- */
- TResult checkedGet() throws TException;
-
- /**
- * Unchecked version of {@link #checkedGet()}
- * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
- *
- * @return the result of this computation
- * @see #checkedGet()
- * @see #resultOnError(Throwable, Object...)
- */
- @Override
- default TResult get() {
- try {
- return checkedGet();
- } catch (Throwable ex) {
- return handleGenericException(ex);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- default CheckedSupplier<TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return new CheckedSupplier<TResult, TException>() {
- @Override
- public TResult checkedGet() throws TException {
- return CheckedSupplier.this.checkedGet();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public TResult handleGenericException(Throwable thrown, Object... args) {
- Object result = handler.handleGenericException(thrown, args);
- try {
- return (TResult) result;
- } catch (Exception ex) {
- return null;
- }
- }
-
- @Override
- public CheckedSupplier<TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
- return CheckedSupplier.this.handleExceptionsWith(handler);
- }
- };
- }
-}
+package io.dico.dicore.exceptions.checkedfunctions;
+
+import io.dico.dicore.exceptions.ExceptionHandler;
+
+import java.util.function.Supplier;
+
+/**
+ * checked mimic of {@link Supplier}
+ *
+ * @param <TResult>
+ * @param <TException>
+ */
+@FunctionalInterface
+public interface CheckedSupplier<TResult, TException extends Throwable>
+ extends CheckedFunctionalObject<TResult, TException>, Supplier<TResult> {
+
+ /**
+ * The computation
+ *
+ * @return the result of this computation
+ * @throws TException if an error occurs
+ */
+ TResult checkedGet() throws TException;
+
+ /**
+ * Unchecked version of {@link #checkedGet()}
+ * If a {@link TException} occurs, an unchecked one might be thrown by {@link #resultOnError(Throwable, Object...)}
+ *
+ * @return the result of this computation
+ * @see #checkedGet()
+ * @see #resultOnError(Throwable, Object...)
+ */
+ @Override
+ default TResult get() {
+ try {
+ return checkedGet();
+ } catch (Throwable ex) {
+ return handleGenericException(ex);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ default CheckedSupplier<TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return new CheckedSupplier<TResult, TException>() {
+ @Override
+ public TResult checkedGet() throws TException {
+ return CheckedSupplier.this.checkedGet();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public TResult handleGenericException(Throwable thrown, Object... args) {
+ Object result = handler.handleGenericException(thrown, args);
+ try {
+ return (TResult) result;
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+
+ @Override
+ public CheckedSupplier<TResult, TException> handleExceptionsWith(ExceptionHandler handler) {
+ return CheckedSupplier.this.handleExceptionsWith(handler);
+ }
+ };
+ }
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/task/BaseTask.java b/dicore3/core/src/main/java/io/dico/dicore/task/BaseTask.java
index b400cce..43db459 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/task/BaseTask.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/task/BaseTask.java
@@ -1,108 +1,108 @@
-package io.dico.dicore.task;
-
-import org.bukkit.Bukkit;
-import org.bukkit.plugin.Plugin;
-
-import java.util.NoSuchElementException;
-
-public abstract class BaseTask<T> {
- private boolean running = false;
- private Integer taskId = null;
- private long workTime = 5L;
- private int workCount;
-
- public void start(Plugin plugin, int delay, int period, long workTime) {
- doStartChecks();
- this.workTime = workTime;
- workCount = 0;
- running = true;
-
- if (delay == -1) {
- run();
- if (!running) {
- return;
- }
- delay = period;
- }
-
- taskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this::run, delay, period);
- }
-
- public void startImmediately(Plugin plugin, int period, long workTime) {
- start(plugin, -1, period, workTime);
- }
-
- protected void doStartChecks() {
- if (isRunning()) {
- throw new IllegalStateException("Can't start when already running");
- }
- }
-
- public void start(Plugin plugin) {
- start(plugin, -1, 20, 5L);
- }
-
- protected void onFinish(boolean early) {
- }
-
- protected long getWorkTime() {
- return workTime;
- }
-
- protected abstract boolean process(T object);
-
- private void run() {
- workCount++;
- final long stop = System.currentTimeMillis() + getWorkTime();
- do {
- if (!processNext()) {
- return;
- }
- } while (System.currentTimeMillis() < stop);
- }
-
- public int getTaskId() {
- return running ? taskId : -1;
- }
-
- public int getWorkCount() {
- return workCount;
- }
-
- public boolean isRunning() {
- return running;
- }
-
- protected abstract T supply() throws NoSuchElementException;
-
- private void cancelTask(boolean early) {
- if (taskId != null) {
- Bukkit.getScheduler().cancelTask(taskId);
- }
- running = false;
- taskId = null;
- onFinish(early);
- }
-
- private boolean processNext() {
- T object;
- try {
- object = supply();
- } catch (NoSuchElementException e) {
- cancelTask(false);
- return false;
- }
-
- try {
- if (process(object)) {
- return true;
- }
- } catch (RuntimeException e) {
- e.printStackTrace();
- }
-
- cancelTask(true);
- return false;
- }
-
-}
+package io.dico.dicore.task;
+
+import org.bukkit.Bukkit;
+import org.bukkit.plugin.Plugin;
+
+import java.util.NoSuchElementException;
+
+public abstract class BaseTask<T> {
+ private boolean running = false;
+ private Integer taskId = null;
+ private long workTime = 5L;
+ private int workCount;
+
+ public void start(Plugin plugin, int delay, int period, long workTime) {
+ doStartChecks();
+ this.workTime = workTime;
+ workCount = 0;
+ running = true;
+
+ if (delay == -1) {
+ run();
+ if (!running) {
+ return;
+ }
+ delay = period;
+ }
+
+ taskId = plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this::run, delay, period);
+ }
+
+ public void startImmediately(Plugin plugin, int period, long workTime) {
+ start(plugin, -1, period, workTime);
+ }
+
+ protected void doStartChecks() {
+ if (isRunning()) {
+ throw new IllegalStateException("Can't start when already running");
+ }
+ }
+
+ public void start(Plugin plugin) {
+ start(plugin, -1, 20, 5L);
+ }
+
+ protected void onFinish(boolean early) {
+ }
+
+ protected long getWorkTime() {
+ return workTime;
+ }
+
+ protected abstract boolean process(T object);
+
+ private void run() {
+ workCount++;
+ final long stop = System.currentTimeMillis() + getWorkTime();
+ do {
+ if (!processNext()) {
+ return;
+ }
+ } while (System.currentTimeMillis() < stop);
+ }
+
+ public int getTaskId() {
+ return running ? taskId : -1;
+ }
+
+ public int getWorkCount() {
+ return workCount;
+ }
+
+ public boolean isRunning() {
+ return running;
+ }
+
+ protected abstract T supply() throws NoSuchElementException;
+
+ private void cancelTask(boolean early) {
+ if (taskId != null) {
+ Bukkit.getScheduler().cancelTask(taskId);
+ }
+ running = false;
+ taskId = null;
+ onFinish(early);
+ }
+
+ private boolean processNext() {
+ T object;
+ try {
+ object = supply();
+ } catch (NoSuchElementException e) {
+ cancelTask(false);
+ return false;
+ }
+
+ try {
+ if (process(object)) {
+ return true;
+ }
+ } catch (RuntimeException e) {
+ e.printStackTrace();
+ }
+
+ cancelTask(true);
+ return false;
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/task/IteratorTask.java b/dicore3/core/src/main/java/io/dico/dicore/task/IteratorTask.java
index e58814c..3ff7be7 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/task/IteratorTask.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/task/IteratorTask.java
@@ -1,120 +1,120 @@
-package io.dico.dicore.task;
-
-import java.util.*;
-import java.util.function.BiConsumer;
-import java.util.function.BiPredicate;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-
-public abstract class IteratorTask<T> extends BaseTask<T> {
-
- private Iterator<? extends T> iterator;
-
- public IteratorTask() {
- }
-
- @SuppressWarnings("unchecked")
- public IteratorTask(Iterable<? extends T> iterable, boolean clone) {
- refresh(iterable, clone);
- }
-
- public IteratorTask(Iterable<? extends T> iterable) {
- this(iterable, false);
- }
-
- public IteratorTask(Iterator<? extends T> iterator) {
- refresh(iterator);
- }
-
- @Override
- protected void doStartChecks() {
- super.doStartChecks();
- if (iterator == null) {
- throw new IllegalStateException("An iterator must be supplied first");
- }
- }
-
- protected final void refresh(Iterable<? extends T> iterable, boolean clone) {
- if (clone) {
- Collection<T> collection;
- if (!(iterable instanceof Collection)) {
- collection = new LinkedList<>();
- for (T next : iterable) {
- collection.add(next);
- }
- } else {
- collection = new ArrayList((Collection) iterable);
- }
- iterator = collection.iterator();
- } else {
- iterator = iterable.iterator();
- }
- }
-
- protected final void refresh(Iterator<? extends T> iterator) {
- Objects.requireNonNull(iterator);
- this.iterator = iterator;
- }
-
- @Override
- protected T supply() {
- return iterator.next();
- }
-
- protected void remove() {
- iterator.remove();
- }
-
- // One argument: The processed object
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, Consumer<T> processor) {
- return create(iterable, false, processor);
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, Consumer<T> processor) {
- return create(iterable, clone, object -> {
- processor.accept(object);
- return true;
- });
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, Predicate<T> processor) {
- return create(iterable, false, processor);
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, Predicate<T> processor) {
- return new IteratorTask<T>(iterable, clone) {
- @Override
- protected boolean process(T object) {
- return processor.test(object);
- }
- };
- }
-
- // Two arguments: the processed object, and a runnable to remove it from the iterator.
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, BiConsumer<T, Runnable> processor) {
- return create(iterable, false, processor);
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, BiConsumer<T, Runnable> processor) {
- return create(iterable, clone, (object, runnable) -> {
- processor.accept(object, runnable);
- return true;
- });
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, BiPredicate<T, Runnable> processor) {
- return create(iterable, false, processor);
- }
-
- public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, BiPredicate<T, Runnable> processor) {
- return new IteratorTask<T>(iterable, clone) {
- @Override
- protected boolean process(T object) {
- return processor.test(object, this::remove);
- }
- };
- }
-
-}
+package io.dico.dicore.task;
+
+import java.util.*;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+
+public abstract class IteratorTask<T> extends BaseTask<T> {
+
+ private Iterator<? extends T> iterator;
+
+ public IteratorTask() {
+ }
+
+ @SuppressWarnings("unchecked")
+ public IteratorTask(Iterable<? extends T> iterable, boolean clone) {
+ refresh(iterable, clone);
+ }
+
+ public IteratorTask(Iterable<? extends T> iterable) {
+ this(iterable, false);
+ }
+
+ public IteratorTask(Iterator<? extends T> iterator) {
+ refresh(iterator);
+ }
+
+ @Override
+ protected void doStartChecks() {
+ super.doStartChecks();
+ if (iterator == null) {
+ throw new IllegalStateException("An iterator must be supplied first");
+ }
+ }
+
+ protected final void refresh(Iterable<? extends T> iterable, boolean clone) {
+ if (clone) {
+ Collection<T> collection;
+ if (!(iterable instanceof Collection)) {
+ collection = new LinkedList<>();
+ for (T next : iterable) {
+ collection.add(next);
+ }
+ } else {
+ collection = new ArrayList((Collection) iterable);
+ }
+ iterator = collection.iterator();
+ } else {
+ iterator = iterable.iterator();
+ }
+ }
+
+ protected final void refresh(Iterator<? extends T> iterator) {
+ Objects.requireNonNull(iterator);
+ this.iterator = iterator;
+ }
+
+ @Override
+ protected T supply() {
+ return iterator.next();
+ }
+
+ protected void remove() {
+ iterator.remove();
+ }
+
+ // One argument: The processed object
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, Consumer<T> processor) {
+ return create(iterable, false, processor);
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, Consumer<T> processor) {
+ return create(iterable, clone, object -> {
+ processor.accept(object);
+ return true;
+ });
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, Predicate<T> processor) {
+ return create(iterable, false, processor);
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, Predicate<T> processor) {
+ return new IteratorTask<T>(iterable, clone) {
+ @Override
+ protected boolean process(T object) {
+ return processor.test(object);
+ }
+ };
+ }
+
+ // Two arguments: the processed object, and a runnable to remove it from the iterator.
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, BiConsumer<T, Runnable> processor) {
+ return create(iterable, false, processor);
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, BiConsumer<T, Runnable> processor) {
+ return create(iterable, clone, (object, runnable) -> {
+ processor.accept(object, runnable);
+ return true;
+ });
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, BiPredicate<T, Runnable> processor) {
+ return create(iterable, false, processor);
+ }
+
+ public static <T> IteratorTask<T> create(Iterable<? extends T> iterable, boolean clone, BiPredicate<T, Runnable> processor) {
+ return new IteratorTask<T>(iterable, clone) {
+ @Override
+ protected boolean process(T object) {
+ return processor.test(object, this::remove);
+ }
+ };
+ }
+
+}
diff --git a/dicore3/core/src/main/java/io/dico/dicore/task/VoidTask.java b/dicore3/core/src/main/java/io/dico/dicore/task/VoidTask.java
index 1298c4c..6204bee 100644
--- a/dicore3/core/src/main/java/io/dico/dicore/task/VoidTask.java
+++ b/dicore3/core/src/main/java/io/dico/dicore/task/VoidTask.java
@@ -1,19 +1,19 @@
-package io.dico.dicore.task;
-
-import java.util.NoSuchElementException;
-
-public abstract class VoidTask extends BaseTask<Void> {
-
- @Override
- protected final boolean process(Void object) {
- return process();
- }
-
- @Override
- protected final Void supply() throws NoSuchElementException {
- return null;
- }
-
- protected abstract boolean process();
-
-}
+package io.dico.dicore.task;
+
+import java.util.NoSuchElementException;
+
+public abstract class VoidTask extends BaseTask<Void> {
+
+ @Override
+ protected final boolean process(Void object) {
+ return process();
+ }
+
+ @Override
+ protected final Void supply() throws NoSuchElementException {
+ return null;
+ }
+
+ protected abstract boolean process();
+
+}