mirror of
https://github.com/CarmJos/EasyConfiguration.git
synced 2026-06-05 02:58:20 +08:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ae756929a | |||
| a9e80aecce | |||
| 477f0d11bc | |||
| 53ff38a76f | |||
| c32bea3864 | |||
| 15823bb076 | |||
| f303f56199 | |||
| 22f2674e7c | |||
| 9eb9c9e13d | |||
| 616314c7f0 | |||
| 05f504a347 | |||
| bf6ea97b99 | |||
| 9847399e56 | |||
| 18515d4a78 | |||
| 9f1fc5bf90 | |||
| e7847b2166 | |||
| 69cec281be | |||
| 28dc9b9e55 | |||
| c60ba074d9 | |||
| e88bf301cc |
@@ -40,7 +40,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
rm -rf docs
|
rm -rf docs
|
||||||
mkdir -vp docs
|
mkdir -vp docs
|
||||||
cp -vrf core/target/apidocs/* docs/
|
cp -vrf core/target/reports/apidocs/* docs/
|
||||||
cp -vrf .doc/JAVADOC-README.md docs/README.md
|
cp -vrf .doc/JAVADOC-README.md docs/README.md
|
||||||
|
|
||||||
- name: "Generate the Javadoc sitemap"
|
- name: "Generate the Javadoc sitemap"
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
/.idea/
|
.idea/
|
||||||
**/target/
|
**/target/
|
||||||
**.iml
|
**.iml
|
||||||
+1
-1
@@ -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>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
+12
-10
@@ -3,8 +3,8 @@ package cc.carm.lib.configuration.builder.impl;
|
|||||||
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
import cc.carm.lib.configuration.adapter.ValueType;
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
|
||||||
import cc.carm.lib.configuration.function.DataConsumer;
|
|
||||||
import cc.carm.lib.configuration.function.DataFunction;
|
import cc.carm.lib.configuration.function.DataFunction;
|
||||||
|
import cc.carm.lib.configuration.function.ValueConsumer;
|
||||||
import cc.carm.lib.configuration.function.ValueHandler;
|
import cc.carm.lib.configuration.function.ValueHandler;
|
||||||
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
@@ -34,28 +34,30 @@ public abstract class AbstractSectionBuilder<
|
|||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(DataFunction<ConfigureSection, PARAM> valueParser) {
|
public @NotNull SELF parse(@NotNull DataFunction<ConfigureSection, PARAM> valueParser) {
|
||||||
return parse((p, section) -> valueParser.handle(section));
|
return parse((p, section) -> valueParser.handle(section));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(ValueHandler<ConfigureSection, PARAM> valueParser) {
|
public @NotNull SELF parse(@NotNull ValueHandler<ConfigureSection, PARAM> valueParser) {
|
||||||
this.parser = valueParser;
|
this.parser = valueParser;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(DataFunction<PARAM, ? extends Map<String, Object>> serializer) {
|
public @NotNull SELF serialize(@NotNull ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
||||||
return serialize((p, value) -> serializer.handle(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public @NotNull SELF serialize(ValueHandler<PARAM, ? extends Map<String, Object>> serializer) {
|
|
||||||
this.serializer = serializer;
|
this.serializer = serializer;
|
||||||
return self();
|
return self();
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF serialize(DataConsumer<Map<String, Object>> serializer) {
|
public @NotNull SELF serialize(@NotNull DataFunction<PARAM, ? extends Map<String, Object>> serializer) {
|
||||||
return serialize((p, value) -> {
|
return serialize((p, value) -> {
|
||||||
|
return serializer.handle(value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF serialize(@NotNull ValueConsumer<Map<String, Object>, PARAM> serializer) {
|
||||||
|
return serialize((h, value) -> {
|
||||||
Map<String, Object> map = new LinkedHashMap<>();
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
serializer.accept(map);
|
serializer.accept(h, map, value);
|
||||||
return map;
|
return map;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ public abstract class AbstractSourceBuilder<
|
|||||||
this.valueSerializer = serializer;
|
this.valueSerializer = serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull SELF parse(DataFunction<SOURCE, PARAM> parser) {
|
public @NotNull SELF parse(@NotNull DataFunction<SOURCE, PARAM> parser) {
|
||||||
return parse((p, source) -> parser.handle(source));
|
return parse((p, source) -> parser.handle(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package cc.carm.lib.configuration.function;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ValueConsumer<U, T> {
|
||||||
|
|
||||||
|
void accept(@NotNull ConfigurationHolder<?> holder, @NotNull U unit, @NotNull T data) throws Exception;
|
||||||
|
|
||||||
|
default ValueConsumer<U, T> andThen(ValueConsumer<? super U, ? super T> after) {
|
||||||
|
return (holder, unit, data) -> {
|
||||||
|
accept(holder, unit, data);
|
||||||
|
after.accept(holder, unit, data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
+2
@@ -3,6 +3,7 @@ package cc.carm.lib.configuration.source.loader;
|
|||||||
import cc.carm.lib.configuration.Configuration;
|
import cc.carm.lib.configuration.Configuration;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
|
||||||
|
import cc.carm.lib.configuration.source.meta.StandardMeta;
|
||||||
import cc.carm.lib.configuration.source.option.StandardOptions;
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
import cc.carm.lib.configuration.value.ConfigValue;
|
import cc.carm.lib.configuration.value.ConfigValue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -168,6 +169,7 @@ public class ConfigurationInitializer {
|
|||||||
String path = getFieldPath(holder, parent, field);
|
String path = getFieldPath(holder, parent, field);
|
||||||
if (path == null) return;
|
if (path == null) return;
|
||||||
value.initialize(holder, path);
|
value.initialize(holder, path);
|
||||||
|
holder.metadata(path).set(StandardMeta.UNIT, true); // Mark the minimal config value unit.
|
||||||
try {
|
try {
|
||||||
this.fieldInitializer.whenInitialize(holder, path, field);
|
this.fieldInitializer.whenInitialize(holder, path, field);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package cc.carm.lib.configuration.source.meta;
|
||||||
|
|
||||||
|
public interface StandardMeta {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To mark the {@link cc.carm.lib.configuration.value.ConfigValue} as a minimal unit path.
|
||||||
|
*/
|
||||||
|
ConfigurationMetadata<Boolean> UNIT = ConfigurationMetadata.of(false);
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -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>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ public interface DemoConfiguration extends Configuration {
|
|||||||
@ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("registered_users") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@HeaderComments({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
@HeaderComments({"Section类型数据测试"}) // 通过注解给配置添加注释。
|
||||||
@InlineComment("默认地注释会加到Section的首行末尾") // 通过注解给配置添加注释。
|
@InlineComment("默认地注释会加到Section的首行末尾") // 通过注解给配置添加注释。
|
||||||
@InlineComment(value = "用户名(匹配注释)", regex = "name") // 通过注解给配置添加注释。
|
|
||||||
@InlineComment(value = "信息", regex = "info.*") // 通过注解给配置添加注释。
|
|
||||||
ConfiguredList<UserRecord> ALLOWLISTS = ConfiguredList.builderOf(UserRecord.class).fromSection()
|
ConfiguredList<UserRecord> ALLOWLISTS = ConfiguredList.builderOf(UserRecord.class).fromSection()
|
||||||
.parse(UserRecord::deserialize).serialize(UserRecord::serialize)
|
.parse(UserRecord::deserialize).serialize(UserRecord::serialize)
|
||||||
.defaults(UserRecord.CARM).build();
|
.defaults(UserRecord.CARM).build();
|
||||||
@@ -81,6 +79,7 @@ public interface DemoConfiguration extends Configuration {
|
|||||||
.build();
|
.build();
|
||||||
|
|
||||||
@HeaderComments({"内部类的内部类测试", "通过这种方式,您可以轻易实现多层次的配置文件结构"})
|
@HeaderComments({"内部类的内部类测试", "通过这种方式,您可以轻易实现多层次的配置文件结构"})
|
||||||
|
@FooterComments({"-------------"})
|
||||||
public interface That extends Configuration {
|
public interface That extends Configuration {
|
||||||
|
|
||||||
ConfiguredList<UUID> OPERATORS = ConfiguredList
|
ConfiguredList<UUID> OPERATORS = ConfiguredList
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public class RegistryConfig implements Configuration {
|
|||||||
|
|
||||||
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
@ConfigPath("test.user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
|
||||||
@FooterComments({"12313213212"})
|
@FooterComments({"12313213212"})
|
||||||
|
@InlineComment(value = "用户名(匹配注释)", regex = "name") // 通过注解给配置添加注释。
|
||||||
|
@InlineComment(value = "信息", regex = {"info.*", "info.game.*"}) // 通过注解给配置添加注释。
|
||||||
public final ConfigValue<UserRecord> TEST_MODEL = ConfiguredValue.builderOf(UserRecord.class).fromSection()
|
public final ConfigValue<UserRecord> TEST_MODEL = ConfiguredValue.builderOf(UserRecord.class).fromSection()
|
||||||
.defaults(new UserRecord("Carm", UUID.randomUUID()))
|
.defaults(new UserRecord("Carm", UUID.randomUUID()))
|
||||||
.parse((holder, section) -> UserRecord.deserialize(section))
|
.parse((holder, section) -> UserRecord.deserialize(section))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ public @interface InlineComment {
|
|||||||
* If the regex is not empty, the comment will be added to
|
* If the regex is not empty, the comment will be added to
|
||||||
* all sub paths if the regex matches the value.
|
* all sub paths if the regex matches the value.
|
||||||
* If the regex is empty, the comment will be added to the current path.
|
* If the regex is empty, the comment will be added to the current path.
|
||||||
* <p> e.g. for section, set <b>{"^foo", "*", "bar"}</b> will be set like
|
* <p> e.g. for section, set <b>"foo.*.bar"</b> will be set like
|
||||||
* <blockquote><pre>
|
* <blockquote><pre>
|
||||||
* section:
|
* section:
|
||||||
* foo:
|
* foo:
|
||||||
|
|||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package cc.carm.lib.configuration.commentable;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
|
||||||
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Commentable {
|
||||||
|
|
||||||
|
private Commentable() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerMeta(@NotNull ConfigurationInitializer initializer) {
|
||||||
|
CommentableMeta.register(initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable String getInlineComment(@NotNull ConfigurationHolder<?> holder, @NotNull String path) {
|
||||||
|
String comment = getInlineComment(holder, path, null);
|
||||||
|
if (comment != null) return comment;
|
||||||
|
|
||||||
|
String sep = String.valueOf(holder.options().get(StandardOptions.PATH_SEPARATOR));
|
||||||
|
|
||||||
|
// If the comment is not found, try to get the comment from the parent section
|
||||||
|
String[] keys = path.split(Pattern.quote(sep));
|
||||||
|
if (keys.length == 1) return null;
|
||||||
|
|
||||||
|
// Try every possible parent key&child key combination
|
||||||
|
for (int i = 1; i < keys.length; i++) {
|
||||||
|
String parentKey = String.join(sep, Arrays.copyOfRange(keys, 0, i));
|
||||||
|
String childKey = String.join(sep, Arrays.copyOfRange(keys, i, keys.length));
|
||||||
|
comment = getInlineComment(holder, parentKey, childKey);
|
||||||
|
if (comment != null) return comment;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable String getInlineComment(@NotNull ConfigurationHolder<?> holder, @NotNull String path, @Nullable String sectionKey) {
|
||||||
|
Map<String, String> pathComment = holder.metadata(path).get(CommentableMeta.INLINE);
|
||||||
|
if (pathComment == null || pathComment.isEmpty()) return null;
|
||||||
|
if (sectionKey == null) return pathComment.get(null);
|
||||||
|
for (Map.Entry<String/*regex*/, String/*content*/> entry : pathComment.entrySet()) {
|
||||||
|
if (entry.getKey() == null) continue;
|
||||||
|
if (Objects.equals(entry.getKey(), sectionKey)) return entry.getValue();
|
||||||
|
Pattern pattern = Pattern.compile(entry.getKey().replace(".", "\\.").replace("*", "(.*)"));
|
||||||
|
if (pattern.matcher(sectionKey).matches()) return entry.getValue();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable List<String> getHeaderComments(@NotNull ConfigurationHolder<?> holder, @Nullable String path) {
|
||||||
|
return holder.metadata(path).get(CommentableMeta.HEADER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable List<String> getFooterComments(@NotNull ConfigurationHolder<?> holder, @Nullable String path) {
|
||||||
|
return holder.metadata(path).get(CommentableMeta.FOOTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package cc.carm.lib.configuration.option;
|
package cc.carm.lib.configuration.commentable;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
import cc.carm.lib.configuration.source.option.ConfigurationOption;
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>cc.carm.lib</groupId>
|
||||||
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
|
<version>4.0.1</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<artifactId>easyconfiguration-feature-text</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-core</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>easyconfiguration-yaml</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueAdapter;
|
||||||
|
import cc.carm.lib.configuration.adapter.ValueType;
|
||||||
|
import cc.carm.lib.configuration.builder.AbstractConfigBuilder;
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
|
import cc.carm.lib.configuration.value.standard.ConfiguredValue;
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import cc.carm.lib.configuration.value.text.function.TextDispatcher;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param <MSG> The type of the message
|
||||||
|
* @param <RECEIVER> The type of the receiver
|
||||||
|
*/
|
||||||
|
public class ConfiguredText<MSG, RECEIVER> extends ConfiguredValue<TextContents> {
|
||||||
|
|
||||||
|
public static <M, R> Builder<M, R, ?> builder() {
|
||||||
|
return new StardardBuilder<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final ValueType<TextContents> TEXT_TYPE = ValueType.of(TextContents.class);
|
||||||
|
public static final ValueAdapter<TextContents> TEXT_ADAPTER = new ValueAdapter<>(TEXT_TYPE,
|
||||||
|
(h, t, d) -> d.serialize(),
|
||||||
|
(h, t, d) -> TextContents.deserialize(d)
|
||||||
|
);
|
||||||
|
|
||||||
|
protected final @NotNull BiFunction<RECEIVER, String, String> parser;
|
||||||
|
protected final @NotNull BiFunction<RECEIVER, String, MSG> compiler;
|
||||||
|
protected final @NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher;
|
||||||
|
|
||||||
|
protected final @NotNull String[] params; // The parameters of the message.
|
||||||
|
|
||||||
|
public ConfiguredText(@NotNull ValueManifest<TextContents> manifest,
|
||||||
|
@NotNull BiFunction<RECEIVER, String, String> parser,
|
||||||
|
@NotNull BiFunction<RECEIVER, String, MSG> compiler,
|
||||||
|
@NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher,
|
||||||
|
@NotNull String[] params) {
|
||||||
|
super(manifest, TEXT_ADAPTER);
|
||||||
|
this.parser = parser;
|
||||||
|
this.compiler = compiler;
|
||||||
|
this.dispatcher = dispatcher;
|
||||||
|
this.params = params;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextDispatcher<MSG, RECEIVER, ?> prepare(@NotNull Object... values) {
|
||||||
|
return new PreparedText<MSG, RECEIVER>(resolve(), this.params)
|
||||||
|
.parser(this.parser).compiler(this.compiler)
|
||||||
|
.dispatcher(this.dispatcher).placeholders(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the message for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
* @return The parsed message.
|
||||||
|
*/
|
||||||
|
public List<String> parse(@Nullable RECEIVER receiver, @NotNull Object... values) {
|
||||||
|
return prepare(values).parse(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the message for the receiver and send it.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
* @return The parsed message.
|
||||||
|
*/
|
||||||
|
public String parseLine(@Nullable RECEIVER receiver, @NotNull Object... values) {
|
||||||
|
return prepare(values).parseLine(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the message for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
* @return The compiled message.
|
||||||
|
*/
|
||||||
|
public List<MSG> compile(@Nullable RECEIVER receiver, @NotNull Object... values) {
|
||||||
|
return prepare(values).compile(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the message for the receiver and send it.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
* @return The compiled message.
|
||||||
|
*/
|
||||||
|
public MSG compileLine(@Nullable RECEIVER receiver, @NotNull Object... values) {
|
||||||
|
return prepare(values).compileLine(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the message to the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
*/
|
||||||
|
public void sendTo(@NotNull RECEIVER receiver, @NotNull Object... values) {
|
||||||
|
prepare(values).to(receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the message to the multiple receivers.
|
||||||
|
*
|
||||||
|
* @param receivers The receivers of the message.
|
||||||
|
* @param values The values to replace the {@link #params}.
|
||||||
|
*/
|
||||||
|
public void sendToAll(@NotNull Iterable<? extends RECEIVER> receivers, @NotNull Object... values) {
|
||||||
|
prepare(values).to(receivers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class Builder<MSG, RECEIVER, SELF extends Builder<MSG, RECEIVER, SELF>>
|
||||||
|
extends AbstractConfigBuilder<TextContents, ConfiguredText<MSG, RECEIVER>, ConfigurationHolder<?>, SELF> {
|
||||||
|
protected @NotNull TextContents.Builder defaultBuilder = TextContents.builder();
|
||||||
|
protected @NotNull String[] params = new String[0];
|
||||||
|
|
||||||
|
protected @NotNull BiFunction<RECEIVER, String, String> parser = (r, s) -> s;
|
||||||
|
protected @NotNull BiFunction<RECEIVER, String, MSG> compiler = (r, s) -> {
|
||||||
|
throw new IllegalStateException("Compiler not supplied.");
|
||||||
|
};
|
||||||
|
protected @NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher = (r, l) -> {
|
||||||
|
throw new IllegalStateException("Dispatcher not supplied.");
|
||||||
|
};
|
||||||
|
|
||||||
|
protected Builder() {
|
||||||
|
super(ConfigurationHolder.class, TEXT_TYPE);
|
||||||
|
defaults(() -> defaultBuilder.build()); // Set the default value from the default builder.
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF parser(@NotNull BiFunction<RECEIVER, String, String> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF compiler(@NotNull BiFunction<RECEIVER, String, MSG> compiler) {
|
||||||
|
this.compiler = compiler;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF dispatcher(@NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher) {
|
||||||
|
this.dispatcher = dispatcher;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF params(@NotNull String... params) {
|
||||||
|
this.params = params;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF defaults(@NotNull Consumer<TextContents.Builder> consumer) {
|
||||||
|
consumer.accept(this.defaultBuilder);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF defaults(@NotNull String... contents) {
|
||||||
|
return defaults(builder -> builder.set(contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF defaults(@NotNull Iterable<String> contents) {
|
||||||
|
return defaults(builder -> builder.set(contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF optional(@NotNull String id, @NotNull String... lines) {
|
||||||
|
return defaults(builder -> builder.optional(id, lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull SELF optional(@NotNull String id, @NotNull Iterable<String> lines) {
|
||||||
|
return defaults(builder -> builder.optional(id, lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredText<MSG, RECEIVER> build() {
|
||||||
|
return new ConfiguredText<>(buildManifest(), this.parser, this.compiler, this.dispatcher, this.params);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StardardBuilder<MSG, RECEIVER> extends Builder<MSG, RECEIVER, StardardBuilder<MSG, RECEIVER>> {
|
||||||
|
@Override
|
||||||
|
protected @NotNull StardardBuilder<MSG, RECEIVER> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import cc.carm.lib.configuration.value.text.function.TextDispatcher;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class PreparedText<MSG, RECEIVER> extends TextDispatcher<MSG, RECEIVER, PreparedText<MSG, RECEIVER>> {
|
||||||
|
|
||||||
|
protected final @NotNull TextContents texts;
|
||||||
|
|
||||||
|
public PreparedText(@NotNull TextContents texts, @NotNull String... params) {
|
||||||
|
this.params = params;
|
||||||
|
this.texts = texts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TextContents texts() {
|
||||||
|
return this.texts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PreparedText<MSG, RECEIVER> self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreparedText<MSG, RECEIVER> insert(@NotNull String key,
|
||||||
|
@NotNull ConfiguredText<?, RECEIVER> message,
|
||||||
|
@NotNull Object... values) {
|
||||||
|
return insert(key, receiver -> message.parse(receiver, values));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+160
@@ -0,0 +1,160 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.data;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.section.ConfigureSection;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TextContents {
|
||||||
|
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TextContents of(@NotNull List<String> lines, @NotNull Map<String, List<String>> optional) {
|
||||||
|
return new TextContents(lines, optional);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final @NotNull List<String> lines;
|
||||||
|
protected final @NotNull Map<String, List<String>> optional;
|
||||||
|
|
||||||
|
public TextContents(@NotNull List<String> lines, @NotNull Map<String, List<String>> optional) {
|
||||||
|
this.lines = lines;
|
||||||
|
this.optional = optional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return lines.isEmpty() || lines.stream().allMatch(String::isEmpty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull List<String> lines() {
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull Map<String, List<String>> optionalLines() {
|
||||||
|
return optional;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable Object serialize() {
|
||||||
|
if (optional.isEmpty()) {
|
||||||
|
if (lines.isEmpty()) return null;
|
||||||
|
else if (lines.size() == 1) return lines.get(0);
|
||||||
|
else return lines;
|
||||||
|
} else {
|
||||||
|
Map<String, Object> map = new LinkedHashMap<>();
|
||||||
|
map.put("contents", lines);
|
||||||
|
map.put("optional", optional);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @Nullable TextContents deserialize(@NotNull Object data) {
|
||||||
|
Builder builder = builder();
|
||||||
|
if (data instanceof String) {
|
||||||
|
return builder.set((String) data).build();
|
||||||
|
} else if (data instanceof List<?>) {
|
||||||
|
((List<?>) data).stream().map(Object::toString).forEach(builder::add);
|
||||||
|
return builder.build();
|
||||||
|
} else if (data instanceof ConfigureSection) {
|
||||||
|
ConfigureSection section = (ConfigureSection) data;
|
||||||
|
builder.set(section.getStringList("contents"));
|
||||||
|
|
||||||
|
ConfigureSection optionalSection = section.getSection("optional");
|
||||||
|
if (optionalSection != null) {
|
||||||
|
for (String key : optionalSection.getKeys(false)) {
|
||||||
|
builder.optional(key, optionalSection.getStringList(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
protected List<String> lines = new ArrayList<>();
|
||||||
|
protected Map<String, List<String>> optional = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add lines to the contents
|
||||||
|
*
|
||||||
|
* @param lines lines to add
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder add(@NotNull String... lines) {
|
||||||
|
this.lines.addAll(Arrays.asList(lines));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add lines to the contents
|
||||||
|
*
|
||||||
|
* @param lines lines to add
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder add(@NotNull Iterable<String> lines) {
|
||||||
|
lines.forEach(this.lines::add);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the lines of the contents
|
||||||
|
*
|
||||||
|
* @param lines lines to set
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder set(@NotNull String... lines) {
|
||||||
|
this.lines = Arrays.asList(lines);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the lines of the contents
|
||||||
|
*
|
||||||
|
* @param lines lines to set
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder set(@NotNull Iterable<String> lines) {
|
||||||
|
this.lines = new ArrayList<>();
|
||||||
|
lines.forEach(this.lines::add);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add optional lines to the contents
|
||||||
|
*
|
||||||
|
* @param key key of the optional lines
|
||||||
|
* @param lines lines to add
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder optional(@NotNull String key, @NotNull String... lines) {
|
||||||
|
optional.put(key, Arrays.asList(lines));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add optional lines to the contents
|
||||||
|
*
|
||||||
|
* @param key key of the optional lines
|
||||||
|
* @param lines lines to add
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public Builder optional(@NotNull String key, @NotNull Iterable<String> lines) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
lines.forEach(list::add);
|
||||||
|
optional.put(key, list);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The built TextContents
|
||||||
|
*/
|
||||||
|
public TextContents build() {
|
||||||
|
return of(lines, optional);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+259
@@ -0,0 +1,259 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.function;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public abstract class ContentHandler<RECEIVER, SELF extends ContentHandler<RECEIVER, SELF>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to match the message insertion
|
||||||
|
* <p>
|
||||||
|
* format:
|
||||||
|
* <br>- to insert parsed line {prefix}#content-id#{offset-above,offset-down}
|
||||||
|
* <br>- to insert original line {prefix}@content-id@{offset-above,offset-down}
|
||||||
|
* <br> example:
|
||||||
|
* <ul>
|
||||||
|
* <li>{- }#content-id#{1,1}</li>
|
||||||
|
* <li>@content-id@{1,1}</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static final @NotNull Pattern INSERT_PATTERN = Pattern.compile(
|
||||||
|
"^(?:\\{(?<prefix>.*)})?(?<type>[#@])(?<id>.*)[#@](?:\\{(?<above>-?\\d+)(?:,(?<down>-?\\d+))?})?$"
|
||||||
|
);
|
||||||
|
public static final @NotNull UnaryOperator<String> DEFAULT_PARAM_BUILDER = s -> "%(" + s + ")";
|
||||||
|
|
||||||
|
protected BiFunction<RECEIVER, String, String> parser = (receiver, value) -> value;
|
||||||
|
protected String lineSeparator = System.lineSeparator();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to store the placeholders of the message
|
||||||
|
*/
|
||||||
|
protected @NotNull Map<String, Object> placeholders = new HashMap<>();
|
||||||
|
protected @NotNull UnaryOperator<String> paramFormatter = DEFAULT_PARAM_BUILDER;
|
||||||
|
protected @NotNull String[] params;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to store the insertion of the message
|
||||||
|
*/
|
||||||
|
protected @NotNull Map<String, Function<RECEIVER, List<String>>> insertion = new HashMap<>();
|
||||||
|
protected boolean disableInsertion = false;
|
||||||
|
|
||||||
|
public abstract SELF self();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable the insertion of the text.
|
||||||
|
* <br> If the insertion is disabled, the text will be parsed directly.
|
||||||
|
*
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF disableInsertion() {
|
||||||
|
this.disableInsertion = true;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable the insertion of the text.
|
||||||
|
*
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF enableInsertion() {
|
||||||
|
this.disableInsertion = false;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the line separator for the text.
|
||||||
|
*
|
||||||
|
* @param lineSeparator the line separator, default is {@link System#lineSeparator()}
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF lineSeparator(@NotNull String lineSeparator) {
|
||||||
|
this.lineSeparator = lineSeparator;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set all the placeholders for the text.
|
||||||
|
* <br> Will override the previous placeholders modifications.
|
||||||
|
*
|
||||||
|
* @param placeholders the placeholders
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF placeholders(@NotNull Map<String, Object> placeholders) {
|
||||||
|
this.placeholders = placeholders;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the placeholders for the text.
|
||||||
|
*
|
||||||
|
* @param consumer the placeholders
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF placeholders(@NotNull Consumer<Map<String, Object>> consumer) {
|
||||||
|
consumer.accept(this.placeholders);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the placeholders for the text.
|
||||||
|
*
|
||||||
|
* @param values The values to replace the {@link #params(String...)}.
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF placeholders(@Nullable Object... values) {
|
||||||
|
return placeholders(map -> map.putAll(buildParams(this.paramFormatter, this.params, values)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the placeholder for the text.
|
||||||
|
*
|
||||||
|
* @param key the key of the placeholder
|
||||||
|
* @param value the value of the placeholder
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF placeholder(@NotNull String key, @Nullable Object value) {
|
||||||
|
this.placeholders.put(paramFormatter.apply(key), value);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the params for the text,
|
||||||
|
* used for {@link #placeholders(Object...)} to build the placeholders.
|
||||||
|
*
|
||||||
|
* @param params the params
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF params(@NotNull String... params) {
|
||||||
|
this.params = params;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the specific contents by the id.
|
||||||
|
*
|
||||||
|
* @param id the id of the insertion text
|
||||||
|
* @param linesSupplier to supply the lines to insert
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF insert(@NotNull String id, @NotNull Function<RECEIVER, List<String>> linesSupplier) {
|
||||||
|
this.insertion.put(id, linesSupplier);
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the specific contents by the id.
|
||||||
|
*
|
||||||
|
* @param id the id of the insertion text
|
||||||
|
* @param lines the lines to insert
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF insert(@NotNull String id, @NotNull String... lines) {
|
||||||
|
return insert(id, Arrays.asList(lines));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the specific contents by the id.
|
||||||
|
*
|
||||||
|
* @param id the id of the insertion text
|
||||||
|
* @param lines the lines to insert
|
||||||
|
* @return the current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF insert(@NotNull String id, @NotNull List<String> lines) {
|
||||||
|
return insert(id, receiver -> lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the parser for the text.
|
||||||
|
*
|
||||||
|
* @param parser The parser
|
||||||
|
* @return The current {@link ContentHandler} instance
|
||||||
|
*/
|
||||||
|
public SELF parser(@NotNull BiFunction<RECEIVER, String, String> parser) {
|
||||||
|
this.parser = parser;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the supplied single text for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver the receiver
|
||||||
|
* @param text the text to parse
|
||||||
|
* @return the parsed text
|
||||||
|
*/
|
||||||
|
protected @Nullable String parse(@Nullable RECEIVER receiver, @NotNull String text) {
|
||||||
|
return this.parser.apply(receiver, setPlaceholders(text, this.placeholders));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(@NotNull TextContents contents, @Nullable RECEIVER receiver,
|
||||||
|
@NotNull Consumer<String> lineConsumer) {
|
||||||
|
if (contents.isEmpty()) return; // Nothing to parse
|
||||||
|
|
||||||
|
if (this.disableInsertion) {
|
||||||
|
contents.lines().forEach(line -> lineConsumer.accept(parse(receiver, line)));
|
||||||
|
return; // Simple parsed
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String line : contents.lines()) {
|
||||||
|
Matcher matcher = INSERT_PATTERN.matcher(line);
|
||||||
|
if (!matcher.matches()) {
|
||||||
|
lineConsumer.accept(parse(receiver, line));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String id = matcher.group("id");
|
||||||
|
List<String> values = Optional.ofNullable(this.insertion.get(id))
|
||||||
|
.map(f -> f.apply(receiver))
|
||||||
|
.orElse(null);
|
||||||
|
if (values == null || values.isEmpty()) continue;
|
||||||
|
|
||||||
|
String prefix = matcher.group("prefix");
|
||||||
|
String type = matcher.group("type");
|
||||||
|
boolean original = type.equals("@");
|
||||||
|
int offsetAbove = Optional.ofNullable(matcher.group("above"))
|
||||||
|
.map(Integer::parseInt).orElse(0);
|
||||||
|
int offsetDown = Optional.ofNullable(matcher.group("down"))
|
||||||
|
.map(Integer::parseInt).orElse(offsetAbove); // If offsetDown is not set, use offsetAbove
|
||||||
|
|
||||||
|
IntStream.range(0, Math.max(0, offsetAbove)).mapToObj(i -> "").forEach(lineConsumer);
|
||||||
|
String prefixContent = Optional.ofNullable(prefix).map(p -> parse(receiver, p)).orElse("");
|
||||||
|
if (original) {
|
||||||
|
values.stream().map(value -> prefixContent + value).forEach(lineConsumer);
|
||||||
|
} else {
|
||||||
|
values.stream().map(value -> prefixContent + parse(receiver, value)).forEach(lineConsumer);
|
||||||
|
}
|
||||||
|
IntStream.range(0, Math.max(0, offsetDown)).mapToObj(i -> "").forEach(lineConsumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String setPlaceholders(@NotNull String messages,
|
||||||
|
@NotNull Map<String, Object> placeholders) {
|
||||||
|
if (messages.isEmpty()) return messages;
|
||||||
|
String parsed = messages;
|
||||||
|
for (Map.Entry<String, Object> entry : placeholders.entrySet()) {
|
||||||
|
parsed = parsed.replace(entry.getKey(), entry.getValue() == null ? "" : entry.getValue().toString());
|
||||||
|
}
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> buildParams(@NotNull UnaryOperator<String> paramBuilder,
|
||||||
|
@Nullable String[] params, @Nullable Object[] values) {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
if (params == null || params.length == 0) return map;
|
||||||
|
for (int i = 0; i < params.length; i++) {
|
||||||
|
map.put(paramBuilder.apply(params[i]), (values != null && values.length > i) ? values[i] : "?");
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.function;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
public abstract class TextCompiler<MSG, RECEIVER, SELF extends TextCompiler<MSG, RECEIVER, SELF>> extends TextParser<RECEIVER, SELF> {
|
||||||
|
|
||||||
|
protected BiFunction<RECEIVER, String, MSG> compiler = (receiver, value) -> null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the text compiler.
|
||||||
|
*
|
||||||
|
* @param compiler The text compiler.
|
||||||
|
* @return The current {@link TextCompiler} instance.
|
||||||
|
*/
|
||||||
|
public SELF compiler(@NotNull BiFunction<RECEIVER, String, MSG> compiler) {
|
||||||
|
this.compiler = compiler;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the text for specific receiver.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver.
|
||||||
|
* @return The compiled text.
|
||||||
|
* @see #parse(Object, BiFunction)
|
||||||
|
*/
|
||||||
|
public @NotNull List<MSG> compile(@Nullable RECEIVER receiver) {
|
||||||
|
return parse(receiver, this.compiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the singleton text for specific receiver.
|
||||||
|
*
|
||||||
|
* @param receiver The receiver.
|
||||||
|
* @return The compiled text.
|
||||||
|
* @see #parseLine(Object, BiFunction)
|
||||||
|
*/
|
||||||
|
public @Nullable MSG compileLine(@Nullable RECEIVER receiver) {
|
||||||
|
return parseLine(receiver, this.compiler);
|
||||||
|
}
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.function;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public abstract class TextDispatcher<MSG, RECEIVER, SELF extends TextDispatcher<MSG, RECEIVER, SELF>> extends TextCompiler<MSG, RECEIVER, SELF> {
|
||||||
|
|
||||||
|
protected @NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher = (receiver, msg) -> {
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the dispatcher to send the message to the receiver
|
||||||
|
*
|
||||||
|
* @param dispatcher the dispatcher
|
||||||
|
* @return {@link TextDispatcher}
|
||||||
|
*/
|
||||||
|
public SELF dispatcher(@NotNull BiConsumer<RECEIVER, List<MSG>> dispatcher) {
|
||||||
|
this.dispatcher = dispatcher;
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch the message to the receiver
|
||||||
|
*
|
||||||
|
* @param receivers the receivers
|
||||||
|
*/
|
||||||
|
@SafeVarargs
|
||||||
|
public final void to(@NotNull RECEIVER... receivers) {
|
||||||
|
if (receivers.length == 0) return;
|
||||||
|
to(Arrays.asList(receivers));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch the message to the receiver
|
||||||
|
*
|
||||||
|
* @param receivers the receivers
|
||||||
|
*/
|
||||||
|
public void to(@NotNull Iterable<? extends RECEIVER> receivers) {
|
||||||
|
for (RECEIVER receiver : receivers) {
|
||||||
|
List<MSG> msg = compile(receiver);
|
||||||
|
if (msg.isEmpty()) return;
|
||||||
|
dispatcher.accept(receiver, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatch the message to the receiver
|
||||||
|
*
|
||||||
|
* @param receivers the receivers
|
||||||
|
*/
|
||||||
|
public void to(@NotNull Supplier<Iterable<? extends RECEIVER>> receivers) {
|
||||||
|
to(receivers.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+74
@@ -0,0 +1,74 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.function;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public abstract class TextParser<RECEIVER, SELF extends TextParser<RECEIVER, SELF>>
|
||||||
|
extends ContentHandler<RECEIVER, SELF> {
|
||||||
|
|
||||||
|
public abstract TextContents texts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the texts for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver the receiver
|
||||||
|
* @return the parsed line
|
||||||
|
*/
|
||||||
|
public List<String> parse(@Nullable RECEIVER receiver) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
handle(receiver, result::add);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the texts for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver the receiver
|
||||||
|
* @param compiler the compiler
|
||||||
|
* @param <V> the type of the message
|
||||||
|
* @return the parsed line
|
||||||
|
*/
|
||||||
|
public <V> List<V> parse(@Nullable RECEIVER receiver, @NotNull BiFunction<RECEIVER, String, V> compiler) {
|
||||||
|
List<V> result = new ArrayList<>();
|
||||||
|
handle(receiver, s -> result.add(compiler.apply(receiver, s)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the texts as a single line for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver the receiver
|
||||||
|
* @return the parsed line
|
||||||
|
*/
|
||||||
|
public @Nullable String parseLine(@Nullable RECEIVER receiver) {
|
||||||
|
if (texts().isEmpty()) return null;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
handle(receiver, s -> builder.append(s).append(this.lineSeparator));
|
||||||
|
// Remove the last line separator, if it exists
|
||||||
|
if (builder.length() > 0) builder.delete(builder.length() - this.lineSeparator.length(), builder.length());
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the texts as a single line for the receiver.
|
||||||
|
*
|
||||||
|
* @param receiver the receiver
|
||||||
|
* @param <V> the type of the message
|
||||||
|
* @return the parsed line
|
||||||
|
*/
|
||||||
|
public <V> @Nullable V parseLine(@Nullable RECEIVER receiver, @NotNull BiFunction<RECEIVER, String, V> compiler) {
|
||||||
|
return Optional.ofNullable(parseLine(receiver)).map(s -> compiler.apply(receiver, s)).orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handle(@Nullable RECEIVER receiver, @NotNull Consumer<String> lineConsumer) {
|
||||||
|
handle(texts(), receiver, lineConsumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.tests;
|
||||||
|
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
|
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
||||||
|
import cc.carm.lib.configuration.value.text.tests.conf.AppMessages;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ConfigTest {
|
||||||
|
|
||||||
|
|
||||||
|
public static final String[] WEBSITES = new String[]{
|
||||||
|
"https://carm.cc",
|
||||||
|
"https://www.baidu.com",
|
||||||
|
"https://www.google.com"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/messages.yml").build();
|
||||||
|
|
||||||
|
holder.initialize(AppMessages.class);
|
||||||
|
|
||||||
|
System.out.println("--------------------------");
|
||||||
|
|
||||||
|
AppMessages.WELCOME.prepare()
|
||||||
|
.placeholders("Carm")
|
||||||
|
.insert("guidance")
|
||||||
|
.insert("websites", WEBSITES)
|
||||||
|
.to(System.out);
|
||||||
|
|
||||||
|
System.out.println("--------------------------");
|
||||||
|
|
||||||
|
AppMessages.NOT_AVAILABLE.sendTo(System.out);
|
||||||
|
|
||||||
|
System.out.println("--------------------------");
|
||||||
|
|
||||||
|
AppMessages.NO_PERMISSION.sendTo(System.out);
|
||||||
|
|
||||||
|
System.out.println("--------------------------");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.tests;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.text.PreparedText;
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class ParseTest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
List<String> lines = new ArrayList<>();
|
||||||
|
lines.add("Hello, %(name)");
|
||||||
|
lines.add("#more-creating#{1}");
|
||||||
|
lines.add("This is a test message");
|
||||||
|
lines.add("#guidance#");
|
||||||
|
lines.add("{- }#websites#{0,1}");
|
||||||
|
lines.add("Thanks for your reading!");
|
||||||
|
|
||||||
|
|
||||||
|
Map<String, List<String>> optional = new HashMap<>();
|
||||||
|
optional.put("guidance", Arrays.asList("To get more information for %(name), see:"));
|
||||||
|
optional.put("websites", Arrays.asList("https://www.baidu.com", "https://www.google.com"));
|
||||||
|
|
||||||
|
TextContents textContents = new TextContents(lines, optional);
|
||||||
|
|
||||||
|
PreparedText<String, PrintStream> msg = new PreparedText<String, PrintStream>(textContents)
|
||||||
|
.dispatcher((p, s) -> s.forEach(p::println))
|
||||||
|
.parser((p, s) -> s)
|
||||||
|
.compiler((p, s) -> s);
|
||||||
|
|
||||||
|
msg.placeholder("name", "Carm")
|
||||||
|
.insert("guidance")
|
||||||
|
.insert("websites", "Baidu", "Bilibili", "Google");
|
||||||
|
|
||||||
|
System.out.println("----------------------------");
|
||||||
|
msg.to(System.out);
|
||||||
|
System.out.println("----------------------------");
|
||||||
|
System.out.println(msg.compileLine(System.out));
|
||||||
|
System.out.println("----------------------------");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.tests.conf;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.Configuration;
|
||||||
|
import cc.carm.lib.configuration.annotation.ConfigPath;
|
||||||
|
|
||||||
|
@ConfigPath(root = true)
|
||||||
|
public interface AppMessages extends Configuration {
|
||||||
|
|
||||||
|
ConfiguredMsg WELCOME = ConfiguredMsg.builder()
|
||||||
|
.defaults(
|
||||||
|
"Hello, %(name)",
|
||||||
|
"#more-creating#{1}",
|
||||||
|
"This is a test message",
|
||||||
|
"#guidance#",
|
||||||
|
"{- }#websites#{0,1}",
|
||||||
|
"Thanks for your reading!")
|
||||||
|
.optional("guidance", "To get more information for %(name), see:")
|
||||||
|
.params("name").build();
|
||||||
|
|
||||||
|
ConfiguredMsg NO_PERMISSION = ConfiguredMsg.builder()
|
||||||
|
.defaults("Sorry! But you don't have permissions to do this.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ConfiguredMsg NOT_AVAILABLE = ConfiguredMsg.builder()
|
||||||
|
.defaults("Error! Service is not available now.", "Please contact your system manager.")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
+47
@@ -0,0 +1,47 @@
|
|||||||
|
package cc.carm.lib.configuration.value.text.tests.conf;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.value.ValueManifest;
|
||||||
|
import cc.carm.lib.configuration.value.text.ConfiguredText;
|
||||||
|
import cc.carm.lib.configuration.value.text.data.TextContents;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
|
||||||
|
public class ConfiguredMsg extends ConfiguredText<String, PrintStream> {
|
||||||
|
|
||||||
|
public static @NotNull MsgBuilder builder() {
|
||||||
|
return new MsgBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static @NotNull ConfiguredMsg of(@NotNull String... text) {
|
||||||
|
return builder().defaults(text).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfiguredMsg(@NotNull ValueManifest<TextContents> manifest, @NotNull String[] params) {
|
||||||
|
super(
|
||||||
|
manifest,
|
||||||
|
(p, s) -> s,
|
||||||
|
(p, s) -> s,
|
||||||
|
(p, s) -> s.forEach(p::println),
|
||||||
|
params
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void print(@NotNull Object... values) {
|
||||||
|
sendTo(System.out, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MsgBuilder extends Builder<String, PrintStream, MsgBuilder> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected @NotNull MsgBuilder self() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull ConfiguredMsg build() {
|
||||||
|
return new ConfiguredMsg(buildManifest(), params);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
|
|||||||
@@ -15,13 +15,14 @@
|
|||||||
<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>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<modules>
|
<modules>
|
||||||
<module>core</module>
|
<module>core</module>
|
||||||
<module>features/section</module>
|
<module>features/section</module>
|
||||||
<module>features/file</module>
|
<module>features/file</module>
|
||||||
<module>features/commentable</module>
|
<module>features/commentable</module>
|
||||||
<module>features/versioned</module>
|
<module>features/versioned</module>
|
||||||
|
<module>features/text</module>
|
||||||
|
|
||||||
<module>providers/yaml</module>
|
<module>providers/yaml</module>
|
||||||
<module>providers/gson</module>
|
<module>providers/gson</module>
|
||||||
|
|||||||
@@ -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>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>easyconfiguration-parent</artifactId>
|
<artifactId>easyconfiguration-parent</artifactId>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<version>4.0.0</version>
|
<version>4.0.1</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
|
||||||
<deps.yamlcommentwriter.version>1.1.0</deps.yamlcommentwriter.version>
|
<deps.yamlcommentwriter.version>1.2.0</deps.yamlcommentwriter.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<artifactId>easyconfiguration-yaml</artifactId>
|
<artifactId>easyconfiguration-yaml</artifactId>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cc.carm.lib</groupId>
|
<groupId>cc.carm.lib</groupId>
|
||||||
<artifactId>yamlcommentwriter</artifactId>
|
<artifactId>yamlcommentwriter</artifactId>
|
||||||
<version>1.1.0</version>
|
<version>1.2.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
package cc.carm.lib.configuration.source.yaml;
|
package cc.carm.lib.configuration.source.yaml;
|
||||||
|
|
||||||
|
import cc.carm.lib.configuration.commentable.Commentable;
|
||||||
import cc.carm.lib.configuration.commentable.CommentableMeta;
|
import cc.carm.lib.configuration.commentable.CommentableMeta;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.file.FileConfigFactory;
|
import cc.carm.lib.configuration.source.file.FileConfigFactory;
|
||||||
@@ -125,7 +126,7 @@ public class YAMLConfigFactory extends FileConfigFactory<YAMLSource, Configurati
|
|||||||
File configFile = this.file;
|
File configFile = this.file;
|
||||||
String sourcePath = this.resourcePath;
|
String sourcePath = this.resourcePath;
|
||||||
|
|
||||||
CommentableMeta.register(this.initializer); // Register commentable meta types
|
Commentable.registerMeta(this.initializer); // Register commentable meta types
|
||||||
|
|
||||||
return new ConfigurationHolder<YAMLSource>(this.adapters, this.options, this.metadata, this.initializer) {
|
return new ConfigurationHolder<YAMLSource>(this.adapters, this.options, this.metadata, this.initializer) {
|
||||||
final @NotNull YAMLSource source = new YAMLSource(this, configFile, sourcePath);
|
final @NotNull YAMLSource source = new YAMLSource(this, configFile, sourcePath);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package cc.carm.lib.configuration.source.yaml;
|
package cc.carm.lib.configuration.source.yaml;
|
||||||
|
|
||||||
import cc.carm.lib.configuration.commentable.CommentableMeta;
|
import cc.carm.lib.configuration.commentable.Commentable;
|
||||||
import cc.carm.lib.configuration.option.CommentableOptions;
|
import cc.carm.lib.configuration.commentable.CommentableOptions;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.file.FileConfigSource;
|
import cc.carm.lib.configuration.source.file.FileConfigSource;
|
||||||
import cc.carm.lib.configuration.source.option.StandardOptions;
|
import cc.carm.lib.configuration.source.option.StandardOptions;
|
||||||
@@ -25,9 +25,10 @@ import java.io.Reader;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
public class YAMLSource extends FileConfigSource<MemorySection, Map<String, Object>, YAMLSource> implements CommentedSection {
|
public class YAMLSource
|
||||||
|
extends FileConfigSource<MemorySection, Map<String, Object>, YAMLSource>
|
||||||
|
implements CommentedSection {
|
||||||
|
|
||||||
protected final @NotNull YamlConstructor yamlConstructor;
|
protected final @NotNull YamlConstructor yamlConstructor;
|
||||||
protected final @NotNull YamlRepresenter yamlRepresenter;
|
protected final @NotNull YamlRepresenter yamlRepresenter;
|
||||||
@@ -193,46 +194,17 @@ public class YAMLSource extends FileConfigSource<MemorySection, Map<String, Obje
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable String getInlineComment(@NotNull String key) {
|
public @Nullable String getInlineComment(@NotNull String key) {
|
||||||
String comment = getInlineComment(key, null);
|
return Commentable.getInlineComment(holder(), key);
|
||||||
if (comment != null) return comment;
|
|
||||||
|
|
||||||
String sep = String.valueOf(separator());
|
|
||||||
|
|
||||||
// If the comment is not found, try to get the comment from the parent section
|
|
||||||
String[] keys = key.split(sep);
|
|
||||||
if (keys.length == 1) return null;
|
|
||||||
|
|
||||||
// Try every possible parent key&child key combination
|
|
||||||
for (int i = 1; i < keys.length; i++) {
|
|
||||||
String parentKey = String.join(sep, Arrays.copyOfRange(keys, 0, i));
|
|
||||||
String childKey = String.join(sep, Arrays.copyOfRange(keys, i, keys.length));
|
|
||||||
comment = getInlineComment(childKey, parentKey);
|
|
||||||
if (comment != null) return comment;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public @Nullable String getInlineComment(@NotNull String key, @Nullable String sectionKey) {
|
|
||||||
Map<String, String> pathComment = holder().metadata(key).get(CommentableMeta.INLINE);
|
|
||||||
if (pathComment == null || pathComment.isEmpty()) return null;
|
|
||||||
if (sectionKey == null) return pathComment.get(null);
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : pathComment.entrySet()) {
|
|
||||||
if (entry.getKey().equals(sectionKey)) return entry.getValue();
|
|
||||||
Pattern pattern = Pattern.compile(entry.getKey().replace(".", "\\.").replace("*", ".*"));
|
|
||||||
if (pattern.matcher(sectionKey).matches()) return entry.getValue();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable List<String> getHeaderComments(@Nullable String key) {
|
public @Nullable List<String> getHeaderComments(@Nullable String key) {
|
||||||
return holder().metadata(key).get(CommentableMeta.HEADER);
|
return Commentable.getHeaderComments(holder(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @Nullable List<String> getFooterComments(@Nullable String key) {
|
public @Nullable List<String> getFooterComments(@Nullable String key) {
|
||||||
return holder().metadata(key).get(CommentableMeta.FOOTER);
|
return Commentable.getFooterComments(holder(), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class YamlRepresenter extends Representer {
|
public static class YamlRepresenter extends Representer {
|
||||||
|
|||||||
@@ -4,17 +4,19 @@ import cc.carm.lib.configuration.commentable.CommentableMeta;
|
|||||||
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
import cc.carm.lib.configuration.demo.tests.ConfigurationTest;
|
||||||
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
import cc.carm.lib.configuration.source.ConfigurationHolder;
|
||||||
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
import cc.carm.lib.configuration.source.yaml.YAMLConfigFactory;
|
||||||
|
import cc.carm.lib.configuration.source.yaml.YAMLSource;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class YamlTests {
|
public class YamlTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
|
|
||||||
ConfigurationHolder<?> holder = YAMLConfigFactory.from("target/tests.yml")
|
ConfigurationHolder<YAMLSource> holder = YAMLConfigFactory.from("target/tests.yml")
|
||||||
.resourcePath("configs/sample.yml").build();
|
.resourcePath("configs/sample.yml").build();
|
||||||
|
|
||||||
ConfigurationTest.testDemo(holder);
|
ConfigurationTest.testDemo(holder);
|
||||||
|
|||||||
Reference in New Issue
Block a user