[AB-70] adding concept of command parameter validators and applied them at various places, this has the intention for commands to fail early

removing duplicated command for assignable role places
This commit is contained in:
Sheldan
2020-09-30 00:17:43 +02:00
parent 0f9a0dc143
commit 8e05bc90ea
33 changed files with 588 additions and 78 deletions

View File

@@ -1,55 +0,0 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class ChangeAssignablePlaceDescription extends AbstractConditionableCommand {
@Autowired
private AssignableRolePlaceService service;
@Override
public CommandResult execute(CommandContext commandContext) {
checkParameters(commandContext);
List<Object> parameters = commandContext.getParameters().getParameters();
String name = (String) parameters.get(0);
String newDescription = (String) parameters.get(1);
service.changeAssignablePlaceDescription(commandContext.getUserInitiatedContext().getServer(), name, newDescription);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
Parameter newDescription = Parameter.builder().name("newDescription").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, newDescription);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("changeAssignablePlaceDescription")
.module(AssignableRoleModule.ASSIGNABLE_ROLES)
.templated(true)
.causesReaction(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureEnum getFeature() {
return AssignableRoleFeature.ASSIGNABLE_ROLES;
}
}

View File

@@ -1,11 +1,14 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -42,9 +45,11 @@ public class CreateAssignableRolePost extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<ParameterValidator> rolePlaceNameValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
Parameter rolePostName = Parameter.builder().name("name").validators(rolePlaceNameValidator).type(String.class).templated(true).build();
Parameter channel = Parameter.builder().name("channel").type(TextChannel.class).templated(true).build();
Parameter text = Parameter.builder().name("text").type(String.class).remainder(true).optional(true).templated(true).build();
List<ParameterValidator> rolePlaceDescriptionValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
Parameter text = Parameter.builder().name("text").validators(rolePlaceDescriptionValidator).type(String.class).remainder(true).optional(true).templated(true).build();
List<String> aliases = Arrays.asList("crRPl", "crAssRoPl");
List<Parameter> parameters = Arrays.asList(rolePostName, channel, text);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();

View File

@@ -1,11 +1,14 @@
package dev.sheldan.abstracto.assignableroles.command;
import dev.sheldan.abstracto.assignableroles.config.features.AssignableRoleFeature;
import dev.sheldan.abstracto.assignableroles.models.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.service.AssignableRolePlaceService;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -36,7 +39,8 @@ public class EditAssignableRolePlaceText extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
Parameter rolePostName = Parameter.builder().name("name").type(String.class).templated(true).build();
List<ParameterValidator> rolePlaceNameValidator = Arrays.asList(MaxStringLengthValidator.max(AssignableRolePlace.ASSIGNABLE_PLACE_NAME_LIMIT));
Parameter rolePostName = Parameter.builder().name("name").validators(rolePlaceNameValidator).type(String.class).templated(true).build();
Parameter newText = Parameter.builder().name("newText").type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(rolePostName, newText);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();

View File

@@ -76,12 +76,6 @@
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="changeAssignablePlaceDescription"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
<column name="created" valueComputed="${today}"/>
</insert>
<insert tableName="command">
<column name="name" value="showAssignableRolePlaceConfig"/>
<column name="module_id" valueComputed="${experienceModule}"/>

View File

@@ -21,6 +21,9 @@ import java.util.List;
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class AssignableRolePlace implements Serializable {
public static final Long ASSIGNABLE_PLACE_NAME_LIMIT = 255L;
public static final Long ASSIGNABLE_PLACE_DESCRIPTION_LIMIT = 255L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
@@ -23,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -68,7 +71,8 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("page").optional(true).templated(true).type(Integer.class).build());
List<ParameterValidator> leaderBoardPageValidators = Arrays.asList(MinIntegerValueValidator.min(0L));
parameters.add(Parameter.builder().name("page").validators(leaderBoardPageValidators).optional(true).templated(true).type(Integer.class).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("leaderboard")

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -18,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -51,7 +54,8 @@ public class SetExpRole extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("level").templated(true).type(Integer.class).build());
List<ParameterValidator> levelValidators = Arrays.asList(MinIntegerValueValidator.min(0L));
parameters.add(Parameter.builder().name("level").validators(levelValidators).templated(true).type(Integer.class).build());
parameters.add(Parameter.builder().name("role").templated(true).type(ARole.class).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
return CommandConfiguration.builder()

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -15,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Component
@@ -42,7 +45,8 @@ public class DeleteNote extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("id").type(Long.class).templated(true).build());
List<ParameterValidator> userNoteIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("id").validators(userNoteIdValidator).type(Long.class).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("deleteNote")

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -37,7 +39,8 @@ public class DeleteWarning extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("warnId").templated(true).type(Long.class).build());
List<ParameterValidator> warnIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("warnId").validators(warnIdValidator).templated(true).type(Long.class).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
List<String> aliases = Arrays.asList("delWarn");
return CommandConfiguration.builder()

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -17,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -47,7 +50,8 @@ public class Purge extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("amount").type(Integer.class).templated(true).build());
List<ParameterValidator> messageAmountValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("amount").validators(messageAmountValidator).type(Integer.class).templated(true).build());
parameters.add(Parameter.builder().name("member").type(Member.class).optional(true).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()

View File

@@ -5,6 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -15,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Slf4j
@@ -35,7 +38,8 @@ public class UnRemind extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("reminderId").templated(true).type(Long.class).build());
List<ParameterValidator> reminderIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("reminderId").validators(reminderIdValidator).templated(true).type(Long.class).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("unRemind")

View File

@@ -5,6 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.*;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
@@ -14,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -37,7 +40,9 @@ public class Accept extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("suggestionId").type(Long.class).templated(true).build());
List<ParameterValidator> suggestionIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("suggestionId").validators(suggestionIdValidator).type(Long.class).templated(true).build());
parameters.add(Parameter.builder().name("text").type(String.class).optional(true).remainder(true).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
return CommandConfiguration.builder()

View File

@@ -5,6 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
import dev.sheldan.abstracto.core.command.execution.*;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.utility.config.features.UtilityFeature;
@@ -14,6 +16,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -37,7 +40,9 @@ public class Reject extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
parameters.add(Parameter.builder().name("suggestionId").type(Long.class).templated(true).build());
List<ParameterValidator> suggestionIdValidator = Arrays.asList(MinIntegerValueValidator.min(1L));
parameters.add(Parameter.builder().name("suggestionId").validators(suggestionIdValidator).type(Long.class).templated(true).build());
parameters.add(Parameter.builder().name("text").type(String.class).optional(true).remainder(true).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
return CommandConfiguration.builder()

View File

@@ -126,6 +126,11 @@
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>

View File

@@ -2,7 +2,9 @@ package dev.sheldan.abstracto.core.command;
import dev.sheldan.abstracto.core.command.condition.ConditionResult;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.Parameters;
import dev.sheldan.abstracto.core.command.exception.CommandParameterValidationException;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
import dev.sheldan.abstracto.core.command.exception.ParameterTooLongException;
import dev.sheldan.abstracto.core.command.service.CommandManager;
@@ -115,6 +117,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
private void tryToExecuteFoundCommand(@Nonnull MessageReceivedEvent event, UserInitiatedServerContext userInitiatedContext, CommandContext.CommandContextBuilder commandContextBuilder, Command foundCommand, UnParsedCommandParameter unParsedParameter) {
try {
Parameters parsedParameters = getParsedParameters(unParsedParameter, foundCommand, event.getMessage(), userInitiatedContext);
validateCommandParameters(parsedParameters, foundCommand);
CommandContext commandContext = commandContextBuilder.parameters(parsedParameters).build();
ConditionResult conditionResult = commandService.isCommandExecutable(foundCommand, commandContext);
CommandResult commandResult = null;
@@ -158,6 +161,21 @@ public class CommandReceivedHandler extends ListenerAdapter {
}
}
private void validateCommandParameters(Parameters parameters, Command foundCommand) {
List<Parameter> parameterList = foundCommand.getConfiguration().getParameters();
// we iterate only over the actually found parameters, that way we dont have to consider the optional parameters
// the parameters are going from left to right anyway
for (int i = 0; i < parameters.getParameters().size(); i++) {
Parameter parameter = parameterList.get(i);
for (ParameterValidator parameterValidator : parameter.getValidators()) {
boolean validate = parameterValidator.validate(parameters.getParameters().get(i));
if(!validate) {
throw new CommandParameterValidationException(parameterValidator.getParameters(), parameterValidator.getTemplateName(), parameter);
}
}
}
}
@Transactional
public void executePostCommandListener(Command foundCommand, CommandContext commandContext, CommandResult result) {
for (PostCommandExecution postCommandExecution : executions) {
@@ -308,8 +326,6 @@ public class CommandReceivedHandler extends ListenerAdapter {
}
} catch (NoSuchElementException e) {
throw new IncorrectParameterException(command, param.getType(), param.getName());
} catch (IllegalArgumentException e) {
}
}

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
@@ -30,7 +32,8 @@ public class SetPrefix extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
Parameter newPrefixParameter = Parameter.builder().name("prefix").type(String.class).templated(true).build();
List<ParameterValidator> validators = Arrays.asList(MaxStringLengthValidator.max(10L));
Parameter newPrefixParameter = Parameter.builder().name("prefix").validators(validators).type(String.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(newPrefixParameter);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()

View File

@@ -4,6 +4,8 @@ import dev.sheldan.abstracto.core.command.UtilityModuleInterface;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.validator.MaxStringLengthValidator;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.config.Parameter;
@@ -38,7 +40,8 @@ public class SetEmote extends AbstractConditionableCommand {
@Override
public CommandConfiguration getConfiguration() {
Parameter emoteKey = Parameter.builder().name("emoteKey").type(String.class).templated(true).build();
List<ParameterValidator> emoteKeyValidators = Arrays.asList(MaxStringLengthValidator.max(255L));
Parameter emoteKey = Parameter.builder().name("emoteKey").validators(emoteKeyValidators).type(String.class).templated(true).build();
Parameter emote = Parameter.builder().name("emote").type(AEmote.class).templated(true).build();
List<Parameter> parameters = Arrays.asList(emoteKey, emote);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();

View File

@@ -4,8 +4,14 @@ import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter @Setter @Builder
public class Parameter {
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@Builder
public class Parameter implements Serializable {
private String name;
private Class type;
private String description;
@@ -16,4 +22,6 @@ public class Parameter {
private Integer maxLength;
@Builder.Default
private Boolean templated = false;
@Builder.Default
private List<ParameterValidator> validators = new ArrayList<>();
}

View File

@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.core.command.config;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import java.util.List;
public interface ParameterValidator {
boolean validate(Object value);
List<ValidatorParam> getParameters();
String getTemplateName();
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MaxIntegerValueValidator implements ParameterValidator {
private Long maxValue;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof Long)) {
throw new ValidatorConfigException("Incorrect value passed to max value validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
Long longValue = (Long) value;
return longValue <= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(maxValue)
.build();
return Arrays.asList(param);
}
@Override
public String getTemplateName() {
return "command_parameter_validation_value_too_large";
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MaxStringLengthValidator implements ParameterValidator {
private Long maxLength;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof String)) {
throw new ValidatorConfigException("Incorrect value passed to max string length validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
String stringValue = (String) value;
return stringValue.length() <= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(maxLength)
.build();
return Arrays.asList(param);
}
@Override
public String getTemplateName() {
return "command_parameter_validation_string_too_long";
}
public static MaxStringLengthValidator max(Long number) {
return MaxStringLengthValidator
.builder()
.maxLength(number)
.build();
}
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MinIntegerValueValidator implements ParameterValidator {
private Long minValue;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof Long)) {
throw new ValidatorConfigException("Incorrect value passed to max value validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
Long longValue = (Long) value;
return longValue >= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(minValue)
.build();
return Arrays.asList(param);
}
public static MinIntegerValueValidator min(Long number) {
return MinIntegerValueValidator
.builder()
.minValue(number)
.build();
}
@Override
public String getTemplateName() {
return "command_parameter_validation_value_too_small";
}
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
@Getter
@Setter
@Builder
public class MinStringLengthValidator implements ParameterValidator {
private Long minLength;
@Override
public boolean validate(Object value) {
if(value == null) {
throw new IllegalArgumentException("Object to validate must not be null");
}
if(!(value instanceof String)) {
throw new ValidatorConfigException("Incorrect value passed to min string length validator.");
}
SingleNumberValidatorParam param = (SingleNumberValidatorParam) getParameters().get(0);
String stringValue = (String) value;
return stringValue.length() >= param.getNumber();
}
@Override
public List<ValidatorParam> getParameters() {
SingleNumberValidatorParam param = SingleNumberValidatorParam
.builder()
.number(minLength)
.build();
return Arrays.asList(param);
}
@Override
public String getTemplateName() {
return "command_parameter_validation_string_too_short";
}
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.abstracto.core.command.config.validator;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SingleNumberValidatorParam implements ValidatorParam {
private Long number;
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.command.config.validator;
import java.io.Serializable;
public interface ValidatorParam extends Serializable {
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import dev.sheldan.abstracto.core.command.models.exception.CommandParameterValidationExceptionModel;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.templating.Templatable;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class CommandParameterValidationException extends AbstractoRunTimeException implements Templatable {
private final CommandParameterValidationExceptionModel model;
public CommandParameterValidationException(List<ValidatorParam> validatorParams, String template, Parameter parameter) {
this.model = CommandParameterValidationExceptionModel
.builder()
.validationTemplate(template)
.validatorParams(validatorParams)
.parameter(parameter)
.build();
}
@Override
public String getTemplateName() {
return "command_parameter_validation_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.command.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
public class ValidatorConfigException extends AbstractoRunTimeException {
public ValidatorConfigException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.core.command.models.exception;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.validator.ValidatorParam;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
import java.util.List;
@Getter
@Setter
@Builder
public class CommandParameterValidationExceptionModel implements Serializable {
private List<ValidatorParam> validatorParams;
private String validationTemplate;
private Parameter parameter;
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MaxIntegerValueValidatorTest {
@InjectMocks
private MaxIntegerValueValidator validator;
@Before
public void setup() {
validator.setMaxValue(4L);
}
@Test(expected = ValidatorConfigException.class)
public void incorrectArgument() {
validator.validate("");
}
@Test(expected = IllegalArgumentException.class)
public void nullArgument() {
validator.validate(null);
}
@Test
public void littleEnoughValue() {
Assert.assertTrue(validator.validate(3L));
}
@Test
public void exactValue() {
Assert.assertTrue(validator.validate(4L));
}
@Test
public void tooLargeValue() {
Assert.assertFalse(validator.validate(5L));
}
}

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MaxStringLengthValidatorTest {
@InjectMocks
private MaxStringLengthValidator validator;
@Before
public void setup() {
validator.setMaxLength(4L);
}
@Test(expected = ValidatorConfigException.class)
public void incorrectArgument() {
validator.validate(4L);
}
@Test(expected = IllegalArgumentException.class)
public void nullArgument() {
validator.validate(null);
}
@Test
public void validateEmptyString() {
Assert.assertTrue(validator.validate(""));
}
@Test
public void validateShortString() {
Assert.assertTrue(validator.validate("t"));
}
@Test
public void validateExactString() {
Assert.assertTrue(validator.validate("text"));
}
@Test
public void validateTooLongString() {
Assert.assertFalse(validator.validate("text1"));
}
}

View File

@@ -0,0 +1,45 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MinIntegerValueValidatorTest {
@InjectMocks
private MinIntegerValueValidator validator;
@Before
public void setup() {
validator.setMinValue(4L);
}
@Test(expected = ValidatorConfigException.class)
public void incorrectArgument() {
validator.validate("");
}
@Test(expected = IllegalArgumentException.class)
public void nullArgument() {
validator.validate(null);
}
@Test
public void tooLittleValue() {
Assert.assertFalse(validator.validate(3L));
}
@Test
public void exactValue() {
Assert.assertTrue(validator.validate(4L));
}
@Test
public void largeEnoughValue() {
Assert.assertTrue(validator.validate(5L));
}
}

View File

@@ -0,0 +1,51 @@
package dev.sheldan.abstracto.core.command.config.validator;
import dev.sheldan.abstracto.core.command.exception.ValidatorConfigException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MinStringLengthValidatorTest {
@InjectMocks
private MinStringLengthValidator validator;
@Before
public void setup() {
validator.setMinLength(4L);
}
@Test(expected = ValidatorConfigException.class)
public void incorrectArgument() {
validator.validate(4L);
}
@Test(expected = IllegalArgumentException.class)
public void nullArgument() {
validator.validate(null);
}
@Test
public void validateEmptyString() {
Assert.assertFalse(validator.validate(""));
}
@Test
public void validateShortString() {
Assert.assertFalse(validator.validate("t"));
}
@Test
public void validateExactString() {
Assert.assertTrue(validator.validate("text"));
}
@Test
public void validateLongEnoughString() {
Assert.assertTrue(validator.validate("text1"));
}
}

View File

@@ -71,6 +71,12 @@
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-impl</artifactId>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core-interface</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>