mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2024-09-19 20:25:51 +00:00
chore(yaml): 独立 YAMLCommentWriter 项目
This commit is contained in:
parent
727c26a2fb
commit
ddd33154be
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -6,7 +6,7 @@ import org.jetbrains.annotations.Unmodifiable;
|
|||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public abstract class ConfigurationComments {
|
public class ConfigurationComments {
|
||||||
|
|
||||||
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
protected final @NotNull Map<String, List<String>> headerComments = new HashMap<>();
|
||||||
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
protected final @NotNull Map<String, String> inlineComments = new HashMap<>();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -16,10 +16,7 @@ import java.util.Objects;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
|
||||||
@HeaderComment({
|
@HeaderComment({"此处内容将显示在配置文件的最上方"})
|
||||||
"此处内容将显示在配置文件的最上方",
|
|
||||||
""/*添加一个空行与其他配置的注释分割*/
|
|
||||||
})
|
|
||||||
public class DemoConfiguration extends ConfigurationRoot {
|
public class DemoConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
@ConfigPath(root = true)
|
@ConfigPath(root = true)
|
||||||
@ -36,7 +33,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
|||||||
public static final Class<?> OTHER = OtherConfiguration.class;
|
public static final Class<?> OTHER = OtherConfiguration.class;
|
||||||
|
|
||||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("Section数据也支持InlineComment注释")
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
||||||
.builder(TestModel.class)
|
.builder(TestModel.class)
|
||||||
@ -44,7 +41,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
|||||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||||
.serializeValue(TestModel::serialize).build();
|
.serializeValue(TestModel::serialize).build();
|
||||||
|
|
||||||
@HeaderComment({"", "[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
@HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||||
public static final ConfiguredMap<Integer, UUID> USERS = ConfiguredMap
|
public static final ConfiguredMap<Integer, UUID> USERS = ConfiguredMap
|
||||||
.builder(Integer.class, UUID.class).fromString()
|
.builder(Integer.class, UUID.class).fromString()
|
||||||
.parseKey(Integer::parseInt)
|
.parseKey(Integer::parseInt)
|
||||||
|
@ -18,7 +18,7 @@ public class TestConfiguration extends ConfigurationRoot {
|
|||||||
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||||
|
|
||||||
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("Section数据也支持InlineComment注释")
|
@InlineComment("Section数据也支持InlineComment注释")
|
||||||
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
||||||
.builder(TestModel.class)
|
.builder(TestModel.class)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@ -28,13 +28,19 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<artifactId>yamlcommentwriter</artifactId>
|
||||||
|
<version>1.0.1</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.parent.groupId}</groupId>
|
<groupId>${project.parent.groupId}</groupId>
|
||||||
<artifactId>easyconfiguration-demo</artifactId>
|
<artifactId>easyconfiguration-demo</artifactId>
|
||||||
<version>${project.parent.version}</version>
|
<version>${project.parent.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bspfsystems</groupId>
|
<groupId>org.bspfsystems</groupId>
|
||||||
<artifactId>yamlconfiguration</artifactId>
|
<artifactId>yamlconfiguration</artifactId>
|
||||||
|
@ -1,111 +0,0 @@
|
|||||||
package cc.carm.lib.configuration.yaml;
|
|
||||||
|
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
|
||||||
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.List;
|
|
||||||
import java.util.StringJoiner;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.IntStream;
|
|
||||||
|
|
||||||
import static cc.carm.lib.configuration.yaml.YAMLConfigProvider.SEPARATOR;
|
|
||||||
|
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
public class YAMLComments extends ConfigurationComments {
|
|
||||||
|
|
||||||
public @Nullable String buildHeaderComments(@Nullable String path, @NotNull String indents) {
|
|
||||||
List<String> comments = getHeaderComment(path);
|
|
||||||
if (comments == null || comments.size() == 0) return null;
|
|
||||||
|
|
||||||
StringJoiner joiner = new StringJoiner("\n");
|
|
||||||
for (String comment : comments) {
|
|
||||||
if (comment.length() == 0) joiner.add(" ");
|
|
||||||
else joiner.add(indents + "# " + comment);
|
|
||||||
}
|
|
||||||
return joiner + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 从一个文件读取配置并写入注释到某个写入器中。
|
|
||||||
* 该方法的部分源代码借鉴自 tchristofferson/ConfigUpdater 项目。
|
|
||||||
*
|
|
||||||
* @param source 源配置文件
|
|
||||||
* @param writer 配置写入器
|
|
||||||
* @throws IOException 当写入发生错误时抛出
|
|
||||||
*/
|
|
||||||
public void writeComments(@NotNull YamlConfiguration source, @NotNull BufferedWriter writer) throws IOException {
|
|
||||||
FileConfiguration temp = new YamlConfiguration(); // 该对象用于临时记录配置内容
|
|
||||||
|
|
||||||
String configHeader = buildHeaderComments(null, "");
|
|
||||||
if (configHeader != null) writer.write(configHeader);
|
|
||||||
|
|
||||||
for (String fullKey : source.getKeys(true)) {
|
|
||||||
Object currentValue = source.get(fullKey);
|
|
||||||
|
|
||||||
String indents = getIndents(fullKey);
|
|
||||||
String headerComments = buildHeaderComments(fullKey, indents);
|
|
||||||
String inlineComment = getInlineComment(fullKey);
|
|
||||||
|
|
||||||
if (headerComments != null) writer.write(headerComments);
|
|
||||||
|
|
||||||
String[] splitFullKey = fullKey.split("[" + SEPARATOR + "]");
|
|
||||||
String trailingKey = splitFullKey[splitFullKey.length - 1];
|
|
||||||
|
|
||||||
if (currentValue instanceof ConfigurationSection) {
|
|
||||||
ConfigurationSection section = (ConfigurationSection) currentValue;
|
|
||||||
writer.write(indents + trailingKey + ":");
|
|
||||||
if (inlineComment != null && inlineComment.length() > 0) {
|
|
||||||
writer.write(" # " + inlineComment);
|
|
||||||
}
|
|
||||||
if (!section.getKeys(false).isEmpty()) {
|
|
||||||
writer.write("\n");
|
|
||||||
} else {
|
|
||||||
writer.write(" {}\n");
|
|
||||||
if (indents.length() == 0) writer.write("\n");
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp.set(trailingKey, currentValue);
|
|
||||||
String yaml = temp.saveToString();
|
|
||||||
temp.set(trailingKey, null);
|
|
||||||
|
|
||||||
yaml = yaml.substring(0, yaml.length() - 1);
|
|
||||||
|
|
||||||
if (inlineComment != null && inlineComment.length() > 0) {
|
|
||||||
if (yaml.contains("\n")) {
|
|
||||||
// section为多行内容,需要 InlineComment 加在首行末尾
|
|
||||||
String[] splitLine = yaml.split("\n", 2);
|
|
||||||
yaml = splitLine[0] + " # " + inlineComment + "\n" + splitLine[1];
|
|
||||||
} else {
|
|
||||||
// 其他情况下就直接加载后面就好。
|
|
||||||
yaml += " # " + inlineComment;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.write(indents + yaml.replace("\n", "\n" + indents) + "\n");
|
|
||||||
if (indents.length() == 0) writer.write("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -3,22 +3,21 @@ package cc.carm.lib.configuration.yaml;
|
|||||||
import cc.carm.lib.configuration.core.ConfigInitializer;
|
import cc.carm.lib.configuration.core.ConfigInitializer;
|
||||||
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
import cc.carm.lib.configuration.core.source.ConfigurationComments;
|
||||||
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
|
||||||
|
import cc.carm.lib.yamlcommentupdater.CommentedYAML;
|
||||||
|
import cc.carm.lib.yamlcommentupdater.CommentedYAMLWriter;
|
||||||
|
import org.bspfsystems.yamlconfiguration.configuration.ConfigurationSection;
|
||||||
|
import org.bspfsystems.yamlconfiguration.file.FileConfiguration;
|
||||||
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
import org.bspfsystems.yamlconfiguration.file.YamlConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.StringWriter;
|
import java.util.List;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.util.Set;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> implements CommentedYAML {
|
||||||
|
|
||||||
protected static final char SEPARATOR = '.';
|
protected final @NotNull ConfigurationComments comments = new ConfigurationComments();
|
||||||
|
|
||||||
protected final @NotNull YAMLComments comments = new YAMLComments();
|
|
||||||
protected YamlConfiguration configuration;
|
protected YamlConfiguration configuration;
|
||||||
protected ConfigInitializer<YAMLConfigProvider> initializer;
|
protected ConfigInitializer<YAMLConfigProvider> initializer;
|
||||||
|
|
||||||
@ -42,27 +41,18 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable ConfigurationComments getComments() {
|
public @NotNull ConfigurationComments getComments() {
|
||||||
return this.comments;
|
return this.comments;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("SpellCheckingInspection")
|
|
||||||
public void save() throws Exception {
|
public void save() throws Exception {
|
||||||
configuration.save(getFile());
|
try {
|
||||||
|
CommentedYAMLWriter.writeWithComments(this, this.file);
|
||||||
// tchristofferson/ConfigUpdater start
|
} catch (Exception ex) {
|
||||||
StringWriter writer = new StringWriter();
|
configuration.save(file);
|
||||||
this.comments.writeComments(configuration, new BufferedWriter(writer));
|
throw ex;
|
||||||
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
|
@Override
|
||||||
@ -70,4 +60,31 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
|||||||
return this.initializer;
|
return this.initializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String serializeValue(@NotNull String key, @NotNull Object value) {
|
||||||
|
FileConfiguration temp = new YamlConfiguration();
|
||||||
|
temp.set(key, value);
|
||||||
|
return temp.saveToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getKeys(@Nullable String sectionKey, boolean deep) {
|
||||||
|
if (sectionKey == null) return configuration.getKeys(deep);
|
||||||
|
|
||||||
|
ConfigurationSection section = configuration.getConfigurationSection(sectionKey);
|
||||||
|
if (section == null) return null;
|
||||||
|
|
||||||
|
return section.getKeys(deep);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable Object getValue(@NotNull String key) {
|
||||||
|
return configuration.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> getHeaderComments(@Nullable String key) {
|
||||||
|
return comments.getHeaderComment(key);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ public class DemoConfigTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onTest() {
|
public void onTest() {
|
||||||
|
|
||||||
ConfigurationTest.testDemo(this.provider);
|
ConfigurationTest.testDemo(this.provider);
|
||||||
ConfigurationTest.testInner(this.provider);
|
ConfigurationTest.testInner(this.provider);
|
||||||
|
|
||||||
|
@ -2,12 +2,14 @@ package config.source;
|
|||||||
|
|
||||||
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
import cc.carm.lib.configuration.core.ConfigurationRoot;
|
||||||
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
import cc.carm.lib.configuration.core.annotation.ConfigPath;
|
||||||
|
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||||
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||||
import config.model.AnyModel;
|
import config.model.AnyModel;
|
||||||
import config.model.SomeModel;
|
import config.model.SomeModel;
|
||||||
|
|
||||||
|
@HeaderComment("以下内容用于测试序列化")
|
||||||
@ConfigPath("model-test")
|
@ConfigPath("model-test")
|
||||||
public class ModelConfiguration extends ConfigurationRoot {
|
public class ModelConfiguration extends ConfigurationRoot {
|
||||||
|
|
||||||
|
@ -1,2 +1 @@
|
|||||||
# Test Header
|
|
||||||
version: 1.0
|
version: 1.0
|
2
pom.xml
2
pom.xml
@ -15,7 +15,7 @@
|
|||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>3.5.0</version>
|
<version>3.5.1</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>demo</module>
|
<module>demo</module>
|
||||||
|
Loading…
Reference in New Issue
Block a user