1
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:
Carm Jos 2023-03-20 20:11:23 +08:00
parent 727c26a2fb
commit ddd33154be
14 changed files with 62 additions and 151 deletions

View File

@ -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>

View File

@ -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<>();

View File

@ -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>

View File

@ -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)

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -21,6 +21,7 @@ public class DemoConfigTest {
@Test
public void onTest() {
ConfigurationTest.testDemo(this.provider);
ConfigurationTest.testInner(this.provider);

View File

@ -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 {

View File

@ -1,2 +1 @@
# Test Header
version: 1.0

View File

@ -15,7 +15,7 @@
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-parent</artifactId>
<packaging>pom</packaging>
<version>3.5.0</version>
<version>3.5.1</version>
<modules>
<module>core</module>
<module>demo</module>