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

feat(init): 支持针对于实体类的初始化 #9

This commit is contained in:
2022-12-11 02:02:16 +08:00
parent 6f97166192
commit 35398ab741
31 changed files with 447 additions and 375 deletions
@@ -60,12 +60,84 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
}
}
/**
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
*
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
*/
public void initialize(@NotNull ConfigurationRoot config) {
initialize(config, true);
}
/**
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
*
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
* @param saveDefaults 是否写入默认值(默认为 true)。
*/
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
initializeClass(
config, null, null,
null, null, null,
saveDefaults
);
if (saveDefaults) {
try {
provider.save();
} catch (Exception e) {
e.printStackTrace();
}
}
}
protected void initializeClass(@NotNull ConfigurationRoot root,
@Nullable String parentPath, @Nullable String fieldName,
@Nullable ConfigPath fieldPath,
@Nullable HeaderComment fieldHeaderComments,
@Nullable InlineComment fieldInlineComments,
boolean saveDefaults) {
String path = getClassPath(root.getClass(), parentPath, fieldName, fieldPath);
this.provider.setHeaderComment(path, getClassHeaderComments(root.getClass(), fieldHeaderComments));
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
for (Field field : root.getClass().getDeclaredFields()) {
initializeField(root, field, path, saveDefaults);
}
}
private void initializeField(@NotNull ConfigurationRoot root,
@NotNull Field field, @Nullable String parent,
boolean saveDefaults) {
try {
field.setAccessible(true);
Object object = field.get(root);
if (object instanceof ConfigValue<?>) {
initializeValue(
(ConfigValue<?>) object, getFieldPath(field, parent),
field.getAnnotation(HeaderComment.class),
field.getAnnotation(InlineComment.class),
saveDefaults
);
} else if (object instanceof ConfigurationRoot) {
initializeClass(
(ConfigurationRoot) object, parent, field.getName(),
field.getAnnotation(ConfigPath.class),
field.getAnnotation(HeaderComment.class),
field.getAnnotation(InlineComment.class),
saveDefaults
);
}
} catch (IllegalAccessException ignored) {
}
}
protected void initializeClass(@NotNull Class<?> clazz,
@Nullable String parentPath, @Nullable String fieldName,
@Nullable ConfigPath fieldPath,
@Nullable HeaderComment fieldHeaderComments,
@Nullable InlineComment fieldInlineComments,
boolean saveDefaults, boolean loadSubClasses) {
if (!ConfigurationRoot.class.isAssignableFrom(clazz)) return; // 只解析继承了 ConfigurationRoot 的类
String path = getClassPath(clazz, parentPath, fieldName, fieldPath);
this.provider.setHeaderComment(path, getClassHeaderComments(clazz, fieldHeaderComments));
if (path != null) this.provider.setInlineComment(path, readInlineComments(fieldInlineComments));
@@ -142,7 +214,7 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
return value.length() > 0 ? value : null;
}
protected static @Nullable String getClassPath(@NotNull Class<?> clazz,
protected static @Nullable String getClassPath(@Nullable Class<?> clazz,
@Nullable String parentPath,
@Nullable String filedName,
@Nullable ConfigPath fieldAnnotation) {
@@ -150,11 +222,13 @@ public class ConfigInitializer<T extends ConfigurationProvider<?>> {
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();
if (clazz != null) {
ConfigPath clazzAnnotation = clazz.getAnnotation(ConfigPath.class);
if (clazzAnnotation != null) {
fromRoot = clazzAnnotation.root();
if (clazzAnnotation.value().length() > 0) {
return (fromRoot ? "" : parent) + clazzAnnotation.value();
}
}
}
@@ -53,18 +53,20 @@ public interface ConfigValueParser<T, R> {
if (Number.class.isAssignableFrom(valueClass)) {
if (Long.class.isAssignableFrom(valueClass)) {
input = longValue().parse(input, null);
input = longValue().parse(input, (Long) defaultValue);
} else if (Integer.class.isAssignableFrom(valueClass)) {
input = intValue().parse(input, null);
input = intValue().parse(input, (Integer) defaultValue);
} else if (Float.class.isAssignableFrom(valueClass)) {
input = floatValue().parse(input, null);
input = floatValue().parse(input, (Float) defaultValue);
} else if (Double.class.isAssignableFrom(valueClass)) {
input = doubleValue().parse(input, null);
input = doubleValue().parse(input, (Double) defaultValue);
} else if (Byte.class.isAssignableFrom(valueClass)) {
input = byteValue().parse(input, null);
input = byteValue().parse(input, (Byte) defaultValue);
} else if (Short.class.isAssignableFrom(valueClass)) {
input = shortValue().parse(input, null);
input = shortValue().parse(input, (Short) defaultValue);
}
} else if (Boolean.class.isAssignableFrom(valueClass)) {
input = booleanValue().parse(input, (Boolean) defaultValue);
}
if (valueClass.isInstance(input)) return valueClass.cast(input);
@@ -2,6 +2,8 @@ package cc.carm.lib.configuration.core.source;
import cc.carm.lib.configuration.core.ConfigInitializer;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.impl.CachedConfigValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable;
@@ -17,23 +19,54 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper<?>> {
this.updateTime = System.currentTimeMillis();
}
/**
* 得到配置文件的更新(最后加载)时间。
*
* @return 更新时间
*/
public long getUpdateTime() {
return updateTime;
}
/**
* 用于 {@link CachedConfigValue} 判断缓存值是否过期(即缓存的时间早于配置文件的最后加载时间)。
*
* @param time 缓存值时的时间戳
* @return 缓存值是否过期
*/
public boolean isExpired(long time) {
return getUpdateTime() > time;
}
/**
* 得到配置文件的原生功能类。
*
* @return 原生类
*/
public abstract @NotNull W getConfiguration();
/**
* 重载当前配置文件。(将不会保存已修改的内容)
*
* @throws Exception 当重载出现错误时抛出
*/
public void reload() throws Exception {
onReload(); // 调用重写的Reload方法
this.updateTime = System.currentTimeMillis();
}
/**
* 将当前对配置文件的更改进行保存。
*
* @throws Exception 当保存出现错误时抛出
*/
public abstract void save() throws Exception;
/**
* 针对于不同配置文件类型所执行的重载操作。
*
* @throws Exception 当操作出现错误时抛出。
*/
protected abstract void onReload() throws Exception;
public abstract @Nullable ConfigurationComments getComments();
@@ -60,16 +93,53 @@ public abstract class ConfigurationProvider<W extends ConfigurationWrapper<?>> {
public abstract @NotNull ConfigInitializer<? extends ConfigurationProvider<W>> getInitializer();
/**
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
*
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
*/
public void initialize(Class<? extends ConfigurationRoot> configClazz) {
initialize(configClazz, true);
}
/**
* 初始化指定类以及其子类的所有 {@link ConfigValue} 对象。
*
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
* @param saveDefaults 是否写入默认值(默认为 true)。
*/
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults) {
getInitializer().initialize(configClazz, saveDefaults);
this.getInitializer().initialize(configClazz, saveDefaults);
}
/**
* 初始化指定类的所有 {@link ConfigValue} 对象。
*
* @param configClazz 配置文件类,须继承于 {@link ConfigurationRoot} 。
* @param saveDefaults 是否写入默认值(默认为 true)。
* @param loadSubClasses 是否加载内部子类(默认为 true)。
*/
public void initialize(Class<? extends ConfigurationRoot> configClazz, boolean saveDefaults, boolean loadSubClasses) {
getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
this.getInitializer().initialize(configClazz, saveDefaults, loadSubClasses);
}
/**
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
*
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
*/
public void initialize(@NotNull ConfigurationRoot config) {
this.getInitializer().initialize(config, true);
}
/**
* 初始化指定实例的所有 {@link ConfigValue} 与内部 {@link ConfigurationRoot} 对象。
*
* @param config 配置文件实例类,须实现 {@link ConfigurationRoot} 。
* @param saveDefaults 是否写入默认值(默认为 true)。
*/
public void initialize(@NotNull ConfigurationRoot config, boolean saveDefaults) {
this.getInitializer().initialize(config, saveDefaults);
}
}
@@ -0,0 +1,64 @@
package cc.carm.test.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;
// }
//
//
//}
//