mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-04 18:48:20 +08:00
[2.3.0] 版本更新
- [U] 基于 tchristofferson/ConfigUpdater 项目重写YAML相关配置文件的注释部分。 - [A] 为 @ConfigComment 注解添加 ”statWrap“ 与 "endWrap" 两个选项,用于实现不同样式的注释。
This commit is contained in:
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>2.2.0</version>
|
||||
<version>2.3.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cc.carm.lib.configuration.json;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.source.ConfigCommentInfo;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||
import com.google.gson.Gson;
|
||||
@@ -68,15 +69,16 @@ public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComments(@NotNull String path, @NotNull String... comments) {
|
||||
// JSON doesn't support comments.
|
||||
public void setComment(@Nullable String path, @Nullable ConfigCommentInfo comment) {
|
||||
// JSON doesn't support comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String[] getComments(@NotNull String path) {
|
||||
return new String[0]; // JSON doesn't support comments.
|
||||
public @Nullable ConfigCommentInfo getComment(@Nullable String path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull ConfigInitializer<? extends ConfigurationProvider<JSONConfigWrapper>> getInitializer() {
|
||||
return this.initializer;
|
||||
|
||||
@@ -4,7 +4,10 @@ import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
|
||||
@@ -33,12 +36,16 @@ public class JSONConfigWrapper implements ConfigurationWrapper {
|
||||
|
||||
@Override
|
||||
public @NotNull Set<String> getKeys(boolean deep) {
|
||||
return new LinkedHashSet<>(this.data.keySet());
|
||||
return getValues(deep).keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Map<String, Object> getValues(boolean deep) {
|
||||
return new LinkedHashMap<>(this.data);
|
||||
if (deep) {
|
||||
Map<String, Object> values = new LinkedHashMap<>();
|
||||
mapChildrenValues(values, this, null, true);
|
||||
return values;
|
||||
} else return new LinkedHashMap<>(this.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,4 +118,16 @@ public class JSONConfigWrapper implements ConfigurationWrapper {
|
||||
return (index == -1) ? path : path.substring(index + 1);
|
||||
}
|
||||
|
||||
|
||||
protected void mapChildrenValues(@NotNull Map<String, Object> output, @NotNull JSONConfigWrapper section,
|
||||
@Nullable String parent, boolean deep) {
|
||||
for (Map.Entry<String, Object> entry : section.data.entrySet()) {
|
||||
String path = (parent == null ? "" : parent + ".") + entry.getKey();
|
||||
output.remove(path);
|
||||
output.put(path, entry.getValue());
|
||||
if (deep && entry.getValue() instanceof JSONConfigWrapper) {
|
||||
this.mapChildrenValues(output, (JSONConfigWrapper) entry.getValue(), path, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,11 @@ public class JSONConfigTest {
|
||||
provider.initialize(DemoConfiguration.class);
|
||||
|
||||
testDemo();
|
||||
System.out.println("----------------------------------------------------");
|
||||
provider.getConfiguration().getValues(true).forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
System.out.println("----------------------------------------------------");
|
||||
provider.getConfiguration().getValues(false).forEach((k, v) -> System.out.println(k + ": " + v));
|
||||
System.out.println("----------------------------------------------------");
|
||||
|
||||
try {
|
||||
provider.save();
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>2.2.0</version>
|
||||
<version>2.3.0</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -27,9 +27,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>yamlconfiguration-commented</artifactId>
|
||||
<version>2.0.2</version>
|
||||
<groupId>org.bspfsystems</groupId>
|
||||
<artifactId>yamlconfiguration</artifactId>
|
||||
<version>1.0.11</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,35 +1,114 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import org.bspfsystems.yamlconfiguration.commented.CommentsProvider;
|
||||
import cc.carm.lib.configuration.core.source.ConfigCommentInfo;
|
||||
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
||||
import org.bspfsystems.yamlconfiguration.file.FileConfiguration;
|
||||
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class YAMLComments implements CommentsProvider {
|
||||
import static cc.carm.lib.configuration.yaml.YAMLConfigProvider.SEPARATOR;
|
||||
|
||||
Map<String, String[]> comments = new HashMap<>();
|
||||
public class YAMLComments {
|
||||
|
||||
protected Map<String, String[]> getComments() {
|
||||
Map<String, ConfigCommentInfo> comments = new HashMap<>();
|
||||
|
||||
protected Map<String, ConfigCommentInfo> getComments() {
|
||||
return comments;
|
||||
}
|
||||
|
||||
public void set(@NotNull String path, @NotNull String... comments) {
|
||||
if (comments.length == 0) {
|
||||
public void set(@Nullable String path, @Nullable ConfigCommentInfo comments) {
|
||||
if (comments == null) {
|
||||
getComments().remove(path);
|
||||
} else {
|
||||
getComments().put(path, comments);
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable String[] get(@NotNull String path) {
|
||||
return getComments().get(path);
|
||||
public @NotNull ConfigCommentInfo get(@Nullable String path) {
|
||||
return getComments().getOrDefault(path, ConfigCommentInfo.defaults());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] apply(String s) {
|
||||
return get(s);
|
||||
public @Nullable String buildComments(@NotNull String indents, @Nullable String path) {
|
||||
ConfigCommentInfo comments = get(path);
|
||||
if (!String.join("", comments.getComments()).isEmpty()) {
|
||||
String prefix = comments.startWrap() ? "\n" : "";
|
||||
String suffix = comments.endWrap() ? "\n" : "";
|
||||
StringJoiner joiner = new StringJoiner("\n", prefix, suffix);
|
||||
for (String comment : comments.getComments()) {
|
||||
if (comment.length() == 0) joiner.add(" ");
|
||||
else joiner.add(indents + "# " + comment);
|
||||
}
|
||||
return joiner + "\n";
|
||||
} else {
|
||||
return comments.startWrap() || comments.endWrap() ? "\n" : null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从一个文件读取配置并写入注释到某个写入器中。
|
||||
* 该方法的源代码来自 tchristofferson/ConfigUpdater 项目。
|
||||
*
|
||||
* @param source 源配置文件
|
||||
* @param writer 配置写入器
|
||||
* @throws IOException 当写入发生错误时抛出
|
||||
*/
|
||||
public void writeComments(@NotNull YamlConfiguration source, @NotNull BufferedWriter writer) throws IOException {
|
||||
FileConfiguration parserConfig = new YamlConfiguration();
|
||||
|
||||
for (String fullKey : source.getKeys(true)) {
|
||||
String indents = getIndents(fullKey);
|
||||
String comment = buildComments(indents, fullKey);
|
||||
if (comment != null) writer.write(comment);
|
||||
|
||||
Object currentValue = source.get(fullKey);
|
||||
|
||||
String[] splitFullKey = fullKey.split("[" + SEPARATOR + "]");
|
||||
String trailingKey = splitFullKey[splitFullKey.length - 1];
|
||||
|
||||
if (currentValue instanceof ConfigurationSection) {
|
||||
writer.write(indents + trailingKey + ":");
|
||||
|
||||
if (!((ConfigurationSection) currentValue).getKeys(false).isEmpty())
|
||||
writer.write("\n");
|
||||
else
|
||||
writer.write(" {}\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
parserConfig.set(trailingKey, currentValue);
|
||||
String yaml = parserConfig.saveToString();
|
||||
yaml = yaml.substring(0, yaml.length() - 1).replace("\n", "\n" + indents);
|
||||
String toWrite = indents + yaml + "\n";
|
||||
parserConfig.set(trailingKey, null);
|
||||
writer.write(toWrite);
|
||||
}
|
||||
|
||||
String endComment = buildComments("", null);
|
||||
if (endComment != null) writer.write(endComment);
|
||||
|
||||
writer.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到一个键的缩进。
|
||||
* 该方法的源代码来自 tchristofferson/ConfigUpdater 项目。
|
||||
*
|
||||
* @param key 键
|
||||
* @return 该键的缩进文本
|
||||
*/
|
||||
protected static String getIndents(String key) {
|
||||
String[] splitKey = key.split("[" + YAMLConfigProvider.SEPARATOR + "]");
|
||||
return IntStream.range(1, splitKey.length).mapToObj(i -> " ").collect(Collectors.joining());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,17 +1,25 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||
import cc.carm.lib.configuration.core.source.ConfigCommentInfo;
|
||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||
import org.bspfsystems.yamlconfiguration.commented.CommentedYamlConfiguration;
|
||||
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
|
||||
protected static final char SEPARATOR = '.';
|
||||
|
||||
protected final @NotNull YAMLComments comments = new YAMLComments();
|
||||
protected CommentedYamlConfiguration configuration;
|
||||
protected YamlConfiguration configuration;
|
||||
protected ConfigInitializer<YAMLConfigProvider> initializer;
|
||||
|
||||
public YAMLConfigProvider(@NotNull File file) {
|
||||
@@ -19,7 +27,7 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
}
|
||||
|
||||
public void initializeConfig() {
|
||||
this.configuration = CommentedYamlConfiguration.loadConfiguration(comments, file);
|
||||
this.configuration = YamlConfiguration.loadConfiguration(file);
|
||||
this.initializer = new ConfigInitializer<>(this);
|
||||
}
|
||||
|
||||
@@ -36,15 +44,29 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
@Override
|
||||
public void save() throws Exception {
|
||||
configuration.save(getFile());
|
||||
|
||||
|
||||
// tchristofferson/ConfigUpdater start
|
||||
StringWriter writer = new StringWriter();
|
||||
this.comments.writeComments(configuration, new BufferedWriter(writer));
|
||||
String value = writer.toString(); // config contents
|
||||
|
||||
Path toUpdatePath = getFile().toPath();
|
||||
if (!value.equals(new String(Files.readAllBytes(toUpdatePath), StandardCharsets.UTF_8))) {
|
||||
// if updated contents are not the same as current file contents, update
|
||||
Files.write(toUpdatePath, value.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
// tchristofferson/ConfigUpdater end
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setComments(@NotNull String path, @NotNull String... comments) {
|
||||
public void setComment(@Nullable String path, @Nullable ConfigCommentInfo comments) {
|
||||
this.comments.set(path, comments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String[] getComments(@NotNull String path) {
|
||||
public @Nullable ConfigCommentInfo getComment(@Nullable String path) {
|
||||
return this.comments.get(path);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cc.carm.lib.configuration.yaml;
|
||||
|
||||
import cc.carm.lib.configuration.core.source.ConfigCommentInfo;
|
||||
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
|
||||
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
|
||||
import cc.carm.lib.configuration.yaml.builder.YAMLConfigBuilder;
|
||||
@@ -13,7 +14,8 @@ public abstract class YAMLValue<T> extends CachedConfigValue<T> {
|
||||
}
|
||||
|
||||
public YAMLValue(@Nullable YAMLConfigProvider provider,
|
||||
@Nullable String configPath, @NotNull String[] comments, @Nullable T defaultValue) {
|
||||
@Nullable String configPath, @Nullable ConfigCommentInfo comments,
|
||||
@Nullable T defaultValue) {
|
||||
super(provider, configPath, comments, defaultValue);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ public class SerializableBuilder<T extends ConfigurationSerializable>
|
||||
|
||||
@Override
|
||||
public @NotNull ConfiguredSerializable<T> build() {
|
||||
return new ConfiguredSerializable<>(this.provider, this.path, this.comments, this.valueClass, this.defaultValue);
|
||||
return new ConfiguredSerializable<>(this.provider, this.path, buildComments(), this.valueClass, this.defaultValue);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+4
-3
@@ -1,7 +1,8 @@
|
||||
package cc.carm.lib.configuration.yaml.value;
|
||||
|
||||
import cc.carm.lib.configuration.yaml.YAMLValue;
|
||||
import cc.carm.lib.configuration.core.source.ConfigCommentInfo;
|
||||
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
|
||||
import cc.carm.lib.configuration.yaml.YAMLValue;
|
||||
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -15,14 +16,14 @@ public class ConfiguredSerializable<T extends ConfigurationSerializable> extends
|
||||
}
|
||||
|
||||
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass,
|
||||
@Nullable V defaultValue) {
|
||||
@Nullable V defaultValue) {
|
||||
return builder().ofSerializable(valueClass).defaults(defaultValue).build();
|
||||
}
|
||||
|
||||
protected final @NotNull Class<T> valueClass;
|
||||
|
||||
public ConfiguredSerializable(@Nullable YAMLConfigProvider provider,
|
||||
@Nullable String configPath, @NotNull String[] comments,
|
||||
@Nullable String configPath, @Nullable ConfigCommentInfo comments,
|
||||
@NotNull Class<T> valueClass, @Nullable T defaultValue) {
|
||||
super(provider, configPath, comments, defaultValue);
|
||||
this.valueClass = valueClass;
|
||||
|
||||
@@ -10,22 +10,26 @@ import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
|
||||
public class DatabaseConfiguration extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath("driver")
|
||||
@ConfigComment({
|
||||
@ConfigComment(value = {
|
||||
"数据库驱动配置,请根据数据库类型设置。",
|
||||
"- MySQL: com.mysql.cj.jdbc.Driver",
|
||||
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
|
||||
})
|
||||
}, startWrap = false)
|
||||
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
|
||||
String.class, "com.mysql.cj.jdbc.Driver"
|
||||
);
|
||||
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
|
||||
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
|
||||
|
||||
@ConfigComment(startWrap = false)
|
||||
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
|
||||
|
||||
protected static String buildJDBC() {
|
||||
|
||||
@@ -16,14 +16,16 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@ConfigComment({"给根类添加的注释将显示在文件的末尾。"})
|
||||
public class DemoConfiguration extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath(root = true)
|
||||
@ConfigComment({
|
||||
@ConfigComment(value = {
|
||||
"有时候,需要在配置文件最上面显示点东西,",
|
||||
"此时就推荐添加一个可以用到但并不重要的参数到最上面",
|
||||
"并给他添加对应的注释。"
|
||||
})
|
||||
}, startWrap = false, endWrap = true)
|
||||
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user