1
mirror of https://github.com/CarmJos/EasyConfiguration.git synced 2026-06-04 18:48:20 +08:00

Compare commits

...

12 Commits

Author SHA1 Message Date
carm c2a08c6c72 Merge remote-tracking branch 'origin/master' 2022-04-22 12:57:21 +08:00
carm dd7a6c819f [2.1.0] 实现JSON版本的数据格式 2022-04-22 12:57:10 +08:00
carm e9c010981e Merge pull request #3 from CarmJos/dependabot/maven/org.apache.maven.plugins-maven-javadoc-plugin-3.4.0
Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
2022-04-22 01:24:28 +08:00
dependabot[bot] 78d52e1aae Bump maven-javadoc-plugin from 3.3.2 to 3.4.0
Bumps [maven-javadoc-plugin](https://github.com/apache/maven-javadoc-plugin) from 3.3.2 to 3.4.0.
- [Release notes](https://github.com/apache/maven-javadoc-plugin/releases)
- [Commits](https://github.com/apache/maven-javadoc-plugin/compare/maven-javadoc-plugin-3.3.2...maven-javadoc-plugin-3.4.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-javadoc-plugin
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-21 14:35:46 +00:00
carm 42ccc23347 更新版本号 2022-04-21 21:56:45 +08:00
carm 85578e3d8c 修改项目介绍 2022-04-21 19:10:24 +08:00
carm dc4d3664d3 修改项目介绍 2022-04-21 19:09:03 +08:00
carm 2e4cb5480a [1.2.0] 版本更新
- `[R]` 独立 bungee 和 bukkit 平台版本到 MineConfiguration 项目。
- `[U]` 重写Initializer逻辑,并支持根据成员变量顺序加载配置文件。
2022-04-21 18:55:56 +08:00
carm 4b7a7aeae7 完成新Initializer,以支持配置文件内容的顺序加载。 2022-04-21 06:40:32 +08:00
carm 132ca81635 放弃Unsafe包操作 2022-04-19 23:20:40 +08:00
carm 80747ac922 测试Unsafe包操作 2022-04-19 21:43:49 +08:00
carm 0d10a06547 测试抽象类继承获取 2022-04-18 22:38:49 +08:00
59 changed files with 951 additions and 2495 deletions
+5 -51
View File
@@ -97,43 +97,6 @@
</details>
<details>
<summary>平台依赖版本</summary>
**基于Spigot实现的版本**
```xml
<project>
<dependencies>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-spigot</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
```
**基于Bungee实现的版本 (不支持自动注释)**
```xml
<project>
<dependencies>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-bungee</artifactId>
<version>[LATEST RELEASE]</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
```
</details>
#### Gradle 依赖
<details>
@@ -173,24 +136,15 @@ dependencies {
</details>
<details>
<summary>平台依赖版本</summary>
## 衍生项目
```groovy
### [**MineConfiguration**](https://github.com/CarmJos/MineConfiguration) (by @CarmJos )
dependencies {
EasyConfiguration for MineCraft!
开始在 MineCraft 相关服务器平台上轻松(做)配置吧!
// 用于Spigot服务端的版本
api "cc.carm.lib:easyconfiguration-spigot:[LATEST RELEASE]"
目前支持 BungeeCord, Bukkit(Spigot) 服务端,后续将支持更多平台。
// 用于BungeeCord服务端的版本,不支持注解。
// 如需注解,可选择使用 `easyconfiguration-yaml` 并打包。
api "cc.carm.lib:easyconfiguration-bungee:[LATEST RELEASE]"
}
```
</details>
## 支持与捐赠
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>easyconfiguration-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>1.1.0</version>
<version>2.1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
@@ -8,8 +8,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Optional;
public class ConfigInitializer<T extends ConfigurationProvider<?>> {
@@ -19,94 +17,116 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
this.provider = provider;
}
public void initialize(Class<? extends ConfigurationRoot> rootClazz) {
initialize(rootClazz, true);
public void initialize(@NotNull Class<? extends ConfigurationRoot> clazz, boolean saveDefaults) {
initializeClass(clazz, null, null, null, null, saveDefaults);
}
public void initialize(Class<? extends ConfigurationRoot> rootClazz, boolean saveDefault) {
String rootSection = null;
ConfigPath sectionAnnotation = rootClazz.getAnnotation(ConfigPath.class);
if (sectionAnnotation != null && sectionAnnotation.value().length() > 1) {
rootSection = sectionAnnotation.value();
protected void initializeClass(@NotNull Class<?> clazz,
@Nullable String parentPath, @Nullable String fieldName,
@Nullable ConfigPath fieldPath, @Nullable ConfigComment filedComments,
boolean saveDefaults) {
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return;
String path = getClassPath(clazz, parentPath, fieldName, fieldPath);
if (path != null) setComments(path, getClassComments(clazz, filedComments));
for (Field field : clazz.getDeclaredFields()) {
initializeField(clazz, field, path, saveDefaults);
}
if (rootSection != null) {
//Not usable for null section.
ConfigComment comments = rootClazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(rootSection, comments.value());
}
}
for (Class<?> innerClass : rootClazz.getDeclaredClasses()) {
initSection(rootSection, innerClass, saveDefault);
}
for (Field field : rootClazz.getDeclaredFields()) {
initValue(rootSection, rootClazz, field, saveDefault);
}
if (saveDefault) {
try {
provider.save();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void initSection(String parentSection, Class<?> clazz, boolean saveDefault) {
if (!Modifier.isStatic(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers())) return;
String section = getSectionPath(clazz.getSimpleName(), parentSection, clazz.getAnnotation(ConfigPath.class));
ConfigComment comments = clazz.getAnnotation(ConfigComment.class);
if (comments != null && comments.value().length > 0) {
provider.setComments(parentSection, comments.value());
}
for (Field field : clazz.getDeclaredFields()) initValue(section, clazz, field, saveDefault);
for (Class<?> innerClass : clazz.getDeclaredClasses()) initSection(section, innerClass, saveDefault);
protected void initializeValue(@NotNull ConfigValue<?> value, @NotNull String path,
@NotNull String[] comments, boolean saveDefaults) {
value.initialize(provider, saveDefaults, path, comments);
}
private void initValue(String parentSection, Class<?> clazz, Field field, boolean saveDefault) {
private void initializeField(@NotNull Class<?> source, @NotNull Field field,
@Nullable String parent, boolean saveDefaults) {
try {
field.setAccessible(true);
Object object = field.get(clazz);
Object object = field.get(source);
if (object instanceof ConfigValue<?>) {
initializeValue(
(ConfigValue<?>) object, saveDefault,
getSectionPath(field.getName(), parentSection, field.getAnnotation(ConfigPath.class)),
Optional.ofNullable(field.getAnnotation(ConfigComment.class))
.map(ConfigComment::value).orElse(new String[0])
String path = getFieldPath(field, parent);
String[] comments = readComments(field.getAnnotation(ConfigComment.class));
initializeValue((ConfigValue<?>) object, path, comments, saveDefaults);
setComments(path, comments);
} else if (object instanceof Class<?>) {
initializeClass(
(Class<?>) object, parent, field.getName(),
field.getAnnotation(ConfigPath.class),
field.getAnnotation(ConfigComment.class),
saveDefaults
);
}
} catch (IllegalAccessException ignored) {
}
}
public void initializeValue(@NotNull ConfigValue<?> value, boolean saveDefault,
@NotNull String path, @NotNull String[] comments) {
value.initialize(provider, path, comments);
if (saveDefault && value.getDefaultValue() != null && !provider.getConfiguration().contains(path)) {
value.setDefault();
}
protected void setComments(@NotNull String path, @Nullable ConfigComment filedComments) {
setComments(path, readComments(filedComments));
}
public static String getSectionPath(@NotNull String name,
@Nullable String parentSection,
@Nullable ConfigPath pathAnnotation) {
@NotNull String parent = parentSection != null ? parentSection + "." : "";
@NotNull String path = getSectionName(name);
boolean root = false;
if (pathAnnotation != null) {
if (pathAnnotation.value().length() > 0) path = pathAnnotation.value();
root = pathAnnotation.root();
protected void setComments(@NotNull String path, @NotNull String[] comments) {
if (comments.length <= 0) return;
this.provider.setComments(path, comments);
}
protected static @NotNull String[] readComments(@Nullable ConfigComment filedComments) {
if (filedComments == null) return new String[0];
if (String.join("", filedComments.value()).length() <= 0) return new String[0];
return filedComments.value();
}
protected static @NotNull String[] getClassComments(@NotNull Class<?> clazz,
@Nullable ConfigComment fieldAnnotation) {
String[] clazzComments = readComments(clazz.getAnnotation(ConfigComment.class));
if (clazzComments.length > 0) return clazzComments;
else return readComments(fieldAnnotation);
}
protected static @Nullable String getClassPath(@NotNull Class<?> clazz,
@Nullable String parentPath,
@Nullable String filedName,
@Nullable ConfigPath fieldAnnotation) {
@NotNull String parent = parentPath != null ? parentPath + "." : "";
boolean fromRoot = false;
// 先获取 Class 对应的路径注解 其优先度最高。
ConfigPath clazzAnnotation = clazz.getAnnotation(ConfigPath.class);
if (clazzAnnotation != null) {
fromRoot = clazzAnnotation.root();
if (clazzAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + clazzAnnotation.value();
}
}
return (root ? "" : parent) + path;
if (fieldAnnotation != null) {
fromRoot = fromRoot || fieldAnnotation.root();
if (fieldAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + fieldAnnotation.value();
}
}
// 再由 fieldName 获取路径
if (filedName != null) return (fromRoot ? "" : parent) + getPathFromName(filedName);
else return null; // 不满足上述条件 且 无 fieldName,则说明是根路径。
}
protected static @NotNull String getFieldPath(@NotNull Field field, @Nullable String parentPath) {
@NotNull String parent = parentPath != null ? parentPath + "." : "";
boolean fromRoot = false;
// 先获取 Field 对应的路径注解 其优先度最高。
ConfigPath pathAnnotation = field.getAnnotation(ConfigPath.class);
if (pathAnnotation != null) {
fromRoot = pathAnnotation.root();
if (pathAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + pathAnnotation.value();
}
}
// 最后再通过 fieldName 自动生成路径
return (fromRoot ? "" : parent) + getPathFromName(field.getName());
}
/**
@@ -116,7 +136,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
* @param name 源名称
* @return 全小写,以“-”链接 的 路径名称
*/
public static String getSectionName(String name) {
public static String getPathFromName(String name) {
return name.replaceAll("[A-Z]", "-$0") // 将驼峰转换为蛇形;
.replaceAll("-(.*)", "$1") // 若首字母也为大写,则也会被转换,需要去掉第一个横线
.replaceAll("_-([A-Z])", "_$1") // 因为命名中可能包含 _,因此需要被特殊处理一下
@@ -16,7 +16,7 @@ public @interface ConfigPath {
/**
* 指定路径的值。
* 若不指定,则会通过 {@link ConfigInitializer#getSectionName(String)}自动生成当前路径的值。
* 若不指定,则会通过 {@link ConfigInitializer#getPathFromName(String)} 自动生成当前路径的值。
*
* @return 路径的值
*/
@@ -31,7 +31,7 @@ public class ConfigListBuilder<V> {
return from(
Object.class, ConfigDataFunction.identity(),
ConfigDataFunction.castObject(valueClass),
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
ConfigDataFunction.toObject(), ConfigDataFunction.toObject()
);
}
@@ -46,7 +46,7 @@ public class ConfigValueBuilder<V> {
return from(
Object.class, ConfigDataFunction.identity(),
ConfigValueParser.castObject(valueClass),
ConfigDataFunction.identity(), ConfigDataFunction.toObject()
ConfigDataFunction.toObject(), ConfigDataFunction.toObject()
);
}
@@ -17,7 +17,12 @@ public interface ConfigDataFunction<T, R> {
}
@Contract(pure = true)
static <T> @NotNull ConfigDataFunction<T, ? super T> identity() {
static <T> @NotNull ConfigDataFunction<T, T> identity() {
return (input) -> input;
}
@Contract(pure = true)
static <T> @NotNull ConfigDataFunction<T, T> identity(Class<T> type) {
return (input) -> input;
}
@@ -33,7 +38,6 @@ public interface ConfigDataFunction<T, R> {
return (input) -> input;
}
@Contract(pure = true)
static <V> @NotNull ConfigDataFunction<Object, V> castObject(Class<V> valueClass) {
return (input) -> {
@@ -34,7 +34,11 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper> {
public abstract @NotNull ConfigInitializer<? extends ConfigurationProvider<W>> getInitializer();
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
getInitializer().initialize(configClazz, true);
initialize(configClazz, true);
}
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
getInitializer().initialize(configClazz, saveDefaults);
}
}
@@ -29,13 +29,12 @@ public abstract class ConfigValue<T> {
this.defaultValue = defaultValue;
}
public void initialize(@NotNull ConfigurationProvider<?> provider, @NotNull String configPath, @NotNull String... comments) {
public void initialize(@NotNull ConfigurationProvider<?> provider, boolean saveDefault,
@NotNull String configPath, @NotNull String... comments) {
if (this.provider == null) this.provider = provider;
if (this.configPath == null) this.configPath = configPath;
if (this.comments.length == 0) this.comments = comments;
this.provider.setComments(this.configPath, this.comments);
get();
if (saveDefault) setDefault();
}
public @Nullable T getDefaultValue() {
@@ -63,6 +62,11 @@ public abstract class ConfigValue<T> {
public abstract void set(@Nullable T value);
public void setDefault() {
setDefault(false);
}
public void setDefault(boolean override) {
if (!override && getConfiguration().contains(getConfigPath())) return;
Optional.ofNullable(getDefaultValue()).ifPresent(this::set);
}
+4 -4
View File
@@ -7,10 +7,10 @@ public class NameTest {
@Test
public void onTest() {
System.out.println(ConfigInitializer.getSectionName("LoveGames")); // -> love-games
System.out.println(ConfigInitializer.getSectionName("EASY_GAME")); // -> easy-game
System.out.println(ConfigInitializer.getSectionName("F")); //-? f
System.out.println(ConfigInitializer.getSectionName("Test123123")); // -? test123123123
System.out.println(ConfigInitializer.getPathFromName("LoveGames")); // -> love-games
System.out.println(ConfigInitializer.getPathFromName("EASY_GAME")); // -> easy-game
System.out.println(ConfigInitializer.getPathFromName("F")); //-? f
System.out.println(ConfigInitializer.getPathFromName("Test123123")); // -? test123123123
}
@@ -5,7 +5,7 @@
<parent>
<artifactId>easyconfiguration-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>1.1.0</version>
<version>2.1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -13,8 +13,7 @@
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<artifactId>easyconfiguration-spigot</artifactId>
<artifactId>easyconfiguration-json</artifactId>
<packaging>jar</packaging>
<dependencies>
@@ -27,10 +26,10 @@
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.18.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
@@ -56,5 +55,4 @@
</plugins>
</build>
</project>
@@ -1,14 +1,14 @@
package cc.carm.lib.configuration;
import cc.carm.lib.configuration.bungee.BungeeConfigProvider;
import cc.carm.lib.configuration.json.JSONConfigProvider;
import java.io.File;
import java.io.IOException;
public class EasyConfiguration {
public static BungeeConfigProvider from(File file, String source) {
BungeeConfigProvider provider = new BungeeConfigProvider(file);
public static JSONConfigProvider from(File file, String source) {
JSONConfigProvider provider = new JSONConfigProvider(file);
try {
provider.initializeFile(source);
provider.initializeConfig();
@@ -18,17 +18,16 @@ public class EasyConfiguration {
return provider;
}
public static BungeeConfigProvider from(File file) {
public static JSONConfigProvider from(File file) {
return from(file, file.getName());
}
public static BungeeConfigProvider from(String fileName) {
public static JSONConfigProvider from(String fileName) {
return from(fileName, fileName);
}
public static BungeeConfigProvider from(String fileName, String source) {
public static JSONConfigProvider from(String fileName, String source) {
return from(new File(fileName), source);
}
}
@@ -0,0 +1,85 @@
package cc.carm.lib.configuration.json;
import cc.carm.lib.configuration.core.ConfigInitializer;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSerializer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap;
/**
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
*
* @author md_5, CarmJos
*/
public class JSONConfigProvider extends FileConfigProvider<JSONConfigWrapper> {
protected final Gson gson = new GsonBuilder()
.serializeNulls().disableHtmlEscaping().setPrettyPrinting()
.registerTypeAdapter(
JSONConfigWrapper.class,
(JsonSerializer<JSONConfigWrapper>) (src, typeOfSrc, context) -> context.serialize(src.data)
).create();
protected JSONConfigWrapper configuration;
protected ConfigInitializer<JSONConfigProvider> initializer;
public JSONConfigProvider(@NotNull File file) {
super(file);
this.initializer = new ConfigInitializer<>(this);
}
public void initializeConfig() {
LinkedHashMap<?, ?> map = null;
try (FileInputStream is = new FileInputStream(file)) {
map = gson.fromJson(new InputStreamReader(is, StandardCharsets.UTF_8), LinkedHashMap.class);
} catch (IOException e) {
e.printStackTrace();
}
if (map == null) map = new LinkedHashMap<>();
this.configuration = new JSONConfigWrapper(map);
this.initializer = new ConfigInitializer<>(this);
}
@Override
public @NotNull JSONConfigWrapper getConfiguration() {
return this.configuration;
}
@Override
public void reload() {
initializeConfig();
}
@Override
public void save() throws Exception {
try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
gson.toJson(configuration.data, writer);
}
}
@Override
public void setComments(@NotNull String path, @NotNull String... comments) {
// JSON doesn't support comments.
}
@Override
public @Nullable String[] getComments(@NotNull String path) {
return new String[0]; // JSON doesn't support comments.
}
@Override
public @NotNull ConfigInitializer<? extends ConfigurationProvider<JSONConfigWrapper>> getInitializer() {
return this.initializer;
}
}
@@ -0,0 +1,114 @@
package cc.carm.lib.configuration.json;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* Some code comes from BungeeCord's implementation of the JsonConfiguration.
*
* @author md_5, CarmJos
*/
public class JSONConfigWrapper implements ConfigurationWrapper {
private static final char SEPARATOR = '.';
protected final Map<String, Object> data;
JSONConfigWrapper(Map<?, ?> map) {
this.data = new LinkedHashMap<>();
for (Map.Entry<?, ?> entry : map.entrySet()) {
String key = (entry.getKey() == null) ? "null" : entry.getKey().toString();
if (entry.getValue() instanceof Map) {
this.data.put(key, new JSONConfigWrapper((Map<?, ?>) entry.getValue()));
} else {
this.data.put(key, entry.getValue());
}
}
}
@Override
public @NotNull Set<String> getKeys(boolean deep) {
return new LinkedHashSet<>(this.data.keySet());
}
@Override
public @NotNull Map<String, Object> getValues(boolean deep) {
return new LinkedHashMap<>(this.data);
}
@Override
public void set(@NotNull String path, @Nullable Object value) {
if (value instanceof Map) {
value = new JSONConfigWrapper((Map<?, ?>) value);
}
JSONConfigWrapper section = getSectionFor(path);
if (section == this) {
if (value == null) {
this.data.remove(path);
} else {
this.data.put(path, value);
}
} else {
section.set(getChild(path), value);
}
}
@Override
public boolean contains(@NotNull String path) {
return get(path) != null;
}
@Override
public @Nullable Object get(@NotNull String path) {
JSONConfigWrapper section = getSectionFor(path);
return section == this ? data.get(path) : section.get(getChild(path));
}
@Override
public boolean isList(@NotNull String path) {
return get(path) instanceof List<?>;
}
@Override
public @Nullable List<?> getList(@NotNull String path) {
Object val = get(path);
return (val instanceof List<?>) ? (List<?>) val : null;
}
@Override
public boolean isConfigurationSection(@NotNull String path) {
return get(path) instanceof JSONConfigWrapper;
}
@Override
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
Object val = get(path);
return (val instanceof JSONConfigWrapper) ? (JSONConfigWrapper) val : null;
}
private JSONConfigWrapper getSectionFor(String path) {
int index = path.indexOf(SEPARATOR);
if (index == -1) return this;
String root = path.substring(0, index);
Object section = this.data.get(root);
if (section == null) {
section = new JSONConfigWrapper(new LinkedHashMap<>());
this.data.put(root, section);
}
return (JSONConfigWrapper) section;
}
private String getChild(String path) {
int index = path.indexOf(SEPARATOR);
return (index == -1) ? path : path.substring(index + 1);
}
}
@@ -0,0 +1,4 @@
package cc.carm.lib.configuration.json;
public abstract class JSONValue {
}
@@ -0,0 +1,63 @@
package config;
import cc.carm.lib.configuration.EasyConfiguration;
import cc.carm.lib.configuration.json.JSONConfigProvider;
import config.model.TestModel;
import config.source.DemoConfiguration;
import org.junit.Test;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class JSONConfigTest {
protected final JSONConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
@Test
public void onTest() {
provider.initialize(DemoConfiguration.class);
testDemo();
try {
provider.save();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void testDemo() {
System.out.println("----------------------------------------------------");
System.out.println("> Test Value:");
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
System.out.println("> Test List:");
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
DemoConfiguration.Sub.That.OPERATORS.set(operators);
System.out.println("> Test Section:");
System.out.println(DemoConfiguration.MODEL_TEST.get());
DemoConfiguration.MODEL_TEST.set(TestModel.random());
System.out.println("> Test Maps:");
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
for (int i = 1; i <= 5; i++) {
data.put(i, UUID.randomUUID());
}
DemoConfiguration.USERS.set(data);
System.out.println("----------------------------------------------------");
}
}
@@ -0,0 +1,16 @@
package config.model;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractModel {
protected final @NotNull String name;
public AbstractModel(@NotNull String name) {
this.name = name;
}
public @NotNull String getName() {
return name;
}
}
@@ -0,0 +1,39 @@
package config.model;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import java.util.HashMap;
import java.util.Map;
public class SomeModel extends AbstractModel {
int num;
public SomeModel(@NotNull String name, int num) {
super(name);
this.num = num;
}
@Override
public String toString() {
return "SomeModel{" +
"name='" + name + '\'' +
", num=" + num +
'}';
}
public @NotNull Map<String, Object> serialize() {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("num", num);
return map;
}
@TestOnly
public static SomeModel deserialize(Map<String, ?> args) {
return new SomeModel((String) args.get("name"), (Integer) args.get("num"));
}
}
@@ -0,0 +1,56 @@
package config.model;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class TestModel extends AbstractModel {
public UUID uuid;
public TestModel(String name, UUID uuid) {
super(name);
this.uuid = uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public UUID getUuid() {
return uuid;
}
public @NotNull Map<String, Object> serialize() {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
Map<String, Object> map2 = new HashMap<>();
map2.put("uuid", uuid.toString());
map.put("info", map2);
return map;
}
public static TestModel deserialize(ConfigurationWrapper section) {
String name = section.getString("name");
if (name == null) throw new NullPointerException("name is null");
String uuidString = section.getString("info.uuid");
if (uuidString == null) throw new NullPointerException("uuid is null");
return new TestModel(name, UUID.fromString(uuidString));
}
public static TestModel random() {
return new TestModel(UUID.randomUUID().toString().substring(0, 5), UUID.randomUUID());
}
@Override
public String toString() {
return "TestUser{" +
"name='" + name + '\'' +
", uuid=" + uuid +
'}';
}
}
@@ -0,0 +1,35 @@
package config.source;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
@ConfigComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
public class DatabaseConfiguration extends ConfigurationRoot {
@ConfigPath("driver")
@ConfigComment({
"数据库驱动配置,请根据数据库类型设置。",
"- MySQL: com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
})
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver"
);
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
}
}
@@ -15,15 +15,31 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
public class ComplexConfiguration extends ConfigurationRoot {
public class DemoConfiguration extends ConfigurationRoot {
@ConfigComment({"User测试"})
public static final ConfigValue<TestModel> USER = ConfiguredSection
@ConfigPath(root = true)
@ConfigComment({
"有时候,需要在配置文件最上面显示点东西,",
"此时就推荐添加一个可以用到但并不重要的参数到最上面",
"并给他添加对应的注释。"
})
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
// 可以直接写静态内部类并通过 Class<?> 声明
public static final Class<?> SUB_TEST = Sub.class;
@ConfigPath("user") // 通过注解规定配置文件中的路径若不进行注解则以变量名自动生成
@ConfigComment({"Section类型数据测试"}) // 通过注解给配置添加注释
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
.builder(TestModel.class)
.defaults(new TestModel("Carm", UUID.randomUUID()))
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
.serializeValue(TestModel::serialize).build();
// 子配置文件
@ConfigPath("database")
public static final Class<?> DB_CONFIG = DatabaseConfiguration.class;
@ConfigComment({"[ID-UUID] 对照表", "", "用于测试Map类型的解析与序列化保存"})
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
.builder(Integer.class, UUID.class).fromString()
@@ -31,25 +47,26 @@ public class ComplexConfiguration extends ConfigurationRoot {
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
.build();
public static class Sub {
@ConfigPath(value = "uuid", root = true)
public static class Sub extends ConfigurationRoot {
@ConfigPath(value = "uuid-value", root = true)
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
.builder(UUID.class).fromString()
.parseValue((data, defaultValue) -> UUID.fromString(data))
.build();
@ConfigPath("nothing")
public static class That {
public static final Class<?> NOTHING = That.class;
public static final ConfigValue<List<UUID>> Operators = ConfiguredList
public static class That extends ConfigurationRoot {
public static final ConfigValue<List<UUID>> OPERATORS = ConfiguredList
.builder(UUID.class).fromString()
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
.build();
}
}
+1 -1
View File
@@ -5,7 +5,7 @@
<parent>
<artifactId>easyconfiguration-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>1.1.0</version>
<version>2.1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -1,14 +1,14 @@
package cc.carm.lib.configuration;
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
import java.io.File;
import java.io.IOException;
public class EasyConfiguration {
public static YamlConfigProvider from(File file, String source) {
YamlConfigProvider provider = new YamlConfigProvider(file);
public static YAMLConfigProvider from(File file, String source) {
YAMLConfigProvider provider = new YAMLConfigProvider(file);
try {
provider.initializeFile(source);
provider.initializeConfig();
@@ -18,15 +18,15 @@ public class EasyConfiguration {
return provider;
}
public static YamlConfigProvider from(File file) {
public static YAMLConfigProvider from(File file) {
return from(file, file.getName());
}
public static YamlConfigProvider from(String fileName) {
public static YAMLConfigProvider from(String fileName) {
return from(fileName, fileName);
}
public static YamlConfigProvider from(String fileName, String source) {
public static YAMLConfigProvider from(String fileName, String source) {
return from(new File(fileName), source);
}
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class YamlComments implements CommentsProvider {
public class YAMLComments implements CommentsProvider {
Map<String, String[]> comments = new HashMap<>();
@@ -8,13 +8,13 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
public class YamlConfigProvider extends FileConfigProvider<YamlSectionWrapper> {
public class YAMLConfigProvider extends FileConfigProvider<YAMLSectionWrapper> {
protected final @NotNull YamlComments comments = new YamlComments();
protected final @NotNull YAMLComments comments = new YAMLComments();
protected CommentedYamlConfiguration configuration;
protected ConfigInitializer<YamlConfigProvider> initializer;
protected ConfigInitializer<YAMLConfigProvider> initializer;
public YamlConfigProvider(@NotNull File file) {
public YAMLConfigProvider(@NotNull File file) {
super(file);
}
@@ -24,8 +24,8 @@ public class YamlConfigProvider extends FileConfigProvider<YamlSectionWrapper> {
}
@Override
public @NotNull YamlSectionWrapper getConfiguration() {
return YamlSectionWrapper.of(configuration);
public @NotNull YAMLSectionWrapper getConfiguration() {
return YAMLSectionWrapper.of(configuration);
}
@Override
@@ -49,7 +49,7 @@ public class YamlConfigProvider extends FileConfigProvider<YamlSectionWrapper> {
}
@Override
public @NotNull ConfigInitializer<YamlConfigProvider> getInitializer() {
public @NotNull ConfigInitializer<YAMLConfigProvider> getInitializer() {
return this.initializer;
}
@@ -12,17 +12,17 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
public class YamlSectionWrapper implements ConfigurationWrapper {
public class YAMLSectionWrapper implements ConfigurationWrapper {
private final ConfigurationSection section;
private YamlSectionWrapper(ConfigurationSection section) {
private YAMLSectionWrapper(ConfigurationSection section) {
this.section = section;
}
@Contract("!null->!null")
public static @Nullable YamlSectionWrapper of(@Nullable ConfigurationSection section) {
return section == null ? null : new YamlSectionWrapper(section);
public static @Nullable YAMLSectionWrapper of(@Nullable ConfigurationSection section) {
return section == null ? null : new YAMLSectionWrapper(section);
}
@Override
@@ -2,30 +2,28 @@ package cc.carm.lib.configuration.yaml;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import cc.carm.lib.configuration.yaml.YamlSectionWrapper;
import cc.carm.lib.configuration.yaml.builder.YamlConfigBuilder;
import cc.carm.lib.configuration.yaml.builder.YAMLConfigBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class YAMLValue<T> extends CachedConfigValue<T> {
public static @NotNull YamlConfigBuilder builder() {
return new YamlConfigBuilder();
public static @NotNull YAMLConfigBuilder builder() {
return new YAMLConfigBuilder();
}
public YAMLValue(@Nullable YamlConfigProvider provider,
public YAMLValue(@Nullable YAMLConfigProvider provider,
@Nullable String configPath, @NotNull String[] comments, @Nullable T defaultValue) {
super(provider, configPath, comments, defaultValue);
}
public YamlConfigProvider getYAMLProvider() {
public YAMLConfigProvider getYAMLProvider() {
ConfigurationProvider<?> provider = getProvider();
if (provider instanceof YamlConfigProvider) return (YamlConfigProvider) getProvider();
else throw new IllegalStateException("Provider is not a SpigotConfigProvider");
if (provider instanceof YAMLConfigProvider) return (YAMLConfigProvider) getProvider();
else throw new IllegalStateException("Provider is not a YamlConfigProvider");
}
public YamlSectionWrapper getYAMLConfig() {
public YAMLSectionWrapper getYAMLConfig() {
return getYAMLProvider().getConfiguration();
}
@@ -1,13 +1,13 @@
package cc.carm.lib.configuration.yaml.builder;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
public abstract class AbstractYAMLBuilder<T, B extends AbstractYAMLBuilder<T, B>>
extends AbstractConfigBuilder<T, B, YamlConfigProvider> {
extends AbstractConfigBuilder<T, B, YAMLConfigProvider> {
public AbstractYAMLBuilder() {
super(YamlConfigProvider.class);
super(YAMLConfigProvider.class);
}
}
@@ -5,7 +5,7 @@ import cc.carm.lib.configuration.yaml.builder.serializable.SerializableBuilder;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
public class YamlConfigBuilder extends ConfigBuilder {
public class YAMLConfigBuilder extends ConfigBuilder {
public <V extends ConfigurationSerializable> @NotNull SerializableBuilder<V> ofSerializable(@NotNull Class<V> valueClass) {
return new SerializableBuilder<>(valueClass);
@@ -1,7 +1,7 @@
package cc.carm.lib.configuration.yaml.value;
import cc.carm.lib.configuration.yaml.YAMLValue;
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -15,13 +15,13 @@ public class ConfiguredSerializable<T extends ConfigurationSerializable> extends
}
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass,
@Nullable V defaultValue) {
@Nullable V defaultValue) {
return builder().ofSerializable(valueClass).defaults(defaultValue).build();
}
protected final @NotNull Class<T> valueClass;
public ConfiguredSerializable(@Nullable YamlConfigProvider provider,
public ConfiguredSerializable(@Nullable YAMLConfigProvider provider,
@Nullable String configPath, @NotNull String[] comments,
@NotNull Class<T> valueClass, @Nullable T defaultValue) {
super(provider, configPath, comments, defaultValue);
@@ -1,9 +1,10 @@
package config;
import cc.carm.lib.configuration.EasyConfiguration;
import cc.carm.lib.configuration.yaml.YamlConfigProvider;
import cc.carm.lib.configuration.yaml.YAMLConfigProvider;
import config.model.AbstractModel;
import config.model.SomeModel;
import config.model.TestModel;
import config.source.ComplexConfiguration;
import config.source.DemoConfiguration;
import config.source.ImplConfiguration;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerialization;
@@ -17,16 +18,19 @@ import java.util.stream.IntStream;
public class ConfigTester {
static {
ConfigurationSerialization.registerClass(TestModel.class);
ConfigurationSerialization.registerClass(SomeModel.class);
}
protected final YAMLConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
@Test
public void onTest() {
ConfigurationSerialization.registerClass(TestModel.class);
provider.initialize(DemoConfiguration.class);
YamlConfigProvider provider = EasyConfiguration.from("target/config.yml", "config.yml");
testDemo(provider);
testComplex(provider);
testSerialization(provider);
testDemo();
testSerialization();
try {
provider.save();
@@ -36,43 +40,40 @@ public class ConfigTester {
}
public static void testSerialization(YamlConfigProvider provider) {
System.out.println("----------------------------------------------------");
provider.initialize(ImplConfiguration.class);
System.out.println(ImplConfiguration.TEST.get());
ImplConfiguration.TEST.set(TestModel.random());
System.out.println("----------------------------------------------------");
}
public static void testDemo(YamlConfigProvider provider) {
provider.initialize(DemoConfiguration.class);
}
public static void testComplex(YamlConfigProvider provider) {
public static void testDemo() {
System.out.println("----------------------------------------------------");
provider.initialize(ComplexConfiguration.class);
System.out.println("> Test Value:");
System.out.println("before: " + ComplexConfiguration.Sub.UUID_CONFIG_VALUE.get());
ComplexConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
System.out.println("after: " + ComplexConfiguration.Sub.UUID_CONFIG_VALUE.get());
System.out.println("before: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
DemoConfiguration.Sub.UUID_CONFIG_VALUE.set(UUID.randomUUID());
System.out.println("after: " + DemoConfiguration.Sub.UUID_CONFIG_VALUE.get());
System.out.println("> Test List:");
ComplexConfiguration.Sub.That.Operators.getNotNull().forEach(System.out::println);
DemoConfiguration.Sub.That.OPERATORS.getNotNull().forEach(System.out::println);
List<UUID> operators = IntStream.range(0, 5).mapToObj(i -> UUID.randomUUID()).collect(Collectors.toList());
ComplexConfiguration.Sub.That.Operators.set(operators);
DemoConfiguration.Sub.That.OPERATORS.set(operators);
System.out.println("> Test Section:");
System.out.println(ComplexConfiguration.USER.get());
ComplexConfiguration.USER.set(TestModel.random());
System.out.println(DemoConfiguration.MODEL_TEST.get());
DemoConfiguration.MODEL_TEST.set(TestModel.random());
System.out.println("> Test Maps:");
ComplexConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
DemoConfiguration.USERS.getNotNull().forEach((k, v) -> System.out.println(k + ": " + v));
LinkedHashMap<Integer, UUID> data = new LinkedHashMap<>();
for (int i = 0; i < 5; i++) {
data.put((int) (1000 * Math.random()), UUID.randomUUID());
for (int i = 1; i <= 5; i++) {
data.put(i, UUID.randomUUID());
}
DemoConfiguration.USERS.set(data);
System.out.println("----------------------------------------------------");
}
public static void testSerialization() {
System.out.println("----------------------------------------------------");
AbstractModel model = ImplConfiguration.TEST.get();
if (model != null) {
System.out.println(model.getName());
}
ComplexConfiguration.USERS.set(data);
System.out.println("----------------------------------------------------");
}
@@ -0,0 +1,26 @@
package config;
import config.offset.FieldOffset;
import config.offset.OffsetUtil;
import config.source.DemoConfiguration;
import org.junit.Test;
import java.util.List;
public class OffsetTest {
@Test
public void test() {
//
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.class));
// output(OffsetUtil.getClassMemberOffset(DemoConfiguration.Sub.class));
}
protected static void output(List<FieldOffset> fieldOffsets) {
for (FieldOffset fieldOffset : fieldOffsets) {
System.out.println(fieldOffset.getOffsetValue() + " -> " + fieldOffset);
}
}
}
@@ -0,0 +1,17 @@
package config.model;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractModel implements ConfigurationSerializable {
protected final @NotNull String name;
public AbstractModel(@NotNull String name) {
this.name = name;
}
public @NotNull String getName() {
return name;
}
}
@@ -0,0 +1,43 @@
package config.model;
import org.bspfsystems.yamlconfiguration.serialization.ConfigurationSerializable;
import org.bspfsystems.yamlconfiguration.serialization.SerializableAs;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import java.util.HashMap;
import java.util.Map;
@SerializableAs("SomeModel")
public class SomeModel extends AbstractModel implements ConfigurationSerializable {
int num;
public SomeModel(@NotNull String name, int num) {
super(name);
this.num = num;
}
@Override
public String toString() {
return "SomeModel{" +
"name='" + name + '\'' +
", num=" + num +
'}';
}
@Override
public @NotNull Map<String, Object> serialize() {
Map<String, Object> map = new HashMap<>();
map.put("name", name);
map.put("num", num);
return map;
}
@TestOnly
public static SomeModel deserialize(Map<String, ?> args) {
return new SomeModel((String) args.get("name"), (Integer) args.get("num"));
}
}
@@ -11,28 +11,19 @@ import java.util.Map;
import java.util.UUID;
@SerializableAs("TestModel")
public class TestModel implements ConfigurationSerializable {
public class TestModel extends AbstractModel implements ConfigurationSerializable {
public String name;
public UUID uuid;
public TestModel(String name, UUID uuid) {
this.name = name;
super(name);
this.uuid = uuid;
}
public void setName(String name) {
this.name = name;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public String getName() {
return name;
}
public UUID getUuid() {
return uuid;
}
@@ -0,0 +1,64 @@
package config.offset;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Field;
import java.util.List;
/**
* @author Chris2018998
*/
public class FieldOffset implements Comparable<FieldOffset> {
private final Field field;
private Long offsetValue;
private List<FieldOffset> subFieldOffsetList;
public FieldOffset(Field field) {
this.field = field;
}
public Long getOffsetValue() {
return offsetValue;
}
public void setOffsetValue(Long offsetValue) {
this.offsetValue = offsetValue;
}
public String toString() {
if (subFieldOffsetList == null)
return field.getName();
else {
StringBuilder builder = new StringBuilder();
builder.append("[");
for (int i = 0; i < subFieldOffsetList.size(); i++) {
FieldOffset offset = subFieldOffsetList.get(i);
if (i > 0) builder.append(",");
builder.append(field.getName()).append(".").append(offset.toString());
}
builder.append("]");
return builder.toString();
}
}
public List<FieldOffset> getSubFieldOffsetList() {
return subFieldOffsetList;
}
public void setSubFieldOffsetList(List<FieldOffset> subFieldOffsetList) {
this.subFieldOffsetList = subFieldOffsetList;
}
public Field getField() {
return field;
}
@Override
public int compareTo(@NotNull FieldOffset that) {
return this.offsetValue.compareTo(that.offsetValue);
}
}
@@ -0,0 +1,63 @@
package config.offset;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* @author Chris2018998
*/
public class OffsetUtil {
private static Unsafe unsafe;
static {
try {
// 获取 Unsafe 内部的私有的实例化单例对象
Field field = Unsafe.class.getDeclaredField("theUnsafe");
// 无视权限
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
// try {
// unsafe = AccessController.doPrivileged((PrivilegedExceptionAction<Unsafe>) () -> {
// Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
// theUnsafe.setAccessible(true);
// return (Unsafe) theUnsafe.get(null);
// });
// } catch (Throwable e) {
// System.err.println("Unable to load unsafe");
// }
}
public static List<FieldOffset> getClassMemberOffset(Class<?> beanClass) {
List<FieldOffset> offsetsList = new LinkedList<>();
for (Field field : beanClass.getDeclaredFields()) {
FieldOffset fieldOffset = new FieldOffset(field);
offsetsList.add(fieldOffset);
if (Modifier.isStatic(field.getModifiers()))
fieldOffset.setOffsetValue(unsafe.staticFieldOffset(field));
else
fieldOffset.setOffsetValue(unsafe.objectFieldOffset(field));
Class<?> fieldType = field.getType();
if (!fieldType.getName().startsWith("java")) {
Field[] subfields = fieldType.getDeclaredFields();
if (subfields.length > 0) {
fieldOffset.setSubFieldOffsetList(getClassMemberOffset(fieldType));
}
}
}
Collections.sort(offsetsList);
return offsetsList;
}
}
@@ -0,0 +1,35 @@
package config.source;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
@ConfigComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
public class DatabaseConfiguration extends ConfigurationRoot {
@ConfigPath("driver")
@ConfigComment({
"数据库驱动配置,请根据数据库类型设置。",
"- MySQL: com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
})
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver"
);
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s", HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get());
}
}
@@ -4,10 +4,17 @@ import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigComment;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredList;
import cc.carm.lib.configuration.core.value.type.ConfiguredMap;
import cc.carm.lib.configuration.core.value.type.ConfiguredSection;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
import config.model.TestModel;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
@ConfigPath("database")
@ConfigComment({"数据库配置", " 用于提供数据库连接,进行数据库操作。"})
public class DemoConfiguration extends ConfigurationRoot {
@ConfigPath(root = true)
@@ -19,29 +26,53 @@ public class DemoConfiguration extends ConfigurationRoot {
protected static final ConfigValue<Double> VERSION = ConfiguredValue.of(Double.class, 1.0D);
@ConfigPath("driver")
@ConfigComment({
"数据库驱动配置,请根据数据库类型设置。",
"- MySQL: com.mysql.cj.jdbc.Driver",
"- MariaDB(推荐): org.mariadb.jdbc.Driver",
})
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.cj.jdbc.Driver"
);
// 注意: 若对应类也有注解,则优先使用类的注解。
@ConfigPath("impl-test") //支持通过注解修改子配置的主路径,若不修改则以变量名自动生成。
@ConfigComment("Something...") // 支持给子路径直接打注释
public static final Class<?> IMPL = ImplConfiguration.class;
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
// 可以直接写静态内部类,并通过 Class<?> 声明。
public static final Class<?> SUB_TEST = Sub.class;
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
@ConfigPath("user") // 通过注解规定配置文件中的路径,若不进行注解则以变量名自动生成。
@ConfigComment({"Section类型数据测试"}) // 通过注解给配置添加注释。
public static final ConfigValue<TestModel> MODEL_TEST = ConfiguredSection
.builder(TestModel.class)
.defaults(new TestModel("Carm", UUID.randomUUID()))
.parseValue((section, defaultValue) -> TestModel.deserialize(section))
.serializeValue(TestModel::serialize).build();
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
// 子配置文件
@ConfigPath("database")
public static final Class<?> DB_CONFIG = DatabaseConfiguration.class;
@ConfigComment({"[ID-UUID] 对照表", "", "用于测试Map类型的解析与序列化保存"})
public static final ConfigValue<Map<Integer, UUID>> USERS = ConfiguredMap
.builder(Integer.class, UUID.class).fromString()
.parseKey(Integer::parseInt)
.parseValue(v -> Objects.requireNonNull(UUID.fromString(v)))
.build();
public static class Sub extends ConfigurationRoot {
@ConfigPath(value = "uuid-value", root = true)
public static final ConfigValue<UUID> UUID_CONFIG_VALUE = ConfiguredValue
.builder(UUID.class).fromString()
.parseValue((data, defaultValue) -> UUID.fromString(data))
.build();
public static final Class<?> NOTHING = Sub.That.class;
public static class That extends ConfigurationRoot {
public static final ConfigValue<List<UUID>> OPERATORS = ConfiguredList
.builder(UUID.class).fromString()
.parseValue(s -> Objects.requireNonNull(UUID.fromString(s)))
.build();
}
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s",
HOST.get(), PORT.get(), DATABASE.get(), EXTRA.get()
);
}
@@ -4,11 +4,13 @@ import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.yaml.value.ConfiguredSerializable;
import config.model.AbstractModel;
import config.model.TestModel;
@ConfigPath("ImplConfiguration")
@ConfigPath(root = true)
public class ImplConfiguration extends ConfigurationRoot {
public static final ConfigValue<TestModel> TEST = ConfiguredSerializable.of(TestModel.class);
public static final ConfigValue<? extends AbstractModel> TEST = ConfiguredSerializable.of(TestModel.class, TestModel.random());
}
-68
View File
@@ -1,68 +0,0 @@
<?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">
<parent>
<artifactId>easyconfiguration-parent</artifactId>
<groupId>cc.carm.lib</groupId>
<version>1.1.0</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>
<artifactId>easyconfiguration-bungee</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>${project.parent.groupId}</groupId>
<artifactId>easyconfiguration-core</artifactId>
<version>${project.parent.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.18-R0.1-SNAPSHOT</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.18-R0.1-SNAPSHOT</version>
<type>javadoc</type>
<scope>provided</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>
@@ -1,61 +0,0 @@
package cc.carm.lib.configuration.bungee;
import cc.carm.lib.configuration.core.ConfigInitializer;
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
import net.md_5.bungee.config.Configuration;
import net.md_5.bungee.config.ConfigurationProvider;
import net.md_5.bungee.config.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
public class BungeeConfigProvider extends FileConfigProvider<BungeeSectionWrapper> {
protected Configuration configuration;
protected ConfigInitializer<BungeeConfigProvider> initializer;
public BungeeConfigProvider(@NotNull File file) {
super(file);
}
public void initializeConfig() throws IOException {
this.configuration = getLoader().load(file);
this.initializer = new ConfigInitializer<>(this);
}
@Override
public @NotNull BungeeSectionWrapper getConfiguration() {
return BungeeSectionWrapper.of(configuration);
}
@Override
public void reload() throws Exception {
this.configuration = getLoader().load(file);
}
@Override
public void save() throws Exception {
getLoader().save(configuration, file);
}
@Override
public void setComments(@NotNull String path, @NotNull String... comments) {
}
@Override
public @Nullable String[] getComments(@NotNull String path) {
return null;
}
@Override
public @NotNull ConfigInitializer<BungeeConfigProvider> getInitializer() {
return this.initializer;
}
public static ConfigurationProvider getLoader() {
return ConfigurationProvider.getProvider(YamlConfiguration.class);
}
}
@@ -1,70 +0,0 @@
package cc.carm.lib.configuration.bungee;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import net.md_5.bungee.config.Configuration;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public class BungeeSectionWrapper implements ConfigurationWrapper {
private final Configuration section;
private BungeeSectionWrapper(Configuration section) {
this.section = section;
}
@Contract("!null->!null")
public static @Nullable BungeeSectionWrapper of(@Nullable Configuration section) {
return section == null ? null : new BungeeSectionWrapper(section);
}
@Override
public @NotNull Set<String> getKeys(boolean deep) {
return new LinkedHashSet<>(section.getKeys());
}
@Override
public @NotNull Map<String, Object> getValues(boolean deep) {
return section.getKeys().stream()
.collect(Collectors.toMap(key -> key, section::get, (a, b) -> b, LinkedHashMap::new));
}
@Override
public void set(@NotNull String path, @Nullable Object value) {
this.section.set(path, value);
}
@Override
public boolean contains(@NotNull String path) {
return this.section.contains(path);
}
@Override
public @Nullable Object get(@NotNull String path) {
return this.section.get(path);
}
@Override
public boolean isList(@NotNull String path) {
return get(path) instanceof List<?>;
}
@Override
public @Nullable List<?> getList(@NotNull String path) {
return this.section.getList(path);
}
@Override
public boolean isConfigurationSection(@NotNull String path) {
return true; // No provided functions :( SRY
}
@Override
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
return of(this.section.getSection(path));
}
}
@@ -1,35 +0,0 @@
package cc.carm.lib.configuration;
import cc.carm.lib.configuration.spigot.SpigotConfigProvider;
import java.io.File;
import java.io.IOException;
public class EasyConfiguration {
public static SpigotConfigProvider from(File file, String source) {
SpigotConfigProvider provider = new SpigotConfigProvider(file);
try {
provider.initializeFile(source);
provider.initializeConfig();
} catch (IOException e) {
e.printStackTrace();
}
return provider;
}
public static SpigotConfigProvider from(File file) {
return from(file, file.getName());
}
public static SpigotConfigProvider from(String fileName) {
return from(fileName, fileName);
}
public static SpigotConfigProvider from(String fileName, String source) {
return from(new File(fileName), source);
}
}
@@ -1,73 +0,0 @@
package cc.carm.lib.configuration.commented;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.constructor.BaseConstructor;
import org.yaml.snakeyaml.error.YAMLException;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;
import org.yaml.snakeyaml.serializer.Serializer;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* A hacky extension of {@link Yaml} that allows to write comments when dumping.
*/
public class CommentedYaml extends Yaml {
private final CommentsProvider commentsProvider;
public CommentedYaml(BaseConstructor constructor, Representer representer, DumperOptions dumperOptions, CommentsProvider commentsProvider) {
super(constructor, representer, dumperOptions);
this.commentsProvider = commentsProvider;
}
@Override
public String dump(Object data) {
List<Object> list = new ArrayList<>(1);
list.add(data);
return this.dumpAll(list.iterator());
}
@Override
public void dump(Object data, Writer output) {
List<Object> list = new ArrayList<>(1);
list.add(data);
this.dumpAll(list.iterator(), output, null);
}
@Override
public String dumpAll(Iterator<?> data) {
StringWriter buffer = new StringWriter();
this.dumpAll(data, buffer, null);
return buffer.toString();
}
@Override
public void dumpAll(Iterator<?> data, Writer output) {
this.dumpAll(data, output, null);
}
private void dumpAll(Iterator<?> data, Writer output, Tag rootTag) {
Serializer serializer = new Serializer(new CommentedEmitter(output, this.dumperOptions, this.commentsProvider), this.resolver, this.dumperOptions, rootTag);
try {
serializer.open();
while (data.hasNext()) {
Node node = this.representer.represent(data.next());
serializer.serialize(node);
}
serializer.close();
} catch (IOException var6) {
throw new YAMLException(var6);
}
}
}
@@ -1,69 +0,0 @@
package cc.carm.lib.configuration.commented;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.configuration.file.YamlConstructor;
import org.bukkit.configuration.file.YamlRepresenter;
import org.jetbrains.annotations.NotNull;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.representer.Representer;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
/**
* A yaml file with comments on certain properties, as returned by the given {@link CommentsProvider}.
* Unlike {@link YamlConfiguration}, this class does not provide a header support.
*/
public class CommentedYamlConfiguration extends YamlConfiguration {
private final DumperOptions yamlOptions = new DumperOptions();
private final Representer yamlRepresenter = new YamlRepresenter();
private final CommentedYaml yaml;
public CommentedYamlConfiguration(CommentsProvider commentsProvider) {
this.yaml = new CommentedYaml(new YamlConstructor(), this.yamlRepresenter, this.yamlOptions, commentsProvider);
}
public static CommentedYamlConfiguration loadConfiguration(CommentsProvider commentsProvider, File file) {
CommentedYamlConfiguration config = new CommentedYamlConfiguration(commentsProvider);
try {
config.load(file);
} catch (FileNotFoundException ignored) {
} catch (IOException | InvalidConfigurationException var4) {
var4.printStackTrace();
}
return config;
}
public static CommentedYamlConfiguration loadConfiguration(CommentsProvider commentsProvider, Reader reader) {
CommentedYamlConfiguration config = new CommentedYamlConfiguration(commentsProvider);
try {
config.load(reader);
} catch (IOException | InvalidConfigurationException ex) {
ex.printStackTrace();
}
return config;
}
@Override
public @NotNull String saveToString() {
this.yamlOptions.setIndent(this.options().indent());
this.yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
this.yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
String dump = this.yaml.dump(this.getValues(false));
if (dump.equals("{}\n")) {
dump = "";
}
// No header support.
return dump;
}
}
@@ -1,7 +0,0 @@
package cc.carm.lib.configuration.commented;
import java.util.function.Function;
public interface CommentsProvider extends Function<String, String[]> {
}
@@ -1,35 +0,0 @@
package cc.carm.lib.configuration.spigot;
import cc.carm.lib.configuration.commented.CommentsProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
public class ConfigComments implements CommentsProvider {
Map<String, String[]> comments = new HashMap<>();
protected Map<String, String[]> getComments() {
return comments;
}
public void set(@NotNull String path, @NotNull String... comments) {
if (comments.length == 0) {
getComments().remove(path);
} else {
getComments().put(path, comments);
}
}
public @Nullable String[] get(@NotNull String path) {
return getComments().get(path);
}
@Override
public String[] apply(String s) {
return get(s);
}
}
@@ -1,60 +0,0 @@
package cc.carm.lib.configuration.spigot;
import cc.carm.lib.configuration.core.ConfigInitializer;
import cc.carm.lib.configuration.core.source.impl.FileConfigProvider;
import cc.carm.lib.configuration.commented.CommentedYamlConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
public class SpigotConfigProvider extends FileConfigProvider<SpigotSectionWrapper> {
protected final ConfigComments comments = new ConfigComments();
protected ConfigInitializer<SpigotConfigProvider> initializer;
protected CommentedYamlConfiguration configuration;
public SpigotConfigProvider(@NotNull File file) {
super(file);
}
public void initializeConfig() {
this.configuration = CommentedYamlConfiguration.loadConfiguration(comments, file);
this.initializer = new ConfigInitializer<>(this);
}
public void say() {
System.out.println("Hello");
}
@Override
public @NotNull SpigotSectionWrapper getConfiguration() {
return SpigotSectionWrapper.of(configuration);
}
@Override
public void reload() throws Exception {
configuration.load(getFile());
}
@Override
public void save() throws Exception {
configuration.save(getFile());
}
@Override
public void setComments(@NotNull String path, @NotNull String... comments) {
this.comments.set(path, comments);
}
@Override
public @Nullable String[] getComments(@NotNull String path) {
return this.comments.get(path);
}
@Override
public @NotNull ConfigInitializer<SpigotConfigProvider> getInitializer() {
return this.initializer;
}
}
@@ -1,85 +0,0 @@
package cc.carm.lib.configuration.spigot;
import cc.carm.lib.configuration.core.source.ConfigurationWrapper;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SpigotSectionWrapper implements ConfigurationWrapper {
private final ConfigurationSection section;
private SpigotSectionWrapper(ConfigurationSection section) {
this.section = section;
}
@Contract("!null->!null")
public static @Nullable SpigotSectionWrapper of(@Nullable ConfigurationSection section) {
return section == null ? null : new SpigotSectionWrapper(section);
}
@Override
public @NotNull Set<String> getKeys(boolean deep) {
return new LinkedHashSet<>(section.getKeys(deep));
}
@Override
public @NotNull Map<String, Object> getValues(boolean deep) {
return section.getValues(deep);
}
@Override
public void set(@NotNull String path, @Nullable Object value) {
this.section.set(path, value);
}
@Override
public boolean contains(@NotNull String path) {
return this.section.contains(path);
}
@Override
public @Nullable Object get(@NotNull String path) {
return this.section.get(path);
}
@Override
public boolean isList(@NotNull String path) {
return this.section.isList(path);
}
@Override
public @Nullable List<?> getList(@NotNull String path) {
return this.section.getList(path);
}
@Override
public boolean isConfigurationSection(@NotNull String path) {
return this.section.isConfigurationSection(path);
}
@Override
public @Nullable ConfigurationWrapper getConfigurationSection(@NotNull String path) {
return of(this.section.getConfigurationSection(path));
}
@Nullable
public <T extends ConfigurationSerializable> T getSerializable(@NotNull String path, @NotNull Class<T> clazz) {
return getSerializable(path, clazz, null);
}
@Nullable
@Contract("_, _, !null -> !null")
public <T extends ConfigurationSerializable> T getSerializable(@NotNull String path, @NotNull Class<T> clazz, @Nullable T defaultValue) {
return this.section.getSerializable(path, clazz, defaultValue);
}
}
@@ -1,32 +0,0 @@
package cc.carm.lib.configuration.spigot;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
import cc.carm.lib.configuration.spigot.builder.SpigotConfigBuilder;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SpigotValue<T> extends CachedConfigValue<T> {
public static @NotNull SpigotConfigBuilder builder() {
return new SpigotConfigBuilder();
}
public SpigotValue(@Nullable SpigotConfigProvider provider,
@Nullable String configPath, @NotNull String[] comments, @Nullable T defaultValue) {
super(provider, configPath, comments, defaultValue);
}
public SpigotConfigProvider getSpigotProvider() {
ConfigurationProvider<?> provider = getProvider();
if (provider instanceof SpigotConfigProvider) return (SpigotConfigProvider) getProvider();
else throw new IllegalStateException("Provider is not a SpigotConfigProvider");
}
public SpigotSectionWrapper getSpigotConfig() {
return getSpigotProvider().getConfiguration();
}
}
@@ -1,13 +0,0 @@
package cc.carm.lib.configuration.spigot.builder;
import cc.carm.lib.configuration.core.builder.AbstractConfigBuilder;
import cc.carm.lib.configuration.spigot.SpigotConfigProvider;
public abstract class AbstractSpigotBuilder<T, B extends AbstractSpigotBuilder<T, B>>
extends AbstractConfigBuilder<T, B, SpigotConfigProvider> {
public AbstractSpigotBuilder() {
super(SpigotConfigProvider.class);
}
}
@@ -1,14 +0,0 @@
package cc.carm.lib.configuration.spigot.builder;
import cc.carm.lib.configuration.core.builder.ConfigBuilder;
import cc.carm.lib.configuration.spigot.builder.serializable.SerializableBuilder;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
public class SpigotConfigBuilder extends ConfigBuilder {
public <V extends ConfigurationSerializable> @NotNull SerializableBuilder<V> ofSerializable(@NotNull Class<V> valueClass) {
return new SerializableBuilder<>(valueClass);
}
}
@@ -1,29 +0,0 @@
package cc.carm.lib.configuration.spigot.builder.serializable;
import cc.carm.lib.configuration.spigot.builder.AbstractSpigotBuilder;
import cc.carm.lib.configuration.spigot.value.ConfiguredSerializable;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
public class SerializableBuilder<T extends ConfigurationSerializable>
extends AbstractSpigotBuilder<T, SerializableBuilder<T>> {
protected final @NotNull Class<T> valueClass;
public SerializableBuilder(@NotNull Class<T> valueClass) {
this.valueClass = valueClass;
}
@Override
protected @NotNull SerializableBuilder<T> getThis() {
return this;
}
@Override
public @NotNull ConfiguredSerializable<T> build() {
return new ConfiguredSerializable<>(this.provider, this.path, this.comments, this.valueClass, this.defaultValue);
}
}
@@ -1,4 +0,0 @@
package cc.carm.lib.configuration.spigot.item;
public class ItemConfiguration {
}
@@ -1,4 +0,0 @@
package cc.carm.lib.configuration.spigot.value;
public class ConfiguredItem {
}
@@ -1,52 +0,0 @@
package cc.carm.lib.configuration.spigot.value;
import cc.carm.lib.configuration.spigot.SpigotConfigProvider;
import cc.carm.lib.configuration.spigot.SpigotValue;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class ConfiguredSerializable<T extends ConfigurationSerializable> extends SpigotValue<T> {
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass) {
return of(valueClass, null);
}
public static <V extends ConfigurationSerializable> ConfiguredSerializable<V> of(@NotNull Class<V> valueClass,
@Nullable V defaultValue) {
return builder().ofSerializable(valueClass).defaults(defaultValue).build();
}
protected final @NotNull Class<T> valueClass;
public ConfiguredSerializable(@Nullable SpigotConfigProvider provider,
@Nullable String configPath, @NotNull String[] comments,
@NotNull Class<T> valueClass, @Nullable T defaultValue) {
super(provider, configPath, comments, defaultValue);
this.valueClass = valueClass;
}
@Override
public @Nullable T get() {
if (isExpired()) { // 已过时的数据,需要重新解析一次。
try {
// 若未出现错误,则直接更新缓存并返回。
return updateCache(getSpigotConfig().getSerializable(getConfigPath(), valueClass, getDefaultValue()));
} catch (Exception e) {
// 出现了解析错误,提示并返回默认值。
e.printStackTrace();
return useDefault();
}
} else return Optional.ofNullable(getCachedValue()).orElse(defaultValue);
}
@Override
public void set(@Nullable T value) {
updateCache(value);
setValue(value);
}
}
+5 -8
View File
@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<properties>
<java.version>8</java.version>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -15,14 +15,11 @@
<groupId>cc.carm.lib</groupId>
<artifactId>easyconfiguration-parent</artifactId>
<packaging>pom</packaging>
<version>1.1.0</version>
<version>2.1.0</version>
<modules>
<module>core</module>
<module>impl/yaml</module>
<module>platform/spigot</module>
<module>platform/bungee</module>
<module>impl/json</module>
</modules>
<name>EasyConfiguration</name>
@@ -93,7 +90,7 @@
<downloadUrl>https://github.com/CarmJos/EasyConfiguration/releases</downloadUrl>
<site>
<id>javadoc</id>
<name>EasySQL JavaDoc (on Github Pages)</name>
<name>EasyConfiguration JavaDoc (on Github Pages)</name>
<url>https://CarmJos.github.io/EasyConfiguration</url>
</site>
</distributionManagement>
@@ -167,7 +164,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.3.2</version>
<version>3.4.0</version>
<configuration>
<classifier>javadoc</classifier>
<detectJavaApiLink>false</detectJavaApiLink>