mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-26 22:02:40 +00:00
[AB-78] adding new concept of feature modes, with splitting it up to new commands and default mode concept
refactoring command received handler to only load the entities in the same thread as the actual executed commands, so that user initiated context contains valid references from the same thread updating documentation fixing issue when the result of role calculation result in no experience role id
This commit is contained in:
@@ -98,6 +98,14 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-interface</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.templating</groupId>
|
||||
<artifactId>templating-interface</artifactId>
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -82,13 +81,44 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void onMessageReceived(@Nonnull MessageReceivedEvent event) {
|
||||
public void onMessageReceived(MessageReceivedEvent event) {
|
||||
if(!event.isFromGuild()) {
|
||||
return;
|
||||
}
|
||||
if(!commandManager.isCommand(event.getMessage())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Command foundCommand;
|
||||
try {
|
||||
String contentStripped = event.getMessage().getContentRaw();
|
||||
List<String> parameters = Arrays.asList(contentStripped.split(" "));
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(contentStripped);
|
||||
String commandName = commandManager.getCommandName(parameters.get(0), event.getGuild().getIdLong());
|
||||
foundCommand = commandManager.findCommandByParameters(commandName, unParsedParameter);
|
||||
tryToExecuteFoundCommand(event, foundCommand, unParsedParameter);
|
||||
|
||||
} catch (Exception e) {
|
||||
reportException(event, null, e, "Exception when executing command.");
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToExecuteFoundCommand(MessageReceivedEvent event, Command foundCommand, UnParsedCommandParameter unParsedParameter) {
|
||||
CompletableFuture<Parameters> parsingFuture = getParsedParameters(unParsedParameter, foundCommand, event.getMessage());
|
||||
parsingFuture.thenAccept(parsedParameters ->
|
||||
self.executeCommand(event, foundCommand, parsedParameters)
|
||||
).exceptionally(throwable -> {
|
||||
reportException(event, foundCommand, throwable, "Exception when executing command.");
|
||||
return null;
|
||||
});
|
||||
parsingFuture.exceptionally(throwable -> {
|
||||
self.reportException(event, foundCommand, throwable, "Exception when parsing command.");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void executeCommand(MessageReceivedEvent event, Command foundCommand, Parameters parsedParameters) {
|
||||
UserInitiatedServerContext userInitiatedContext = buildTemplateParameter(event);
|
||||
CommandContext.CommandContextBuilder commandContextBuilder = CommandContext.builder()
|
||||
.author(event.getMember())
|
||||
@@ -98,73 +128,58 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
.message(event.getMessage())
|
||||
.jda(event.getJDA())
|
||||
.userInitiatedContext(userInitiatedContext);
|
||||
final Command foundCommand;
|
||||
try {
|
||||
String contentStripped = event.getMessage().getContentRaw();
|
||||
List<String> parameters = Arrays.asList(contentStripped.split(" "));
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(contentStripped);
|
||||
String commandName = commandManager.getCommandName(parameters.get(0), event.getGuild().getIdLong());
|
||||
foundCommand = commandManager.findCommandByParameters(commandName, unParsedParameter);
|
||||
tryToExecuteFoundCommand(event, commandContextBuilder, foundCommand, unParsedParameter);
|
||||
validateCommandParameters(parsedParameters, foundCommand);
|
||||
CommandContext commandContext = commandContextBuilder.parameters(parsedParameters).build();
|
||||
ConditionResult conditionResult = commandService.isCommandExecutable(foundCommand, commandContext);
|
||||
CommandResult commandResult = null;
|
||||
if(conditionResult.isResult()) {
|
||||
if(foundCommand.getConfiguration().isAsync()) {
|
||||
log.info("Executing async command {} for server {} in channel {} based on message {} by user {}.",
|
||||
foundCommand.getConfiguration().getName(), commandContext.getGuild().getId(), commandContext.getChannel().getId(), commandContext.getMessage().getId(), commandContext.getAuthor().getId());
|
||||
|
||||
} catch (Exception e) {
|
||||
reportException(commandContextBuilder, null, e, "Exception when executing command.");
|
||||
foundCommand.executeAsync(commandContext).thenAccept(result ->
|
||||
executePostCommandListener(foundCommand, commandContext, result)
|
||||
).exceptionally(throwable -> {
|
||||
log.error("Asynchronous command {} failed.", foundCommand.getConfiguration().getName(), throwable);
|
||||
UserInitiatedServerContext rebuildUserContext = buildTemplateParameter(event);
|
||||
CommandContext rebuildContext = CommandContext.builder()
|
||||
.author(event.getMember())
|
||||
.guild(event.getGuild())
|
||||
.channel(event.getTextChannel())
|
||||
.message(event.getMessage())
|
||||
.jda(event.getJDA())
|
||||
.undoActions(commandContext.getUndoActions()) // TODO really do this? it would need to guarantee that its available and usable
|
||||
.userInitiatedContext(rebuildUserContext)
|
||||
.parameters(parsedParameters).build();
|
||||
CommandResult failedResult = CommandResult.fromError(throwable.getMessage(), throwable);
|
||||
self.executePostCommandListener(foundCommand, rebuildContext, failedResult);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
commandResult = self.executeCommand(foundCommand, commandContext);
|
||||
}
|
||||
} else {
|
||||
// TODO can it be done nicer?
|
||||
if(conditionResult.getException() != null) {
|
||||
throw conditionResult.getException();
|
||||
}
|
||||
}
|
||||
if(commandResult != null) {
|
||||
self.executePostCommandListener(foundCommand, commandContext, commandResult);
|
||||
}
|
||||
}
|
||||
|
||||
private void tryToExecuteFoundCommand(@Nonnull MessageReceivedEvent event, CommandContext.CommandContextBuilder commandContextBuilder, Command foundCommand, UnParsedCommandParameter unParsedParameter) {
|
||||
CompletableFuture<Parameters> parsingFuture = getParsedParameters(unParsedParameter, foundCommand, event.getMessage());
|
||||
parsingFuture.thenAccept(parsedParameters -> {
|
||||
validateCommandParameters(parsedParameters, foundCommand);
|
||||
CommandContext commandContext = commandContextBuilder.parameters(parsedParameters).build();
|
||||
ConditionResult conditionResult = commandService.isCommandExecutable(foundCommand, commandContext);
|
||||
CommandResult commandResult = null;
|
||||
if(conditionResult.isResult()) {
|
||||
if(foundCommand.getConfiguration().isAsync()) {
|
||||
log.info("Executing async command {} for server {} in channel {} based on message {} by user {}.",
|
||||
foundCommand.getConfiguration().getName(), commandContext.getGuild().getId(), commandContext.getChannel().getId(), commandContext.getMessage().getId(), commandContext.getAuthor().getId());
|
||||
|
||||
foundCommand.executeAsync(commandContext).thenAccept(result ->
|
||||
executePostCommandListener(foundCommand, commandContext, result)
|
||||
).exceptionally(throwable -> {
|
||||
log.error("Asynchronous command {} failed.", foundCommand.getConfiguration().getName(), throwable);
|
||||
UserInitiatedServerContext rebuildUserContext = buildTemplateParameter(event);
|
||||
CommandContext rebuildContext = CommandContext.builder()
|
||||
.author(event.getMember())
|
||||
.guild(event.getGuild())
|
||||
.channel(event.getTextChannel())
|
||||
.message(event.getMessage())
|
||||
.jda(event.getJDA())
|
||||
.undoActions(commandContext.getUndoActions()) // TODO really do this? it would need to guarantee that its available and usable
|
||||
.userInitiatedContext(rebuildUserContext)
|
||||
.parameters(parsedParameters).build();
|
||||
CommandResult failedResult = CommandResult.fromError(throwable.getMessage(), throwable);
|
||||
self.executePostCommandListener(foundCommand, rebuildContext, failedResult);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
commandResult = self.executeCommand(foundCommand, commandContext);
|
||||
}
|
||||
} else {
|
||||
// TODO can it be done nicer?
|
||||
if(conditionResult.getException() != null) {
|
||||
throw conditionResult.getException();
|
||||
}
|
||||
}
|
||||
if(commandResult != null) {
|
||||
self.executePostCommandListener(foundCommand, commandContext, commandResult);
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
reportException(commandContextBuilder, foundCommand, throwable, "Exception when executing command.");
|
||||
return null;
|
||||
});
|
||||
parsingFuture.exceptionally(throwable -> {
|
||||
reportException(commandContextBuilder, foundCommand, throwable, "Exception when parsing command.");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void reportException(CommandContext.CommandContextBuilder commandContextBuilder, Command foundCommand, Throwable throwable, String s) {
|
||||
@Transactional
|
||||
public void reportException(MessageReceivedEvent event, Command foundCommand, Throwable throwable, String s) {
|
||||
UserInitiatedServerContext userInitiatedContext = buildTemplateParameter(event);
|
||||
CommandContext.CommandContextBuilder commandContextBuilder = CommandContext.builder()
|
||||
.author(event.getMember())
|
||||
.guild(event.getGuild())
|
||||
.undoActions(new ArrayList<>())
|
||||
.channel(event.getTextChannel())
|
||||
.message(event.getMessage())
|
||||
.jda(event.getJDA())
|
||||
.userInitiatedContext(userInitiatedContext);
|
||||
log.error(s, throwable);
|
||||
CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable);
|
||||
CommandContext commandContext = commandContextBuilder.build();
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.features;
|
||||
|
||||
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.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DisableMode extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private FeatureManagementService featureManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
String featureName = (String) commandContext.getParameters().getParameters().get(0);
|
||||
String modeName = (String) commandContext.getParameters().getParameters().get(1);
|
||||
FeatureEnum featureEnum = featureConfigService.getFeatureEnum(featureName);
|
||||
FeatureMode featureMode = featureModeService.getFeatureModeForKey(modeName);
|
||||
featureModeService.disableFeatureModeForFeature(featureEnum, commandContext.getUserInitiatedContext().getServer(), featureMode);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter featureName = Parameter.builder().name("feature").type(String.class).templated(true).build();
|
||||
Parameter mode = Parameter.builder().name("mode").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(featureName, mode);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("disableMode")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.parameters(parameters)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,10 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -21,7 +22,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SetMode extends AbstractConditionableCommand {
|
||||
public class EnableMode extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private FeatureManagementService featureManagementService;
|
||||
@@ -33,31 +34,34 @@ public class SetMode extends AbstractConditionableCommand {
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagManagementService featureFlagManagementService;
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
String featureName = (String) commandContext.getParameters().getParameters().get(0);
|
||||
String modeName = (String) commandContext.getParameters().getParameters().get(1);
|
||||
|
||||
featureModeService.setModeForFeatureTo(featureName, commandContext.getUserInitiatedContext().getServer(), modeName);
|
||||
FeatureEnum featureEnum = featureConfigService.getFeatureEnum(featureName);
|
||||
FeatureMode featureMode = featureModeService.getFeatureModeForKey(modeName);
|
||||
featureModeService.enableFeatureModeForFeature(featureEnum, commandContext.getUserInitiatedContext().getServer(), featureMode);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter featureName = Parameter.builder().name("feature").type(String.class).templated(true).build();
|
||||
Parameter newMode = Parameter.builder().name("newMode").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(featureName, newMode);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
|
||||
Parameter mode = Parameter.builder().name("mode").type(String.class).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(featureName, mode);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("setMode")
|
||||
.name("enableMode")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.parameters(parameters)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
@@ -0,0 +1,81 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.features;
|
||||
|
||||
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.features.CoreFeatures;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.commands.config.ConfigModuleInterface;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModesModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class FeatureModes extends AbstractConditionableCommand {
|
||||
|
||||
public static final String FEATURE_MODES_RESPONSE_TEMPLATE_KEY = "feature_modes_response";
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureManagementService featureManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
checkParameters(commandContext);
|
||||
List<FeatureModeDisplay> featureModes;
|
||||
if(commandContext.getParameters().getParameters().isEmpty()) {
|
||||
featureModes = featureModeService.getEffectiveFeatureModes(commandContext.getUserInitiatedContext().getServer());
|
||||
} else {
|
||||
String featureName = (String) commandContext.getParameters().getParameters().get(0);
|
||||
FeatureEnum featureEnum = featureConfigService.getFeatureEnum(featureName);
|
||||
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
|
||||
featureModes = featureModeService.getEffectiveFeatureModes(commandContext.getUserInitiatedContext().getServer(), feature);
|
||||
}
|
||||
FeatureModesModel model = FeatureModesModel.builder().featureModes(featureModes).build();
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInChannel(FEATURE_MODES_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter featureName = Parameter.builder().name("feature").type(String.class).optional(true).templated(true).build();
|
||||
List<Parameter> parameters = Arrays.asList(featureName);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("featureModes")
|
||||
.module(ConfigModuleInterface.CONFIG)
|
||||
.parameters(parameters)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.help(helpInfo)
|
||||
.async(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return CoreFeatures.CORE_FEATURE;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,13 @@
|
||||
package dev.sheldan.abstracto.core.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -21,43 +16,19 @@ public class FeatureFlagListener implements ServerConfigListener {
|
||||
@Autowired
|
||||
private FeatureFlagManagementService service;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureManagementService featureManagementService;
|
||||
|
||||
@Autowired
|
||||
private Environment environment;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagManagementService featureFlagManagementService;
|
||||
|
||||
@Autowired
|
||||
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
|
||||
|
||||
@Override
|
||||
public void updateServerConfig(AServer server) {
|
||||
log.info("Setting up feature flags if necessary.");
|
||||
List<String> defaultFeatureKeys = defaultFeatureFlagManagementService.getDefaultFeatureKeys();
|
||||
defaultFeatureFlagManagementService.getAllDefaultFeatureFlags().forEach(featureFlagKey -> {
|
||||
String featureKey = featureFlagKey.getFeature().getKey();
|
||||
AFeature feature = featureManagementService.getFeature(featureKey);
|
||||
if(defaultFeatureKeys.contains(featureKey)) {
|
||||
if(service.getFeatureFlag(feature, server.getId()) == null) {
|
||||
log.info("Creating feature flag {} for server {}.", feature.getKey(), server.getId());
|
||||
service.createFeatureFlag(feature, server.getId(), featureFlagKey.isEnabled());
|
||||
} else {
|
||||
log.trace("Feature flag {} for server {} already exists.", feature.getKey(), server.getId());
|
||||
}
|
||||
if(featureFlagKey.getMode() != null && !featureModeManagementService.featureModeSet(feature, server)) {
|
||||
featureModeService.createMode(feature, server, featureFlagKey.getMode());
|
||||
}
|
||||
defaultFeatureFlagManagementService.getAllDefaultFeatureFlags().forEach(defaultFeatureFlag -> {
|
||||
AFeature feature = defaultFeatureFlag.getFeature();
|
||||
if(!service.featureFlagExists(feature, server)) {
|
||||
log.info("Creating feature flag {} for server {}.", feature.getKey(), server.getId());
|
||||
service.createFeatureFlag(feature, server.getId(), defaultFeatureFlag.isEnabled());
|
||||
} else {
|
||||
log.warn("Feature {} was found as interface, but not in the properties configuration. It will not be setup.", featureKey);
|
||||
log.trace("Feature flag {} for server {} already exists.", feature.getKey(), server.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.core.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface DefaultFeatureModeRepository extends JpaRepository<DefaultFeatureMode, Long> {
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<DefaultFeatureMode> findByFeature(AFeature feature);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
Optional<DefaultFeatureMode> findByFeatureAndMode(AFeature feature, String mode);
|
||||
}
|
||||
@@ -14,6 +14,9 @@ public interface FeatureFlagRepository extends JpaRepository<AFeatureFlag, Long>
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
AFeatureFlag findByServerAndFeature(AServer server, AFeature key);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
boolean existsByServerAndFeature(AServer server, AFeature key);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<AFeatureFlag> findAllByServer(AServer server);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
@@ -9,12 +8,19 @@ import org.springframework.data.jpa.repository.QueryHints;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface FeatureModeRepository extends JpaRepository<AFeatureMode, Long> {
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
AFeatureMode findByFeatureFlag(AFeatureFlag featureFlag);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
boolean existsByFeatureFlag_ServerAndFeatureFlag_Feature(AServer server, AFeature feature);
|
||||
Optional<AFeatureMode> findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(AServer server, AFeature feature, String mode);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<AFeatureMode> findByServer(AServer server);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<AFeatureMode> findByServerAndFeatureFlag_Feature(AServer server, AFeature feature);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -131,6 +132,11 @@ public class FeatureConfigServiceBean implements FeatureConfigService {
|
||||
throw new FeatureModeNotFoundException(key, getFeatureModesFromFeatureAsString(featureConfig.getFeature().getKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureConfig getFeatureConfigForFeature(AFeature feature) {
|
||||
return getFeatureDisplayForFeature(feature.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModeValid(String featureName, String modeName) {
|
||||
return availableFeatures
|
||||
|
||||
@@ -4,15 +4,22 @@ import dev.sheldan.abstracto.core.command.service.management.FeatureManagementSe
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class FeatureModeServiceBean implements FeatureModeService {
|
||||
|
||||
@@ -28,105 +35,127 @@ public class FeatureModeServiceBean implements FeatureModeService {
|
||||
@Autowired
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(String key, AServer server, String newMode) {
|
||||
FeatureEnum featureEnum = featureConfigService.getFeatureEnum(key);
|
||||
return setModeForFeatureTo(featureEnum, server, newMode);
|
||||
}
|
||||
@Autowired
|
||||
private DefaultFeatureModeManagement defaultFeatureModeManagement;
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(AFeatureFlag flag, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(flag.getFeature().getKey());
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return setModeForFeatureTo(flag, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(FeatureEnum featureEnum, AServer server, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(featureEnum);
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return setModeForFeatureTo(featureEnum, server, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(AFeature feature, AServer server, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(feature.getKey());
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return setModeForFeatureTo(feature, server, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
|
||||
public void enableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
|
||||
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
|
||||
return setModeForFeatureTo(feature, server, mode);
|
||||
Optional<AFeatureMode> existing = featureModeManagementService.getFeatureMode(feature, server, mode);
|
||||
if(existing.isPresent()) {
|
||||
existing.get().setEnabled(true);
|
||||
} else {
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
|
||||
featureModeManagementService.createMode(featureFlag, mode, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(AFeature feature, AServer server, FeatureMode mode) {
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
|
||||
return setModeForFeatureTo(featureFlag, mode);
|
||||
public void setFutureModeForFuture(FeatureEnum featureEnum, AServer server, FeatureMode mode, Boolean newValue) {
|
||||
if(newValue) {
|
||||
enableFeatureModeForFeature(featureEnum, server, mode);
|
||||
} else {
|
||||
disableFeatureModeForFeature(featureEnum, server, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeatureTo(AFeatureFlag featureFlag, FeatureMode mode) {
|
||||
return featureModeManagementService.setModeForFeature(featureFlag, mode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(String key, AServer server, String newMode) {
|
||||
FeatureEnum featureEnum = featureConfigService.getFeatureEnum(key);
|
||||
return createMode(featureEnum, server, newMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeatureFlag flag, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(flag.getFeature().getKey());
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return createMode(flag, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(FeatureEnum featureEnum, AServer server, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(featureEnum);
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return createMode(featureEnum, server, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeature feature, AServer server, String newMode) {
|
||||
FeatureConfig featureConfig = featureConfigService.getFeatureDisplayForFeature(feature.getKey());
|
||||
FeatureMode featureMode = featureConfigService.getFeatureModeByKey(featureConfig, newMode);
|
||||
return createMode(feature, server, featureMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
|
||||
public void disableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
|
||||
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
|
||||
return createMode(feature, server, mode);
|
||||
Optional<AFeatureMode> existing = featureModeManagementService.getFeatureMode(feature, server, mode);
|
||||
if(existing.isPresent()) {
|
||||
existing.get().setEnabled(false);
|
||||
} else {
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
|
||||
featureModeManagementService.createMode(featureFlag, mode, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeature feature, AServer server, FeatureMode mode) {
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
|
||||
return createMode(featureFlag, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode) {
|
||||
return featureModeManagementService.createMode(featureFlag, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode getFeatureMode(FeatureEnum featureEnum, AServer server) {
|
||||
public boolean featureModeActive(FeatureEnum featureEnum, AServer server, FeatureMode mode) {
|
||||
AFeature feature = featureManagementService.getFeature(featureEnum.getKey());
|
||||
return getFeatureMode(feature, server);
|
||||
if(featureModeManagementService.doesFeatureModeExist(feature, server, mode)) {
|
||||
return featureModeManagementService.isFeatureModeActive(feature, server, mode);
|
||||
} else {
|
||||
return defaultFeatureModeManagement.getFeatureMode(feature, mode.getKey()).isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode getFeatureMode(AFeature feature, AServer server) {
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(feature, server);
|
||||
return featureModeManagementService.getModeForFeature(featureFlag);
|
||||
public FeatureMode getFeatureModeForKey(String key) {
|
||||
return getAllAvailableFeatureModes().stream().filter(mode -> mode.getKey().equalsIgnoreCase(key)).findAny().orElseThrow(() -> new FeatureModeNotFoundException(key, getFeatureModesAsStrings()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAllAvailableFeatureModes() {
|
||||
List<FeatureMode> featureModes = new ArrayList<>();
|
||||
featureConfigService.getAllFeatureConfigs().forEach(featureConfig -> featureModes.addAll(featureConfig.getAvailableModes()));
|
||||
return featureModes;
|
||||
}
|
||||
|
||||
private List<String> getFeatureModesAsStrings() {
|
||||
return getAllAvailableFeatureModes().stream().map(FeatureMode::getKey).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server) {
|
||||
List<DefaultFeatureMode> allDefaultModes = defaultFeatureModeManagement.getAll();
|
||||
List<AFeatureMode> allModesFromServer = featureModeManagementService.getFeatureModesOfServer(server);
|
||||
return combineFeatureModesWithDefault(server, allDefaultModes, allModesFromServer);
|
||||
}
|
||||
|
||||
private List<FeatureModeDisplay> combineFeatureModesWithDefault(AServer server, List<DefaultFeatureMode> allDefaultModes, List<AFeatureMode> allModesFromServer) {
|
||||
List<FeatureModeDisplay> result = new ArrayList<>();
|
||||
List<AFeatureMode> activeModes = allModesFromServer.stream().filter(AFeatureMode::getEnabled).collect(Collectors.toList());
|
||||
List<AFeatureMode> disabledModes = allModesFromServer.stream().filter(aFeatureMode -> !aFeatureMode.getEnabled()).collect(Collectors.toList());
|
||||
List<String> usedModes = allModesFromServer.stream().map(aFeatureMode -> aFeatureMode.getFeatureMode().getMode()).collect(Collectors.toList());
|
||||
HashMap<String, FeatureConfig> featureConfigCache = new HashMap<>();
|
||||
Consumer<AFeatureMode> loadUsedValues = aFeatureMode -> {
|
||||
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, aFeatureMode.getFeatureFlag().getFeature());
|
||||
FeatureModeDisplay featureModeDisplay = FeatureModeDisplay
|
||||
.builder()
|
||||
.featureMode(aFeatureMode)
|
||||
.isDefaultValue(false)
|
||||
.featureConfig(featureConfig)
|
||||
.build();
|
||||
result.add(featureModeDisplay);
|
||||
};
|
||||
activeModes.forEach(loadUsedValues);
|
||||
disabledModes.forEach(loadUsedValues);
|
||||
allDefaultModes.forEach(defaultFeatureMode -> {
|
||||
if(!usedModes.contains(defaultFeatureMode.getMode())) {
|
||||
FeatureConfig featureConfig = getFeatureConfig(featureConfigCache, defaultFeatureMode.getFeature());
|
||||
AFeatureFlag featureFlag = featureFlagManagementService.getFeatureFlag(defaultFeatureMode.getFeature(), server);
|
||||
AFeatureMode fakeMode = AFeatureMode.builder().server(server).enabled(defaultFeatureMode.isEnabled()).featureMode(defaultFeatureMode).featureFlag(featureFlag).build();
|
||||
FeatureModeDisplay featureModeDisplay = FeatureModeDisplay
|
||||
.builder()
|
||||
.featureMode(fakeMode)
|
||||
.isDefaultValue(true)
|
||||
.featureConfig(featureConfig)
|
||||
.build();
|
||||
result.add(featureModeDisplay);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
private FeatureConfig getFeatureConfig(HashMap<String, FeatureConfig> featureConfigs, AFeature feature) {
|
||||
String featureKey = feature.getKey();
|
||||
FeatureConfig featureConfig;
|
||||
if (featureConfigs.containsKey(featureKey)) {
|
||||
featureConfig = featureConfigs.get(featureKey);
|
||||
} else {
|
||||
featureConfig = featureConfigService.getFeatureConfigForFeature(feature);
|
||||
featureConfigs.put(featureKey, featureConfig);
|
||||
}
|
||||
return featureConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server, AFeature feature) {
|
||||
List<DefaultFeatureMode> allDefaultModes = defaultFeatureModeManagement.getFeatureModesForFeature(feature);
|
||||
List<AFeatureMode> allModesFromServer = featureModeManagementService.getFeatureModesOfFeatureInServer(server, feature);
|
||||
return combineFeatureModesWithDefault(server, allDefaultModes, allModesFromServer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package dev.sheldan.abstracto.core.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
|
||||
import dev.sheldan.abstracto.core.repository.DefaultFeatureModeRepository;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class DefaultFeatureModeManagementBean implements DefaultFeatureModeManagement {
|
||||
|
||||
@Autowired
|
||||
private DefaultFeatureModeRepository defaultFeatureModeRepository;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Override
|
||||
public List<DefaultFeatureMode> getFeatureModesForFeature(AFeature feature) {
|
||||
return defaultFeatureModeRepository.findByFeature(feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DefaultFeatureMode> getAll() {
|
||||
return defaultFeatureModeRepository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DefaultFeatureMode> getFeatureModeOptional(AFeature feature, String mode) {
|
||||
return defaultFeatureModeRepository.findByFeatureAndMode(feature, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultFeatureMode getFeatureMode(AFeature feature, String mode) {
|
||||
return getFeatureModeOptional(feature, mode).orElseThrow(() -> new FeatureModeNotFoundException(mode, featureConfigService.getFeatureModesFromFeatureAsString(feature.getKey())));
|
||||
}
|
||||
}
|
||||
@@ -50,6 +50,11 @@ public class FeatureFlagManagementServiceBean implements FeatureFlagManagementSe
|
||||
return getFeatureFlag(feature, server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean featureFlagExists(AFeature feature, AServer server) {
|
||||
return repository.existsByServerAndFeature(server, feature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureFlag getFeatureFlag(AFeature feature, AServer server) {
|
||||
return repository.findByServerAndFeature(server, feature);
|
||||
|
||||
@@ -1,26 +1,37 @@
|
||||
package dev.sheldan.abstracto.core.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.repository.FeatureModeRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class FeatureModeManagementServiceBean implements FeatureModeManagementService {
|
||||
|
||||
@Autowired
|
||||
private FeatureModeRepository featureModeRepository;
|
||||
|
||||
@Autowired
|
||||
private DefaultFeatureModeManagement defaultFeatureModeManagement;
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode) {
|
||||
public AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode, boolean enabled) {
|
||||
return createMode(featureFlag, mode.getKey(), enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode createMode(AFeatureFlag featureFlag, String mode, boolean enabled) {
|
||||
DefaultFeatureMode defaultMode = defaultFeatureModeManagement.getFeatureMode(featureFlag.getFeature(), mode);
|
||||
AFeatureMode aFeatureMode = AFeatureMode
|
||||
.builder()
|
||||
.featureFlag(featureFlag)
|
||||
.mode(mode.getKey())
|
||||
.server(featureFlag.getServer())
|
||||
.enabled(enabled)
|
||||
.featureMode(defaultMode)
|
||||
.build();
|
||||
|
||||
featureModeRepository.save(aFeatureMode);
|
||||
@@ -28,19 +39,40 @@ public class FeatureModeManagementServiceBean implements FeatureModeManagementSe
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode getModeForFeature(AFeatureFlag featureFlag) {
|
||||
return featureModeRepository.findByFeatureFlag(featureFlag);
|
||||
public boolean isFeatureModeActive(AFeature aFeature, AServer server, FeatureMode mode) {
|
||||
Optional<AFeatureMode> featureModeOptional = featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, mode.getKey());
|
||||
return featureModeOptional.isPresent() && featureModeOptional.get().getEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean featureModeSet(AFeature aFeature, AServer server) {
|
||||
return featureModeRepository.existsByFeatureFlag_ServerAndFeatureFlag_Feature(server, aFeature);
|
||||
public boolean doesFeatureModeExist(AFeature aFeature, AServer server, FeatureMode mode) {
|
||||
return getFeatureMode(aFeature, server, mode).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AFeatureMode setModeForFeature(AFeatureFlag featureFlag, FeatureMode featureMode) {
|
||||
AFeatureMode modeForFeature = getModeForFeature(featureFlag);
|
||||
modeForFeature.setMode(featureMode.getKey());
|
||||
return modeForFeature;
|
||||
public boolean doesFeatureModeExist(AFeature aFeature, AServer server, String modeKey) {
|
||||
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, modeKey).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AFeatureMode> getFeatureMode(AFeature aFeature, AServer server, FeatureMode mode) {
|
||||
return getFeatureMode(aFeature, server, mode.getKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AFeatureMode> getFeatureMode(AFeature aFeature, AServer server, String modeKey) {
|
||||
return featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, aFeature, modeKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AFeatureMode> getFeatureModesOfServer(AServer server) {
|
||||
return featureModeRepository.findByServer(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AFeatureMode> getFeatureModesOfFeatureInServer(AServer server, AFeature aFeature) {
|
||||
return featureModeRepository.findByServerAndFeatureFlag_Feature(server, aFeature);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -170,7 +170,19 @@
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="setMode"/>
|
||||
<column name="name" value="enableMode"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="disableMode"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="featureModes"/>
|
||||
<column name="module_id" valueComputed="${configModule}"/>
|
||||
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="default_feature_mode-table">
|
||||
<createTable tableName="default_feature_mode">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="default_feature_mode_pkey"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="mode" type="VARCHAR(255)"/>
|
||||
<column name="enabled" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="feature_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="default_feature_flag-fk_default_feature_mode_feature">
|
||||
<addForeignKeyConstraint baseColumnNames="feature_id" baseTableName="default_feature_mode" constraintName="fk_default_feature_mode_feature" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="feature" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -12,8 +12,13 @@
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="feature_mode_pkey"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="mode" type="VARCHAR(255)"/>
|
||||
<column name="enabled" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="feature_mode_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="feature_flag_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
@@ -22,4 +27,7 @@
|
||||
<changeSet author="Sheldan" id="feature_mode-fk_feature_mode_flag">
|
||||
<addForeignKeyConstraint baseColumnNames="feature_flag_id" baseTableName="feature_mode" constraintName="fk_feature_mode_flag" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="feature_flag" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="feature_mode-fk_feature_mode_mode">
|
||||
<addForeignKeyConstraint baseColumnNames="feature_mode_id" baseTableName="feature_mode" constraintName="fk_feature_mode_mode" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="default_feature_mode" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -19,6 +19,7 @@
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="channel_group.xml" relativeToChangelogFile="true"/>
|
||||
<include file="default_feature_flag.xml" relativeToChangelogFile="true"/>
|
||||
<include file="default_feature_mode.xml" relativeToChangelogFile="true" />
|
||||
<include file="feature_flag.xml" relativeToChangelogFile="true"/>
|
||||
<include file="feature_mode.xml" relativeToChangelogFile="true"/>
|
||||
<include file="lock.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.features;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
|
||||
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureNotFoundException;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DisableModeTest {
|
||||
|
||||
@InjectMocks
|
||||
private DisableMode testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Test(expected = InsufficientParametersException.class)
|
||||
public void testTooLittleParameters() {
|
||||
CommandTestUtilities.executeNoParametersTest(testUnit);
|
||||
}
|
||||
|
||||
@Test(expected = IncorrectParameterTypeException.class)
|
||||
public void testIncorrectParameterType() {
|
||||
CommandTestUtilities.executeWrongParametersTest(testUnit);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteDisable() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
FeatureEnum featureEnum = Mockito.mock(FeatureEnum.class);
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenReturn(featureEnum);
|
||||
FeatureMode featureMode = Mockito.mock(FeatureMode.class);
|
||||
when(featureModeService.getFeatureModeForKey(modeName)).thenReturn(featureMode);
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
CommandResult commandResultCompletableFuture = testUnit.execute(context);
|
||||
CommandTestUtilities.checkSuccessfulCompletion(commandResultCompletableFuture);
|
||||
verify(featureModeService, times(1)).disableFeatureModeForFeature(featureEnum, context.getUserInitiatedContext().getServer(), featureMode);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureNotFoundException.class)
|
||||
public void testExecuteDisableNotExistingFeature() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenThrow(new FeatureNotFoundException(featureName, new ArrayList<>()));
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
testUnit.execute(context);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureModeNotFoundException.class)
|
||||
public void testExecuteDisableNotExistingFeatureMode() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
FeatureEnum featureEnum = Mockito.mock(FeatureEnum.class);
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenReturn(featureEnum);
|
||||
when(featureModeService.getFeatureModeForKey(modeName)).thenThrow(new FeatureModeNotFoundException(modeName, new ArrayList<>()));
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
testUnit.execute(context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.features;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
|
||||
import dev.sheldan.abstracto.core.command.exception.InsufficientParametersException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureNotFoundException;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class EnableModeTest {
|
||||
|
||||
@InjectMocks
|
||||
private EnableMode testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Test(expected = InsufficientParametersException.class)
|
||||
public void testTooLittleParameters() {
|
||||
CommandTestUtilities.executeNoParametersTest(testUnit);
|
||||
}
|
||||
|
||||
@Test(expected = IncorrectParameterTypeException.class)
|
||||
public void testIncorrectParameterType() {
|
||||
CommandTestUtilities.executeWrongParametersTest(testUnit);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteDisable() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
FeatureEnum featureEnum = Mockito.mock(FeatureEnum.class);
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenReturn(featureEnum);
|
||||
FeatureMode featureMode = Mockito.mock(FeatureMode.class);
|
||||
when(featureModeService.getFeatureModeForKey(modeName)).thenReturn(featureMode);
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
CommandResult commandResultCompletableFuture = testUnit.execute(context);
|
||||
CommandTestUtilities.checkSuccessfulCompletion(commandResultCompletableFuture);
|
||||
verify(featureModeService, times(1)).enableFeatureModeForFeature(featureEnum, context.getUserInitiatedContext().getServer(), featureMode);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureNotFoundException.class)
|
||||
public void testExecuteDisableNotExistingFeature() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenThrow(new FeatureNotFoundException(featureName, new ArrayList<>()));
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
testUnit.execute(context);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureModeNotFoundException.class)
|
||||
public void testExecuteDisableNotExistingFeatureMode() {
|
||||
String featureName = "text";
|
||||
String modeName = "mode";
|
||||
FeatureEnum featureEnum = Mockito.mock(FeatureEnum.class);
|
||||
when(featureConfigService.getFeatureEnum(featureName)).thenReturn(featureEnum);
|
||||
when(featureModeService.getFeatureModeForKey(modeName)).thenThrow(new FeatureModeNotFoundException(modeName, new ArrayList<>()));
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(featureName, modeName));
|
||||
testUnit.execute(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package dev.sheldan.abstracto.core.commands.config.features;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.exception.FeatureNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModesModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureModesTest {
|
||||
|
||||
@InjectMocks
|
||||
private FeatureModes testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
|
||||
@Mock
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Mock
|
||||
private FeatureManagementService featureManagementService;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<FeatureModesModel> modelCaptor;
|
||||
|
||||
private static final String FEATURE_NAME = "feature";
|
||||
|
||||
@Test(expected = IncorrectParameterTypeException.class)
|
||||
public void testIncorrectParameterType() {
|
||||
CommandTestUtilities.executeWrongParametersTestAsync(testUnit);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteNoParameters() {
|
||||
CommandContext noParameters = CommandTestUtilities.getNoParameters();
|
||||
FeatureModeDisplay display1 = Mockito.mock(FeatureModeDisplay.class);
|
||||
FeatureModeDisplay display2 = Mockito.mock(FeatureModeDisplay.class);
|
||||
List<FeatureModeDisplay> featureModeDisplays = Arrays.asList(display1, display2);
|
||||
when(featureModeService.getEffectiveFeatureModes(noParameters.getUserInitiatedContext().getServer())).thenReturn(featureModeDisplays);
|
||||
when(channelService.sendEmbedTemplateInChannel(eq(FeatureModes.FEATURE_MODES_RESPONSE_TEMPLATE_KEY), modelCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(new ArrayList<>());
|
||||
CompletableFuture<CommandResult> commandResultCompletableFuture = testUnit.executeAsync(noParameters);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(commandResultCompletableFuture);
|
||||
List<FeatureModeDisplay> usedDisplays = modelCaptor.getValue().getFeatureModes();
|
||||
Assert.assertEquals(featureModeDisplays.size(), usedDisplays.size());
|
||||
Assert.assertEquals(featureModeDisplays, usedDisplays);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteFeatureParameter() {
|
||||
CommandContext noParameters = CommandTestUtilities.getWithParameters(Arrays.asList(FEATURE_NAME));
|
||||
FeatureModeDisplay display1 = Mockito.mock(FeatureModeDisplay.class);
|
||||
FeatureEnum featureEnum = Mockito.mock(FeatureEnum.class);
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureConfigService.getFeatureEnum(FEATURE_NAME)).thenReturn(featureEnum);
|
||||
AFeature feature = Mockito.mock(AFeature.class);
|
||||
when(featureManagementService.getFeature(FEATURE_NAME)).thenReturn(feature);
|
||||
List<FeatureModeDisplay> featureModeDisplays = Arrays.asList(display1);
|
||||
when(featureModeService.getEffectiveFeatureModes(noParameters.getUserInitiatedContext().getServer(), feature)).thenReturn(featureModeDisplays);
|
||||
when(channelService.sendEmbedTemplateInChannel(eq(FeatureModes.FEATURE_MODES_RESPONSE_TEMPLATE_KEY), modelCaptor.capture(), eq(noParameters.getChannel()))).thenReturn(new ArrayList<>());
|
||||
CompletableFuture<CommandResult> commandResultCompletableFuture = testUnit.executeAsync(noParameters);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(commandResultCompletableFuture);
|
||||
List<FeatureModeDisplay> usedDisplays = modelCaptor.getValue().getFeatureModes();
|
||||
Assert.assertEquals(featureModeDisplays.size(), usedDisplays.size());
|
||||
Assert.assertEquals(featureModeDisplays, usedDisplays);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureNotFoundException.class)
|
||||
public void testExecuteDisableNotExistingFeature() {
|
||||
when(featureConfigService.getFeatureEnum(FEATURE_NAME)).thenThrow(new FeatureNotFoundException(FEATURE_NAME, new ArrayList<>()));
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(FEATURE_NAME));
|
||||
testUnit.executeAsync(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package dev.sheldan.abstracto.core.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.DefaultFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultFeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureFlagListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private FeatureFlagListener testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureFlagManagementService service;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureFlagManagementService defaultFeatureFlagManagementService;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureFlag defaultFeatureFlag1;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureFlag defaultFeatureFlag2;
|
||||
|
||||
@Mock
|
||||
private AFeature aFeature1;
|
||||
|
||||
@Mock
|
||||
private AFeature aFeature2;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AFeatureFlag aFeatureFlag;
|
||||
|
||||
private static final Long SERVER_ID = 8L;
|
||||
|
||||
@Test
|
||||
public void testCreateMultipleOneAlreadyExisting() {
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(defaultFeatureFlagManagementService.getAllDefaultFeatureFlags()).thenReturn(Arrays.asList(defaultFeatureFlag1, defaultFeatureFlag2));
|
||||
when(defaultFeatureFlag1.getFeature()).thenReturn(aFeature1);
|
||||
when(defaultFeatureFlag2.getFeature()).thenReturn(aFeature2);
|
||||
when(defaultFeatureFlag2.isEnabled()).thenReturn(true);
|
||||
when(service.featureFlagExists(aFeature1, server)).thenReturn(true);
|
||||
when(service.featureFlagExists(aFeature2, server)).thenReturn(false);
|
||||
when(service.createFeatureFlag(aFeature2, SERVER_ID, true)).thenReturn(aFeatureFlag);
|
||||
testUnit.updateServerConfig(server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package dev.sheldan.abstracto.core.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureModeServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private FeatureModeServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Mock
|
||||
private FeatureFlagManagementService featureFlagManagementService;
|
||||
|
||||
@Mock
|
||||
private FeatureManagementService featureManagementService;
|
||||
|
||||
@Mock
|
||||
private FeatureModeManagementService featureModeManagementService;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureModeManagement defaultFeatureModeManagement;
|
||||
|
||||
@Mock
|
||||
private FeatureMode featureMode;
|
||||
|
||||
@Mock
|
||||
private AFeatureMode aFeatureMode;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private FeatureEnum featureEnum;
|
||||
|
||||
@Mock
|
||||
private AFeature feature;
|
||||
|
||||
@Mock
|
||||
private AFeatureFlag featureFlag;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureMode defaultFeatureMode;
|
||||
|
||||
@Mock
|
||||
private FeatureConfig featureConfig;
|
||||
|
||||
private static final String FEATURE_NAME = "feature";
|
||||
private static final String FEATURE_MODE = "mode";
|
||||
|
||||
@Test
|
||||
public void enableFeatureModeForFeatureWhichAlreadyExists() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.of(aFeatureMode));
|
||||
testUnit.enableFeatureModeForFeature(featureEnum, server, featureMode);
|
||||
verify(aFeatureMode, times(1)).setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enableFeatureModeForFeatureCreatingNewMode() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.empty());
|
||||
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
|
||||
testUnit.enableFeatureModeForFeature(featureEnum, server, featureMode);
|
||||
verify(featureModeManagementService, times(1)).createMode(featureFlag, featureMode, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFutureModeForFutureEnable() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.of(aFeatureMode));
|
||||
testUnit.setFutureModeForFuture(featureEnum, server, featureMode, true);
|
||||
verify(aFeatureMode, times(1)).setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFutureModeForFutureDisable() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.of(aFeatureMode));
|
||||
testUnit.setFutureModeForFuture(featureEnum, server, featureMode, false);
|
||||
verify(aFeatureMode, times(1)).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disableFeatureModeForFeatureWhichAlreadyExists() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.of(aFeatureMode));
|
||||
testUnit.disableFeatureModeForFeature(featureEnum, server, featureMode);
|
||||
verify(aFeatureMode, times(1)).setEnabled(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disableFeatureModeForFeatureCreatingNewMode() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.getFeatureMode(feature, server, featureMode)).thenReturn(Optional.empty());
|
||||
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
|
||||
testUnit.disableFeatureModeForFeature(featureEnum, server, featureMode);
|
||||
verify(featureModeManagementService, times(1)).createMode(featureFlag, featureMode, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeatureModeActiveForCustomizedFeatureMode() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.doesFeatureModeExist(feature, server, featureMode)).thenReturn(true);
|
||||
when(featureModeManagementService.isFeatureModeActive(feature, server, featureMode)).thenReturn(true);
|
||||
boolean actualResult = testUnit.featureModeActive(featureEnum, server, featureMode);
|
||||
Assert.assertTrue(actualResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFeatureModeActiveForDefaultFeatureMode() {
|
||||
when(featureEnum.getKey()).thenReturn(FEATURE_NAME);
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
when(featureManagementService.getFeature(featureEnum.getKey())).thenReturn(feature);
|
||||
when(featureModeManagementService.doesFeatureModeExist(feature, server, featureMode)).thenReturn(false);
|
||||
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
|
||||
when(defaultFeatureMode.isEnabled()).thenReturn(true);
|
||||
boolean actualResult = testUnit.featureModeActive(featureEnum, server, featureMode);
|
||||
Assert.assertTrue(actualResult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureModeForKey() {
|
||||
FeatureConfig featureConfig1 = Mockito.mock(FeatureConfig.class);
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
FeatureMode featureMode2 = Mockito.mock(FeatureMode.class);
|
||||
when(featureConfig1.getAvailableModes()).thenReturn(Arrays.asList(featureMode, featureMode2));
|
||||
when(featureConfigService.getAllFeatureConfigs()).thenReturn(Arrays.asList(featureConfig1));
|
||||
FeatureMode featureModeForKey = testUnit.getFeatureModeForKey(FEATURE_MODE);
|
||||
Assert.assertEquals(featureMode, featureModeForKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllAvailableFeatureModes() {
|
||||
FeatureConfig featureConfig1 = Mockito.mock(FeatureConfig.class);
|
||||
FeatureMode featureMode2 = Mockito.mock(FeatureMode.class);
|
||||
when(featureConfig1.getAvailableModes()).thenReturn(Arrays.asList(featureMode, featureMode2));
|
||||
FeatureConfig featureConfig2 = Mockito.mock(FeatureConfig.class);
|
||||
FeatureMode featureMode3 = Mockito.mock(FeatureMode.class);
|
||||
FeatureMode featureMode4 = Mockito.mock(FeatureMode.class);
|
||||
when(featureConfig2.getAvailableModes()).thenReturn(Arrays.asList(featureMode3, featureMode4));
|
||||
when(featureConfigService.getAllFeatureConfigs()).thenReturn(Arrays.asList(featureConfig1, featureConfig2));
|
||||
List<FeatureMode> allAvailableFeatureModes = testUnit.getAllAvailableFeatureModes();
|
||||
Assert.assertEquals(4, allAvailableFeatureModes.size());
|
||||
Assert.assertEquals(featureMode, allAvailableFeatureModes.get(0));
|
||||
Assert.assertEquals(featureMode2, allAvailableFeatureModes.get(1));
|
||||
Assert.assertEquals(featureMode3, allAvailableFeatureModes.get(2));
|
||||
Assert.assertEquals(featureMode4, allAvailableFeatureModes.get(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEffectiveFeatureModesOnlyOneDefault() {
|
||||
when(defaultFeatureMode.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureMode.isEnabled()).thenReturn(true);
|
||||
when(defaultFeatureMode.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode));
|
||||
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
|
||||
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(new ArrayList<>());
|
||||
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
|
||||
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
|
||||
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
|
||||
Assert.assertEquals(1, effectiveFeatureModes.size());
|
||||
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
|
||||
Assert.assertEquals(true, featureModeDisplay.getIsDefaultValue());
|
||||
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
|
||||
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
|
||||
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
|
||||
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
|
||||
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEffectiveFeatureModesOnlyOneCustomized() {
|
||||
when(aFeatureMode.getEnabled()).thenReturn(true);
|
||||
when(aFeatureMode.getFeatureFlag()).thenReturn(featureFlag);
|
||||
when(aFeatureMode.getServer()).thenReturn(server);
|
||||
when(aFeatureMode.getFeatureMode()).thenReturn(defaultFeatureMode);
|
||||
when(featureFlag.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode));
|
||||
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
|
||||
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(Arrays.asList(aFeatureMode));
|
||||
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
|
||||
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
|
||||
Assert.assertEquals(1, effectiveFeatureModes.size());
|
||||
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
|
||||
Assert.assertEquals(false, featureModeDisplay.getIsDefaultValue());
|
||||
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
|
||||
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
|
||||
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
|
||||
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
|
||||
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEffectiveFeatureModesMixed() {
|
||||
when(aFeatureMode.getEnabled()).thenReturn(true);
|
||||
when(aFeatureMode.getFeatureFlag()).thenReturn(featureFlag);
|
||||
when(aFeatureMode.getServer()).thenReturn(server);
|
||||
when(aFeatureMode.getFeatureMode()).thenReturn(defaultFeatureMode);
|
||||
when(featureFlag.getFeature()).thenReturn(feature);
|
||||
DefaultFeatureMode defaultFeatureMode2 = Mockito.mock(DefaultFeatureMode.class);
|
||||
when(defaultFeatureMode2.getMode()).thenReturn("SECOND");
|
||||
when(defaultFeatureMode2.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureMode2.isEnabled()).thenReturn(false);
|
||||
when(defaultFeatureModeManagement.getAll()).thenReturn(Arrays.asList(defaultFeatureMode2, defaultFeatureMode));
|
||||
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
|
||||
when(featureModeManagementService.getFeatureModesOfServer(server)).thenReturn(Arrays.asList(aFeatureMode));
|
||||
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
|
||||
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
|
||||
|
||||
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server);
|
||||
|
||||
Assert.assertEquals(2, effectiveFeatureModes.size());
|
||||
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
|
||||
Assert.assertEquals(false, featureModeDisplay.getIsDefaultValue());
|
||||
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
|
||||
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
|
||||
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
|
||||
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
|
||||
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
|
||||
|
||||
FeatureModeDisplay featureModeDisplay2 = effectiveFeatureModes.get(1);
|
||||
Assert.assertEquals(true, featureModeDisplay2.getIsDefaultValue());
|
||||
Assert.assertFalse(featureModeDisplay2.getFeatureMode().getEnabled());
|
||||
Assert.assertEquals(featureFlag, featureModeDisplay2.getFeatureMode().getFeatureFlag());
|
||||
Assert.assertEquals(server, featureModeDisplay2.getFeatureMode().getServer());
|
||||
Assert.assertEquals(defaultFeatureMode2, featureModeDisplay2.getFeatureMode().getFeatureMode());
|
||||
Assert.assertEquals(featureConfig, featureModeDisplay2.getFeatureConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetEffectiveFeatureModesForFeature() {
|
||||
when(defaultFeatureMode.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureMode.isEnabled()).thenReturn(true);
|
||||
when(defaultFeatureMode.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureModeManagement.getFeatureModesForFeature(feature)).thenReturn(Arrays.asList(defaultFeatureMode));
|
||||
when(featureConfigService.getFeatureConfigForFeature(feature)).thenReturn(featureConfig);
|
||||
when(featureModeManagementService.getFeatureModesOfFeatureInServer(server, feature)).thenReturn(new ArrayList<>());
|
||||
when(defaultFeatureMode.getMode()).thenReturn(FEATURE_MODE);
|
||||
when(featureFlagManagementService.getFeatureFlag(feature, server)).thenReturn(featureFlag);
|
||||
List<FeatureModeDisplay> effectiveFeatureModes = testUnit.getEffectiveFeatureModes(server, feature);
|
||||
Assert.assertEquals(1, effectiveFeatureModes.size());
|
||||
FeatureModeDisplay featureModeDisplay = effectiveFeatureModes.get(0);
|
||||
Assert.assertEquals(true, featureModeDisplay.getIsDefaultValue());
|
||||
Assert.assertTrue(featureModeDisplay.getFeatureMode().getEnabled());
|
||||
Assert.assertEquals(featureFlag, featureModeDisplay.getFeatureMode().getFeatureFlag());
|
||||
Assert.assertEquals(server, featureModeDisplay.getFeatureMode().getServer());
|
||||
Assert.assertEquals(defaultFeatureMode, featureModeDisplay.getFeatureMode().getFeatureMode());
|
||||
Assert.assertEquals(featureConfig, featureModeDisplay.getFeatureConfig());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package dev.sheldan.abstracto.core.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.FeatureModeNotFoundException;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
|
||||
import dev.sheldan.abstracto.core.repository.DefaultFeatureModeRepository;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultFeatureModeManagementBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private DefaultFeatureModeManagementBean testUnit;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureModeRepository defaultFeatureModeRepository;
|
||||
|
||||
@Mock
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Mock
|
||||
private AFeature feature;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureMode defaultFeatureMode1;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureMode defaultFeatureMode2;
|
||||
|
||||
private static final String MODE_NAME = "mode";
|
||||
|
||||
@Test
|
||||
public void getFeatureModesForFeature() {
|
||||
List<DefaultFeatureMode> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
|
||||
when(defaultFeatureModeRepository.findByFeature(feature)).thenReturn(defaultFeatureModes);
|
||||
List<DefaultFeatureMode> featureModesForFeature = testUnit.getFeatureModesForFeature(feature);
|
||||
Assert.assertEquals(defaultFeatureModes.size(), featureModesForFeature.size());
|
||||
Assert.assertEquals(defaultFeatureModes, featureModesForFeature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAll() {
|
||||
List<DefaultFeatureMode> defaultFeatureModes = Arrays.asList(defaultFeatureMode1, defaultFeatureMode2);
|
||||
when(defaultFeatureModeRepository.findAll()).thenReturn(defaultFeatureModes);
|
||||
List<DefaultFeatureMode> featureModesForFeature = testUnit.getAll();
|
||||
Assert.assertEquals(defaultFeatureModes.size(), featureModesForFeature.size());
|
||||
Assert.assertEquals(defaultFeatureModes, featureModesForFeature);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureModeOptional() {
|
||||
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.of(defaultFeatureMode1));
|
||||
Optional<DefaultFeatureMode> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
|
||||
Assert.assertTrue(featureModeOptional.isPresent());
|
||||
featureModeOptional.ifPresent(defaultFeatureMode ->
|
||||
Assert.assertEquals(defaultFeatureMode1, defaultFeatureMode)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureModeOptionalNotExisting() {
|
||||
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.empty());
|
||||
Optional<DefaultFeatureMode> featureModeOptional = testUnit.getFeatureModeOptional(feature, MODE_NAME);
|
||||
Assert.assertFalse(featureModeOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureMode() {
|
||||
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.of(defaultFeatureMode1));
|
||||
DefaultFeatureMode defaultFeatureMode = testUnit.getFeatureMode(feature, MODE_NAME);
|
||||
Assert.assertEquals(defaultFeatureMode1, defaultFeatureMode);
|
||||
}
|
||||
|
||||
@Test(expected = FeatureModeNotFoundException.class)
|
||||
public void getFeatureModeNotExisting() {
|
||||
when(defaultFeatureModeRepository.findByFeatureAndMode(feature, MODE_NAME)).thenReturn(Optional.empty());
|
||||
testUnit.getFeatureMode(feature, MODE_NAME);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
package dev.sheldan.abstracto.core.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.repository.FeatureModeRepository;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureModeManagementServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private FeatureModeManagementServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureModeRepository featureModeRepository;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureModeManagement defaultFeatureModeManagement;
|
||||
|
||||
@Mock
|
||||
private AFeature feature;
|
||||
|
||||
@Mock
|
||||
private DefaultFeatureMode defaultFeatureMode;
|
||||
|
||||
@Mock
|
||||
private AFeatureFlag featureFlag;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private FeatureMode featureMode;
|
||||
|
||||
@Mock
|
||||
private AFeatureMode aFeatureMode;
|
||||
|
||||
private static final String FEATURE_MODE = "featureMode";
|
||||
|
||||
@Test
|
||||
public void createModeWithModeAsString() {
|
||||
when(featureFlag.getServer()).thenReturn(server);
|
||||
when(featureFlag.getFeature()).thenReturn(feature);
|
||||
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
|
||||
AFeatureMode createdMode = testUnit.createMode(featureFlag, FEATURE_MODE, true);
|
||||
Assert.assertEquals(true, createdMode.getEnabled());
|
||||
Assert.assertEquals(featureFlag, createdMode.getFeatureFlag());
|
||||
Assert.assertEquals(defaultFeatureMode, createdMode.getFeatureMode());
|
||||
Assert.assertEquals(server, createdMode.getServer());
|
||||
verify(featureModeRepository, times(1)).save(createdMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMode() {
|
||||
when(featureFlag.getServer()).thenReturn(server);
|
||||
when(featureFlag.getFeature()).thenReturn(feature);
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
when(defaultFeatureModeManagement.getFeatureMode(feature, FEATURE_MODE)).thenReturn(defaultFeatureMode);
|
||||
AFeatureMode createdMode = testUnit.createMode(featureFlag, featureMode, true);
|
||||
Assert.assertEquals(true, createdMode.getEnabled());
|
||||
Assert.assertEquals(featureFlag, createdMode.getFeatureFlag());
|
||||
Assert.assertEquals(defaultFeatureMode, createdMode.getFeatureMode());
|
||||
Assert.assertEquals(server, createdMode.getServer());
|
||||
verify(featureModeRepository, times(1)).save(createdMode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeActive() {
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
when(aFeatureMode.getEnabled()).thenReturn(true);
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
|
||||
Assert.assertTrue(testUnit.isFeatureModeActive(feature, server, featureMode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeNotActive() {
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
when(aFeatureMode.getEnabled()).thenReturn(false);
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
|
||||
Assert.assertFalse(testUnit.isFeatureModeActive(feature, server, featureMode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeNotPresent() {
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
|
||||
Assert.assertFalse(testUnit.isFeatureModeActive(feature, server, featureMode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeStringExists() {
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
|
||||
Assert.assertTrue(testUnit.doesFeatureModeExist(feature, server, FEATURE_MODE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeObjectExists() {
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
Assert.assertTrue(testUnit.doesFeatureModeExist(feature, server, featureMode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void featureModeDoesNotExist() {
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
|
||||
when(featureMode.getKey()).thenReturn(FEATURE_MODE);
|
||||
Assert.assertFalse(testUnit.doesFeatureModeExist(feature, server, featureMode));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFeatureModeOptional() {
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.of(aFeatureMode));
|
||||
Optional<AFeatureMode> featureModeOptional = testUnit.getFeatureMode(feature, server, FEATURE_MODE);
|
||||
Assert.assertTrue(featureModeOptional.isPresent());
|
||||
featureModeOptional.ifPresent(aFeatureMode1 ->
|
||||
Assert.assertEquals(aFeatureMode, aFeatureMode1)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetFeatureModeOptionalNotExisting() {
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_FeatureAndFeatureMode_Mode(server, feature, FEATURE_MODE)).thenReturn(Optional.empty());
|
||||
Optional<AFeatureMode> featureModeOptional = testUnit.getFeatureMode(feature, server, FEATURE_MODE);
|
||||
Assert.assertFalse(featureModeOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureModesOfServer() {
|
||||
List<AFeatureMode> expected = Arrays.asList(aFeatureMode, aFeatureMode);
|
||||
when(featureModeRepository.findByServer(server)).thenReturn(expected);
|
||||
List<AFeatureMode> featureModesOfServer = testUnit.getFeatureModesOfServer(server);
|
||||
Assert.assertEquals(expected, featureModesOfServer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFeatureModesOfFeatureInServer() {
|
||||
List<AFeatureMode> expected = Arrays.asList(aFeatureMode);
|
||||
when(featureModeRepository.findByServerAndFeatureFlag_Feature(server, feature)).thenReturn(expected);
|
||||
List<AFeatureMode> featureModesOfServer = testUnit.getFeatureModesOfFeatureInServer(server, feature);
|
||||
Assert.assertEquals(expected, featureModesOfServer);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,22 @@
|
||||
|
||||
<artifactId>core-interface</artifactId>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>test-jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -2,51 +2,33 @@ package dev.sheldan.abstracto.core.command.condition;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.models.exception.IncorrectFeatureModeMessage;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.exception.IncorrectFeatureModeException;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class FeatureModeCondition implements CommandCondition {
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private FeatureConfigService featureConfigService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService modeService;
|
||||
|
||||
@Override
|
||||
public ConditionResult shouldExecute(CommandContext context, Command command) {
|
||||
String reason = "";
|
||||
boolean featureModeFits = true;
|
||||
if(!command.getFeatureModeLimitations().isEmpty()){
|
||||
FeatureEnum feature = command.getFeature();
|
||||
if(feature != null) {
|
||||
AFeatureMode featureMode = modeService.getFeatureMode(feature, context.getUserInitiatedContext().getServer());
|
||||
featureModeFits = command.getFeatureModeLimitations().stream().anyMatch(featureMode1 -> featureMode1.getKey().equalsIgnoreCase(featureMode.getMode()));
|
||||
if(!featureModeFits) {
|
||||
IncorrectFeatureModeMessage featureDisabledMessage = IncorrectFeatureModeMessage
|
||||
.builder()
|
||||
.featureConfig(featureConfigService.getFeatureDisplayForFeature(feature))
|
||||
.command(command)
|
||||
.build();
|
||||
reason = templateService.renderTemplate("feature_mode_not_correct_message", featureDisabledMessage);
|
||||
for (FeatureMode featureModeLimitation : command.getFeatureModeLimitations()) {
|
||||
if(modeService.featureModeActive(feature, context.getUserInitiatedContext().getServer(), featureModeLimitation)) {
|
||||
return ConditionResult.builder().result(true).build();
|
||||
}
|
||||
}
|
||||
throw new IncorrectFeatureModeException(command, feature, command.getFeatureModeLimitations());
|
||||
}
|
||||
}
|
||||
|
||||
return ConditionResult.builder().reason(reason).result(featureModeFits).build();
|
||||
return ConditionResult.builder().result(true).build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.sheldan.abstracto.core.exception;
|
||||
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.exception.IncorrectFeatureModeExceptionModel;
|
||||
import dev.sheldan.abstracto.templating.Templatable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class IncorrectFeatureModeException extends AbstractoRunTimeException implements Templatable {
|
||||
|
||||
private final IncorrectFeatureModeExceptionModel model;
|
||||
|
||||
public IncorrectFeatureModeException(Command command, FeatureEnum featureEnum, List<FeatureMode> requiredModes) {
|
||||
super("Incorrect feature mode for the command.");
|
||||
this.model = IncorrectFeatureModeExceptionModel.builder().command(command).featureEnum(featureEnum).requiredModes(requiredModes).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "incorrect_feature_mode_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return model;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@@ -35,6 +36,12 @@ public class AFeatureFlag implements Serializable {
|
||||
@JoinColumn(name = "feature_id", nullable = false)
|
||||
private AFeature feature;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "featureFlag")
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
private List<AFeatureMode> modes;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean enabled;
|
||||
|
||||
@@ -23,14 +23,26 @@ public class AFeatureMode implements Serializable {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToOne
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "feature_flag_id", nullable = false)
|
||||
private AFeatureFlag featureFlag;
|
||||
|
||||
@Column
|
||||
@Setter
|
||||
@Getter
|
||||
private String mode;
|
||||
@Setter
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "feature_mode_id", nullable = false)
|
||||
private DefaultFeatureMode featureMode;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToOne
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column
|
||||
@Getter
|
||||
@Setter
|
||||
private Boolean enabled;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package dev.sheldan.abstracto.core.models.database;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="default_feature_mode")
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Cacheable
|
||||
@EqualsAndHashCode
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class DefaultFeatureMode implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Getter
|
||||
@Column(name = "id")
|
||||
public Long id;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToOne
|
||||
@JoinColumn(name = "feature_id", nullable = false)
|
||||
private AFeature feature;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToMany(fetch = FetchType.LAZY, mappedBy = "featureMode")
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
private List<AFeatureMode> modes;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean enabled;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String mode;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@PrePersist
|
||||
private void onInsert() {
|
||||
this.created = Instant.now();
|
||||
}
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updateTimestamp;
|
||||
|
||||
@PreUpdate
|
||||
private void onUpdate() {
|
||||
this.updateTimestamp = Instant.now();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.core.models.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class IncorrectFeatureModeExceptionModel implements Serializable {
|
||||
private List<FeatureMode> requiredModes;
|
||||
private Command command;
|
||||
private FeatureEnum featureEnum;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.abstracto.core.models.template.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class FeatureModeDisplay {
|
||||
private AFeatureMode featureMode;
|
||||
private FeatureConfig featureConfig;
|
||||
private Boolean isDefaultValue;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.core.models.template.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
public class FeatureModesModel extends UserInitiatedServerContext {
|
||||
private List<FeatureModeDisplay> featureModes;
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
|
||||
import java.util.List;
|
||||
@@ -22,5 +23,6 @@ public interface FeatureConfigService {
|
||||
PostTargetEnum getPostTargetEnumByKey(String key);
|
||||
FeatureValidationResult validateFeatureSetup(FeatureConfig featureConfig, AServer server);
|
||||
FeatureMode getFeatureModeByKey(FeatureConfig featureConfig, String key);
|
||||
FeatureConfig getFeatureConfigForFeature(AFeature feature);
|
||||
boolean isModeValid(String featureName, String modeName);
|
||||
}
|
||||
|
||||
@@ -3,27 +3,19 @@ package dev.sheldan.abstracto.core.service;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface FeatureModeService {
|
||||
AFeatureMode setModeForFeatureTo(String key, AServer server, String newMode);
|
||||
AFeatureMode setModeForFeatureTo(AFeatureFlag flag, String newMode);
|
||||
AFeatureMode setModeForFeatureTo(FeatureEnum featureEnum, AServer server, String newMode);
|
||||
AFeatureMode setModeForFeatureTo(AFeature featureEnum, AServer server, String newMode);
|
||||
AFeatureMode setModeForFeatureTo(FeatureEnum featureEnum, AServer server, FeatureMode mode);
|
||||
AFeatureMode setModeForFeatureTo(AFeature feature, AServer server, FeatureMode mode);
|
||||
AFeatureMode setModeForFeatureTo(AFeatureFlag featureFlag, FeatureMode mode);
|
||||
|
||||
AFeatureMode createMode(String key, AServer server, String newMode);
|
||||
AFeatureMode createMode(AFeatureFlag flag, String newMode);
|
||||
AFeatureMode createMode(FeatureEnum featureEnum, AServer server, String newMode);
|
||||
AFeatureMode createMode(AFeature featureEnum, AServer server, String newMode);
|
||||
AFeatureMode createMode(FeatureEnum featureEnum, AServer server, FeatureMode mode);
|
||||
AFeatureMode createMode(AFeature feature, AServer server, FeatureMode mode);
|
||||
AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode);
|
||||
|
||||
AFeatureMode getFeatureMode(FeatureEnum featureEnum, AServer server);
|
||||
AFeatureMode getFeatureMode(AFeature feature, AServer server);
|
||||
void enableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode);
|
||||
void setFutureModeForFuture(FeatureEnum featureEnum, AServer server, FeatureMode mode, Boolean newValue);
|
||||
void disableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode);
|
||||
boolean featureModeActive(FeatureEnum featureEnum, AServer server, FeatureMode mode);
|
||||
FeatureMode getFeatureModeForKey(String key);
|
||||
List<FeatureMode> getAllAvailableFeatureModes();
|
||||
List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server);
|
||||
List<FeatureModeDisplay> getEffectiveFeatureModes(AServer server, AFeature feature);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.abstracto.core.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AFeature;
|
||||
import dev.sheldan.abstracto.core.models.database.DefaultFeatureMode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface DefaultFeatureModeManagement {
|
||||
List<DefaultFeatureMode> getFeatureModesForFeature(AFeature feature);
|
||||
List<DefaultFeatureMode> getAll();
|
||||
Optional<DefaultFeatureMode> getFeatureModeOptional(AFeature feature, String mode);
|
||||
DefaultFeatureMode getFeatureMode(AFeature feature, String mode);
|
||||
}
|
||||
@@ -10,6 +10,7 @@ public interface FeatureFlagManagementService {
|
||||
AFeatureFlag createFeatureFlag(AFeature feature, Long serverId, Boolean newValue);
|
||||
AFeatureFlag createFeatureFlag(AFeature feature, AServer server, Boolean newValue);
|
||||
AFeatureFlag getFeatureFlag(AFeature key, Long serverId);
|
||||
boolean featureFlagExists(AFeature feature, AServer server);
|
||||
AFeatureFlag getFeatureFlag(AFeature key, AServer server);
|
||||
List<AFeatureFlag> getFeatureFlagsOfServer(AServer server);
|
||||
AFeatureFlag setFeatureFlagValue(AFeature feature, Long serverId, Boolean newValue);
|
||||
|
||||
@@ -6,9 +6,18 @@ import dev.sheldan.abstracto.core.models.database.AFeatureFlag;
|
||||
import dev.sheldan.abstracto.core.models.database.AFeatureMode;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface FeatureModeManagementService {
|
||||
AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode);
|
||||
AFeatureMode getModeForFeature(AFeatureFlag featureFlag);
|
||||
boolean featureModeSet(AFeature aFeature, AServer server);
|
||||
AFeatureMode setModeForFeature(AFeatureFlag featureFlag, FeatureMode featureMode);
|
||||
AFeatureMode createMode(AFeatureFlag featureFlag, FeatureMode mode, boolean enabled);
|
||||
AFeatureMode createMode(AFeatureFlag featureFlag, String mode, boolean enabled);
|
||||
|
||||
boolean isFeatureModeActive(AFeature aFeature, AServer server, FeatureMode mode);
|
||||
boolean doesFeatureModeExist(AFeature aFeature, AServer server, FeatureMode mode);
|
||||
boolean doesFeatureModeExist(AFeature aFeature, AServer server, String modeKey);
|
||||
Optional<AFeatureMode> getFeatureMode(AFeature aFeature, AServer server, FeatureMode mode);
|
||||
Optional<AFeatureMode> getFeatureMode(AFeature aFeature, AServer server, String modeKey);
|
||||
List<AFeatureMode> getFeatureModesOfServer(AServer server);
|
||||
List<AFeatureMode> getFeatureModesOfFeatureInServer(AServer server, AFeature aFeature);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package dev.sheldan.abstracto.core.command.condition;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.exception.IncorrectFeatureModeException;
|
||||
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class FeatureModeConditionTest {
|
||||
|
||||
@InjectMocks
|
||||
private FeatureModeCondition testUnit;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService modeService;
|
||||
|
||||
@Mock
|
||||
private Command command;
|
||||
|
||||
@Mock
|
||||
private CommandContext commandContext;
|
||||
|
||||
@Mock
|
||||
private FeatureMode featureMode;
|
||||
|
||||
@Mock
|
||||
private FeatureEnum featureEnum;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private UserInitiatedServerContext userInitiatedServerContext;
|
||||
|
||||
@Test
|
||||
public void testNoLimitations() {
|
||||
when(command.getFeatureModeLimitations()).thenReturn(new ArrayList<>());
|
||||
CommandTestUtilities.checkSuccessfulCondition(testUnit.shouldExecute(commandContext, command));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetLimitations() {
|
||||
when(commandContext.getUserInitiatedContext()).thenReturn(userInitiatedServerContext);
|
||||
when(userInitiatedServerContext.getServer()).thenReturn(server);
|
||||
when(command.getFeature()).thenReturn(featureEnum);
|
||||
when(modeService.featureModeActive(featureEnum, server, featureMode)).thenReturn(true);
|
||||
when(command.getFeatureModeLimitations()).thenReturn(Arrays.asList(featureMode));
|
||||
CommandTestUtilities.checkSuccessfulCondition(testUnit.shouldExecute(commandContext, command));
|
||||
}
|
||||
|
||||
@Test(expected = IncorrectFeatureModeException.class)
|
||||
public void testLimitedCommand() {
|
||||
when(commandContext.getUserInitiatedContext()).thenReturn(userInitiatedServerContext);
|
||||
when(userInitiatedServerContext.getServer()).thenReturn(server);
|
||||
when(command.getFeature()).thenReturn(featureEnum);
|
||||
when(modeService.featureModeActive(featureEnum, server, featureMode)).thenReturn(false);
|
||||
when(command.getFeatureModeLimitations()).thenReturn(Arrays.asList(featureMode));
|
||||
testUnit.shouldExecute(commandContext, command);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.abstracto.core.test;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
|
||||
public class MockUtils {
|
||||
|
||||
private MockUtils() {
|
||||
|
||||
}
|
||||
|
||||
public static AUserInAServer getUserObject(Long id, AServer server) {
|
||||
AUser user = AUser.builder().id(id).build();
|
||||
AUserInAServer createdUser = AUserInAServer.builder().userReference(user).serverReference(server).userInServerId(id).build();
|
||||
server.getUsers().add(createdUser);
|
||||
return createdUser;
|
||||
}
|
||||
|
||||
public static AServer getServer(Long id){
|
||||
return AServer.builder().id(id).build();
|
||||
}
|
||||
|
||||
public static AServer getServer() {
|
||||
return getServer(2L);
|
||||
}
|
||||
|
||||
public static AChannel getTextChannel(AServer server, Long id) {
|
||||
return AChannel.builder().id(id).server(server).deleted(false).type(AChannelType.TEXT).build();
|
||||
}
|
||||
|
||||
public static ARole getRole(Long id, AServer server) {
|
||||
return ARole.builder().server(server).id(id).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.abstracto.core.test.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import org.junit.Assert;
|
||||
|
||||
public class CommandConfigValidator {
|
||||
|
||||
private CommandConfigValidator() {
|
||||
|
||||
}
|
||||
|
||||
public static void validateCommandConfiguration(CommandConfiguration toValidate) {
|
||||
Assert.assertNotNull(toValidate.getModule());
|
||||
Assert.assertNotNull(toValidate.getName());
|
||||
if(toValidate.isTemplated()) {
|
||||
Assert.assertNull(toValidate.getDescription());
|
||||
} else {
|
||||
Assert.assertNotNull(toValidate.getDescription());
|
||||
}
|
||||
toValidate.getParameters().forEach(parameter -> {
|
||||
Assert.assertNotNull(parameter.getName());
|
||||
Assert.assertNotNull(parameter.getType());
|
||||
if(parameter.getTemplated()) {
|
||||
Assert.assertNull(parameter.getDescription());
|
||||
} else {
|
||||
Assert.assertNotNull(parameter.getDescription());
|
||||
}
|
||||
});
|
||||
HelpInfo helpInfo = toValidate.getHelp();
|
||||
Assert.assertNotNull(helpInfo);
|
||||
if(helpInfo.isTemplated()) {
|
||||
Assert.assertNull(helpInfo.getLongHelp());
|
||||
Assert.assertNull(helpInfo.getExample());
|
||||
} else {
|
||||
Assert.assertNotNull(helpInfo.getLongHelp());
|
||||
if(helpInfo.isHasExample()) {
|
||||
Assert.assertNotNull(helpInfo.getExample());
|
||||
} else {
|
||||
Assert.assertNull(helpInfo.getExample());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package dev.sheldan.abstracto.core.test.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.condition.ConditionResult;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameters;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.test.MockUtils;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.junit.Assert;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class CommandTestUtilities {
|
||||
|
||||
private CommandTestUtilities() {
|
||||
|
||||
}
|
||||
|
||||
public static void checkSuccessfulCondition(ConditionResult result) {
|
||||
Assert.assertTrue(result.isResult());
|
||||
}
|
||||
|
||||
public static void executeNoParametersTest(Command com) {
|
||||
CommandContext context = CommandTestUtilities.getNoParameters();
|
||||
com.execute(context);
|
||||
}
|
||||
|
||||
public static void executeNoParametersTestAsync(Command com) {
|
||||
CommandContext context = CommandTestUtilities.getNoParameters();
|
||||
com.executeAsync(context);
|
||||
}
|
||||
|
||||
public static void executeWrongParametersTest(Command com) {
|
||||
executeWrongParametersTest(com, new ArrayList<>());
|
||||
}
|
||||
|
||||
public static void executeWrongParametersTest(Command com, Object value) {
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(value));
|
||||
com.execute(context);
|
||||
}
|
||||
|
||||
public static void executeWrongParametersTestAsync(Command com) {
|
||||
executeWrongParametersTestAsync(com, new ArrayList<>());
|
||||
}
|
||||
|
||||
public static void executeWrongParametersTestAsync(Command com, Object value) {
|
||||
CommandContext context = CommandTestUtilities.getWithParameters(Arrays.asList(value));
|
||||
com.executeAsync(context);
|
||||
}
|
||||
|
||||
public static CommandContext getNoParameters() {
|
||||
AServer server = MockUtils.getServer();
|
||||
AUserInAServer author = MockUtils.getUserObject(3L, server);
|
||||
CommandContext context = CommandContext
|
||||
.builder()
|
||||
.build();
|
||||
Guild guild = Mockito.mock(Guild.class);
|
||||
context.setGuild(guild);
|
||||
Member member = Mockito.mock(Member.class);
|
||||
context.setAuthor(member);
|
||||
long channelId = 4L;
|
||||
TextChannel mockedTextChannel = Mockito.mock(TextChannel.class);
|
||||
UserInitiatedServerContext userInitiatedContext = UserInitiatedServerContext
|
||||
.builder()
|
||||
.server(server)
|
||||
.guild(guild)
|
||||
.aUserInAServer(author)
|
||||
.member(member)
|
||||
.user(author.getUserReference())
|
||||
.channel(MockUtils.getTextChannel(server, channelId))
|
||||
.messageChannel(mockedTextChannel)
|
||||
.build();
|
||||
context.setUserInitiatedContext(userInitiatedContext);
|
||||
context.setChannel(mockedTextChannel);
|
||||
context.setParameters(Parameters.builder().parameters(new ArrayList<>()).build());
|
||||
context.setMessage(Mockito.mock(Message.class));
|
||||
return context;
|
||||
}
|
||||
|
||||
public static CommandContext getWithParameters(List<Object> parameters) {
|
||||
CommandContext context = getNoParameters();
|
||||
context.getParameters().getParameters().addAll(parameters);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static CommandContext enhanceWithParameters(CommandContext context, List<Object> parameters) {
|
||||
context.getParameters().getParameters().addAll(parameters);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static void checkSuccessfulCompletion(CommandResult result){
|
||||
Assert.assertEquals(ResultState.SUCCESSFUL, result.getResult());
|
||||
}
|
||||
|
||||
public static void checkSuccessfulCompletionAsync(CompletableFuture<CommandResult> result){
|
||||
Assert.assertEquals(ResultState.SUCCESSFUL, result.join().getResult());
|
||||
}
|
||||
|
||||
public static List<CompletableFuture<Message>> messageFutureList() {
|
||||
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user