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>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
@ -6,7 +6,7 @@ import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
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, String> inlineComments = new HashMap<>();
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<properties>
|
||||
|
@ -16,10 +16,7 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
|
||||
@HeaderComment({
|
||||
"此处内容将显示在配置文件的最上方",
|
||||
""/*添加一个空行与其他配置的注释分割*/
|
||||
})
|
||||
@HeaderComment({"此处内容将显示在配置文件的最上方"})
|
||||
public class DemoConfiguration extends ConfigurationRoot {
|
||||
|
||||
@ConfigPath(root = true)
|
||||
@ -36,7 +33,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
public static final Class<?> OTHER = OtherConfiguration.class;
|
||||
|
||||
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@InlineComment("Section数据也支持InlineComment注释")
|
||||
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
|
||||
.builder(TestModel.class)
|
||||
@ -44,7 +41,7 @@ public class DemoConfiguration extends ConfigurationRoot {
|
||||
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
|
||||
.serializeValue(TestModel::serialize).build();
|
||||
|
||||
@HeaderComment({"", "[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||
@HeaderComment({"[ID - UUID]对照表", "", "用于测试Map类型的解析与序列化保存"})
|
||||
public static final ConfiguredMap<Integer, UUID> USERS = ConfiguredMap
|
||||
.builder(Integer.class, UUID.class).fromString()
|
||||
.parseKey(Integer::parseInt)
|
||||
|
@ -18,7 +18,7 @@ public class TestConfiguration extends ConfigurationRoot {
|
||||
public final ConfigValue<Double> CLASS_VALUE = ConfiguredValue.of(Double.class, 1.0D);
|
||||
|
||||
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||
@HeaderComment({"", "Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@HeaderComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||
@InlineComment("Section数据也支持InlineComment注释")
|
||||
public final ConfigValue<TestModel> TEST_MODEL = ConfiguredSection
|
||||
.builder(TestModel.class)
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>easyconfiguration-parent</artifactId>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<version>3.5.0</version>
|
||||
<version>3.5.1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@ -28,13 +28,19 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cc.carm.lib</groupId>
|
||||
<artifactId>yamlcommentwriter</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>${project.parent.groupId}</groupId>
|
||||
<artifactId>easyconfiguration-demo</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bspfsystems</groupId>
|
||||
<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.source.ConfigurationComments;
|
||||
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.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;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> implements CommentedYAML {
|
||||
|
||||
protected static final char SEPARATOR = '.';
|
||||
|
||||
protected final @NotNull YAMLComments comments = new YAMLComments();
|
||||
protected final @NotNull ConfigurationComments comments = new ConfigurationComments();
|
||||
protected YamlConfiguration configuration;
|
||||
protected ConfigInitializer<YAMLConfigProvider> initializer;
|
||||
|
||||
@ -42,27 +41,18 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ConfigurationComments getComments() {
|
||||
public @NotNull ConfigurationComments getComments() {
|
||||
return this.comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
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));
|
||||
try {
|
||||
CommentedYAMLWriter.writeWithComments(this, this.file);
|
||||
} catch (Exception ex) {
|
||||
configuration.save(file);
|
||||
throw ex;
|
||||
}
|
||||
// tchristofferson/ConfigUpdater end
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -70,4 +60,31 @@ public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
|
||||
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
|
||||
public void onTest() {
|
||||
|
||||
ConfigurationTest.testDemo(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.annotation.ConfigPath;
|
||||
import cc.carm.lib.configuration.core.annotation.HeaderComment;
|
||||
import cc.carm.lib.configuration.core.value.ConfigValue;
|
||||
import cc.carm.lib.configuration.demo.tests.model.AbstractModel;
|
||||
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
|
||||
import config.model.AnyModel;
|
||||
import config.model.SomeModel;
|
||||
|
||||
@HeaderComment("以下内容用于测试序列化")
|
||||
@ConfigPath("model-test")
|
||||
public class ModelConfiguration extends ConfigurationRoot {
|
||||
|
||||
|
@ -1,2 +1 @@
|
||||
# Test Header
|
||||
version: 1.0
|
Loading…
Reference in New Issue
Block a user