ru.cwcode.tkach.config.base.manager.ConfigManager Maven / Gradle / Ivy
The newest version!
package ru.cwcode.tkach.config.base.manager;
import org.jetbrains.annotations.NotNull;
import ru.cwcode.commands.api.Sender;
import ru.cwcode.tkach.config.Utils;
import ru.cwcode.tkach.config.annotation.Reloadable;
import ru.cwcode.tkach.config.base.Config;
import ru.cwcode.tkach.config.base.ConfigPersistOptions;
import ru.cwcode.tkach.config.base.ConfigPlatform;
import java.nio.file.Path;
import java.sql.Timestamp;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static ru.cwcode.tkach.config.server.ServerPlatform.l10n;
public abstract class ConfigManager> {
protected final ConfigPlatform platform;
protected final ConfigLoader loader; //file->str
protected final ConfigPersister persister; //str->file
protected final ConfigMapper mapper; //str > obj, obj>str
protected final ConfigCreator creator; //null -> init
protected HashMap configs = new HashMap<>();
public ConfigManager(ConfigPlatform configPlatform,
ConfigLoader loader,
ConfigPersister persister,
ConfigMapper mapper,
ConfigCreator creator) {
//
this.platform = configPlatform;
this.loader = loader;
this.persister = persister;
this.mapper = mapper;
this.creator = creator;
loader.setConfigManager(this);
persister.setConfigManager(this);
mapper.setConfigManager(this);
creator.setConfigManager(this);
}
@NotNull
private static ConfigPersistOptions loadOptions(Consumer options) {
ConfigPersistOptions persistOptions = new ConfigPersistOptions();
options.accept(persistOptions);
return persistOptions;
}
public ConfigLoader loader() {
return loader;
}
public ConfigPersister persister() {
return persister;
}
public ConfigMapper mapper() {
return mapper;
}
public ConfigPlatform platform() {
return platform;
}
public V load(String name, Class configClass) {
return load(name, configClass, ConfigPersistOptions.DEFAULT);
}
public V load(String name, Class configClass, Consumer options) {
return load(name, configClass, loadOptions(options));
}
public V load(String name, Class configClass, ConfigPersistOptions options) {
AtomicBoolean shouldSave = new AtomicBoolean(false);
Optional data = loader.load(name, options);
Optional config = data.flatMap(x -> mapper.map(x, configClass, options));
if (config.isEmpty()) {
shouldSave.set(true);
if (data.isPresent()) backupConfigFile(name, options);
config = creator.create(name, configClass, options);
}
config.ifPresentOrElse(c -> {
configs.put(name, c);
c.setName(name);
c.setManager(this);
if (!options.isSilent()) {
platform.info(l10n.get("config.manager.loaded", name));
}
if (shouldSave.get()) {
save(c, options);
}
}, () -> {
if (!options.isSilent()) {
platform.info(l10n.get("config.manager.cantLoad", name));
}
platform.disable();
});
return config.orElse(null);
}
public void backupConfigFile(String name, Consumer options) {
backupConfigFile(name, loadOptions(options));
}
public void backupConfigFile(String name, ConfigPersistOptions options) {
Path original = getPath(name);
Path backup = getPath(name + " " + new Timestamp(System.currentTimeMillis()).toString().replace(":", "-"));
if (!options.isSilent()) {
platform.warning(l10n.get("config.manager.backup", name, backup));
}
Utils.copy(original, backup);
}
public void save(V config) {
save(config, __ -> {});
}
public void save(C config, Consumer options) {
save(config, loadOptions(options));
}
public void save(C config, ConfigPersistOptions options) {
if (config == null) return;
mapper.map(config, options)
.ifPresentOrElse(data -> {
persister.persist(config, data, getPath(config.name()), options);
}, () -> {
if (!options.isSilent()) {
platform.info(l10n.get("config.manager.cantMap", config.name()));
}
});
}
public void saveAll() {
saveAll(__ -> {});
}
public void saveAll(Consumer options) {
saveAll(loadOptions(options));
}
public void saveAll(ConfigPersistOptions options) {
if (options.isAsync()) {
options.async(false); //не лучшая идея, но проблем пока что быть не должно
platform.runAsync(() -> {
saveAll0(options);
});
} else {
saveAll0(options);
}
}
public boolean reload(Sender sender, C config) {
if (config instanceof Reloadable reloadable) {
if (reloadable.reload()) {
sender.sendMessage(l10n.get("config.manager.reloaded", config.name()));
return true;
} else {
sender.sendMessage(l10n.get("config.manager.cantReload", config.name()));
return false;
}
}
return false;
}
public List reloadAll(Sender sender) {
List reloaded = new ArrayList<>();
configs.forEach((name, config) -> {
if (reload(sender, config)) {
findConfig(config.name()).ifPresent(reloaded::add);
}
});
return reloaded;
}
protected void saveAll0(ConfigPersistOptions options) {
if (!options.isSilent()) {
platform.info(l10n.get("config.manager.saveAll"));
}
configs.values().forEach(config -> {
if (config.saveAllEnabled()) save(config, options);
});
}
public Path getPath(String name) {
return platform.dataFolder().resolve(name + ".yml");
}
public String toString(V config) {
return mapper.map(config, ConfigPersistOptions.DEFAULT).orElse(null);
}
public Set getConfigNames(Predicate predicate) {
return configs.values().stream()
.filter(predicate)
.map(Config::name)
.collect(Collectors.toSet());
}
public void scheduleAutosave(Duration frequency, Consumer options) {
platform.schedule(() -> saveAll(loadOptions(options)), frequency, loadOptions(options).isAsync());
}
public Optional findConfig(String name) {
return Optional.ofNullable(configs.get(name));
}
}