package fr.xephi.authme.settings.commandconfig; import com.github.authme.configme.migration.MigrationService; import com.github.authme.configme.properties.Property; import com.github.authme.configme.resource.PropertyResource; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.settings.SettingsMigrationService; import fr.xephi.authme.util.RandomStringUtils; import javax.inject.Inject; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; /** * Migrates the commands from their old location, in config.yml, to the dedicated commands configuration file. */ class CommandMigrationService implements MigrationService { @Inject private SettingsMigrationService settingsMigrationService; CommandMigrationService() { } @Override public boolean checkAndMigrate(PropertyResource resource, List> properties) { final CommandConfig commandConfig = CommandSettingsHolder.COMMANDS.getValue(resource); final boolean didMoveCommands = transformOldCommands(commandConfig); if (didMoveCommands) { // TODO ConfigMe/#29: Check that loaded file isn't completely empty resource.setValue("", commandConfig); return true; } return false; } /** * Adds command settings from their old location (in config.yml) to the given command configuration object. * * @param commandConfig the command config object to move old commands to * @return true if commands have been moved, false if no migration was necessary */ @VisibleForTesting boolean transformOldCommands(CommandConfig commandConfig) { boolean didMoveCommands = false; for (MigratableCommandSection section : MigratableCommandSection.values()) { didMoveCommands |= section.convertCommands(settingsMigrationService, commandConfig); } return didMoveCommands; } /** * Enum defining the forced command settings that should be moved from config.yml to the new commands.yml file. */ private enum MigratableCommandSection { ON_JOIN( SettingsMigrationService::getOnLoginCommands, Executor.PLAYER, CommandConfig::getOnLogin), ON_JOIN_CONSOLE( SettingsMigrationService::getOnLoginConsoleCommands, Executor.CONSOLE, CommandConfig::getOnLogin), ON_REGISTER( SettingsMigrationService::getOnRegisterCommands, Executor.PLAYER, CommandConfig::getOnRegister), ON_REGISTER_CONSOLE( SettingsMigrationService::getOnRegisterConsoleCommands, Executor.CONSOLE, CommandConfig::getOnRegister); private final Function> legacyCommandsGetter; private final Executor executor; private final Function> commandMapGetter; /** * Constructor. * * @param legacyCommandsGetter getter on MigrationService to get the deprecated command entries * @param executor the executor of the commands * @param commandMapGetter the getter for the commands map in the new settings structure to add the old * settings to after conversion */ MigratableCommandSection(Function> legacyCommandsGetter, Executor executor, Function> commandMapGetter) { this.legacyCommandsGetter = legacyCommandsGetter; this.executor = executor; this.commandMapGetter = commandMapGetter; } /** * Adds the commands from the sections' settings migration service to the appropriate place in the new * command config object. * * @param settingsMigrationService settings migration service to read old commands from * @param commandConfig command config object to add converted commands to * @return true if there were commands to migrate, false otherwise */ boolean convertCommands(SettingsMigrationService settingsMigrationService, CommandConfig commandConfig) { List commands = legacyCommandsGetter.apply(settingsMigrationService).stream() .map(cmd -> new Command(cmd, executor)).collect(Collectors.toList()); if (commands.isEmpty()) { return false; } Map commandMap = commandMapGetter.apply(commandConfig); commands.forEach(cmd -> commandMap.put(RandomStringUtils.generate(10), cmd)); ConsoleLogger.info("Moving " + commands.size() + " commands of type " + this + " from config.yml to commands.yml"); return true; } } }