diff --git a/core/pom.xml b/core/pom.xml index 4a285d5..5f9a61e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -18,14 +18,6 @@ easyconfiguration-core jar - - - cc.carm.lib - easyoptions - 1.1.0 - - - diff --git a/core/src/main/java/cc/carm/lib/configuration/Configuration.java b/core/src/main/java/cc/carm/lib/configuration/Configuration.java index 3596cf7..26a52a1 100644 --- a/core/src/main/java/cc/carm/lib/configuration/Configuration.java +++ b/core/src/main/java/cc/carm/lib/configuration/Configuration.java @@ -2,8 +2,6 @@ package cc.carm.lib.configuration; /** * The root interface of the configuration file interfaces, - * which is used to label and record the configuration information. + * which is used to label a class as a configuration. */ -public interface Configuration { - -} +public interface Configuration { } \ No newline at end of file diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapter.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapter.java index deeb81d..6fe33a3 100644 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapter.java +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapter.java @@ -1,52 +1,77 @@ package cc.carm.lib.configuration.adapter; import cc.carm.lib.configuration.source.ConfigurationProvider; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; /** * Value adapter, used to convert the value of the configuration file into the objects. * - * @param The type of the base data - * @param The type of the target value + * @param The type of the target value */ -public abstract class ValueAdapter implements ValueSerializer, ValueDeserializer { +public class ValueAdapter + implements ValueSerializer, ValueParser { - protected final Class baseType; - protected final Class valueType; + protected final @NotNull ValueType type; + protected @Nullable ValueSerializer serializer; + protected @Nullable ValueParser deserializer; - protected ValueAdapter(Class baseType, Class valueType) { - this.baseType = baseType; - this.valueType = valueType; + public ValueAdapter(@NotNull ValueType type) { + this(type, null, null); } - public Class getBaseClass() { - return baseType; + public ValueAdapter(@NotNull ValueType type, + @Nullable ValueSerializer serializer, + @Nullable ValueParser deserializer) { + this.type = type; + this.serializer = serializer; + this.deserializer = deserializer; } - public Class getValueClass() { - return valueType; + public @NotNull ValueType type() { + return type; } - public boolean isAdaptedFrom(Class clazz) { - return clazz.isAssignableFrom(valueType); + public @Nullable ValueSerializer serializer() { + return serializer; } - public boolean isAdaptedFrom(Object object) { - return isAdaptedFrom(object.getClass()); + public @Nullable ValueParser deserializer() { + return deserializer; } - public boolean isAdaptedTo(Class clazz) { - return clazz == valueType; + public void serializer(@Nullable ValueSerializer serializer) { + this.serializer = serializer; } - @SuppressWarnings("unchecked") - protected final V deserializeObject(ConfigurationProvider provider, Class valueClass, Object data) throws Exception { - return deserialize(provider, (Class) valueClass, (B) data); + public void deserializer(@Nullable ValueParser deserializer) { + this.deserializer = deserializer; } - @SuppressWarnings("unchecked") - protected final B serializeObject(ConfigurationProvider provider, Object value) throws Exception { - return serialize(provider, (V) value); + @Override + public Object serialize(@NotNull ConfigurationProvider provider, @NotNull ValueType type, @NotNull TYPE value) throws Exception { + if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported"); + return serializer.serialize(provider, type, value); } + @Override + public TYPE deserialize(@NotNull ConfigurationProvider provider, @NotNull ValueType type, @NotNull Object value) throws Exception { + if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported"); + return deserializer.deserialize(provider, type, value); + } + + @Override + public boolean equals(Object o) { + if (!(o instanceof ValueAdapter)) return false; + ValueAdapter that = (ValueAdapter) o; + return Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hashCode(type); + } } diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapterRegistry.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapterRegistry.java index 3216c79..3bb7e67 100644 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapterRegistry.java +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueAdapterRegistry.java @@ -1,91 +1,125 @@ package cc.carm.lib.configuration.adapter; -import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapters; import cc.carm.lib.configuration.function.ConfigDataFunction; import cc.carm.lib.configuration.source.ConfigurationProvider; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.Map; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; public class ValueAdapterRegistry { - protected final Map, ValueAdapter> adapters = new HashMap<>(); + protected final Set> adapters = new HashSet<>(); - public void register(@NotNull ValueAdapter adapter) { - adapters.put(adapter.getValueClass(), adapter); + public void register(@NotNull Class from, @NotNull Class to, + @Nullable ConfigDataFunction parser, + @Nullable ConfigDataFunction serializer) { + register(ValueType.of(from), ValueType.of(to), parser, serializer); } - public void register(Class clazz, @NotNull ValueAdapter adapter) { - adapters.put(clazz, adapter); + public void register(@NotNull ValueType from, @NotNull ValueType to, + @Nullable ConfigDataFunction parser, + @Nullable ConfigDataFunction serializer) { + ValueAdapter fromAdapter = adapterOf(from); + if (fromAdapter == null) throw new IllegalArgumentException("No adapter for type " + from); + register(to, + serializer == null ? null : (provider, type, value) -> fromAdapter.serialize(provider, from, serializer.handle(value)), + parser == null ? null : (provider, type, data) -> parser.handle(fromAdapter.deserialize(provider, from, data)) + ); } - public void register(Class baseClass, Class valueClass, - ConfigDataFunction parser, - ConfigDataFunction serializer) { - register(new ValueAdapter(baseClass, valueClass) { - @Override - public B serialize(@NotNull ConfigurationProvider provider, @NotNull V value) throws Exception { - return serializer.parse(value); - } - - @Override - public V deserialize(@NotNull ConfigurationProvider provider, @NotNull Class clazz, @NotNull B data) throws Exception { - return parser.parse(data); - } - }); + public void register(@NotNull ValueAdapter... adapter) { + adapters.addAll(Arrays.asList(adapter)); } - public void unregister(@NotNull Class typeClass) { - adapters.remove(typeClass); + public void register(@NotNull Class type, @NotNull ValueSerializer serializer) { + register(ValueType.of(type), serializer); + } + + public void register(@NotNull ValueType type, @NotNull ValueSerializer serializer) { + ValueAdapter existing = adapterOf(type); + if (existing != null) { + existing.serializer(serializer); + } else { + register(new ValueAdapter<>(type, serializer, null)); + } + } + + public void register(@NotNull Class type, @NotNull ValueParser deserializer) { + register(ValueType.of(type), deserializer); + } + + public void register(@NotNull ValueType type, @NotNull ValueParser deserializer) { + ValueAdapter existing = adapterOf(type); + if (existing != null) { + existing.deserializer(deserializer); + } else { + register(new ValueAdapter<>(type, null, deserializer)); + } + } + + public void register(@NotNull ValueType type, @Nullable ValueSerializer serializer, @Nullable ValueParser deserializer) { + if (serializer == null && deserializer == null) return; + ValueAdapter existing = adapterOf(type); + if (existing != null) { + if (serializer != null) existing.serializer(serializer); + if (deserializer != null) existing.deserializer(deserializer); + } else { + register(new ValueAdapter<>(type, serializer, deserializer)); + } + } + + public void unregister(@NotNull Class type) { + unregister(ValueType.of(type)); + } + + public void unregister(@NotNull ValueType type) { + adapters.removeIf(adapter -> adapter.type().equals(type)); } @SuppressWarnings("unchecked") + public ValueAdapter adapterOf(@NotNull ValueType type) { + ValueAdapter matched = adapters.stream().filter(adapter -> adapter.type().equals(type)).findFirst().orElse(null); + if (matched != null) return (ValueAdapter) matched; + + // If no adapter found, try to find the adapter for the super type + return (ValueAdapter) adapters.stream() + .filter(adapter -> adapter.type().isSubtypeOf(type)) + .findFirst().orElse(null); + } + + public ValueAdapter adapterOf(@NotNull T value) { + return adapterOf(ValueType.of(value)); + } + + public ValueAdapter adapterOf(@NotNull Class type) { + return adapterOf(ValueType.of(type)); + } + @Contract("_,_,null -> null") public T deserialize(@NotNull ConfigurationProvider provider, @NotNull Class type, @Nullable Object source) throws Exception { + return deserialize(provider, ValueType.of(type), source); + } + + @Contract("_,_,null -> null") + public T deserialize(@NotNull ConfigurationProvider provider, @NotNull ValueType type, @Nullable Object source) throws Exception { if (source == null) return null; // Null check if (type.isInstance(source)) return type.cast(source); // Not required to deserialize - - ValueAdapter adapter = getAdapter(type); - if (adapter == null) throw new RuntimeException("No adapter for type " + type.getName()); - - // Check if value is adapted from given value's type - if (adapter.isAdaptedFrom(source)) { - return (T) adapter.deserializeObject(provider, type, source); - } - - // Otherwise, we need to deserialize one by one. - Object baseValue = deserialize(provider, adapter.getBaseClass(), source); - if (baseValue == null) return null; // Null check - - return (T) adapter.deserializeObject(provider, type, baseValue); + ValueAdapter adapter = adapterOf(type); + if (adapter == null) throw new RuntimeException("No adapter for type " + type); + return adapter.deserialize(provider, type, source); } @Contract("_,null -> null") public Object serialize(@NotNull ConfigurationProvider provider, @Nullable T value) throws Exception { if (value == null) return null; // Null check - - ValueAdapter adapter = getAdapter(value.getClass()); + ValueType type = ValueType.of(value); + ValueAdapter adapter = adapterOf(type); if (adapter == null) return value; // No adapters, try to return the original value - - if (adapter instanceof PrimitiveAdapters) { - // If the value is adapted from a primitive type, - // we should serialize it into object, then return. - return adapter.serializeObject(provider, value); - } - - // Otherwise, we need to serialize one by one. - return serialize(provider, adapter.serializeObject(provider, value)); - } - - public ValueAdapter getAdapter(Class clazz) { - return adapters.getOrDefault(clazz, findAdapter(clazz)); - } - - public ValueAdapter findAdapter(Class clazz) { - return adapters.values().stream().filter(adapter -> adapter.isAdaptedTo(clazz)).findFirst().orElse(null); + return adapter.serialize(provider, type, value); } diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueDeserializer.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueDeserializer.java deleted file mode 100644 index 2f63ebb..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueDeserializer.java +++ /dev/null @@ -1,17 +0,0 @@ -package cc.carm.lib.configuration.adapter; - -import cc.carm.lib.configuration.source.ConfigurationProvider; -import org.jetbrains.annotations.NotNull; - -/** - * Value deserializer, convert base data to target value. - * - * @param The type of base data - * @param The type of target value - */ -@FunctionalInterface -public interface ValueDeserializer { - - V deserialize(@NotNull ConfigurationProvider provider, @NotNull Class clazz, @NotNull B data) throws Exception; - -} diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueParser.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueParser.java new file mode 100644 index 0000000..b35b089 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueParser.java @@ -0,0 +1,19 @@ +package cc.carm.lib.configuration.adapter; + +import cc.carm.lib.configuration.source.ConfigurationProvider; +import org.jetbrains.annotations.NotNull; + +/** + * Value deserializer, convert base data to target value. + * + * @param The type of target value + */ +@FunctionalInterface +public interface ValueParser { + + TYPE deserialize( + @NotNull ConfigurationProvider provider, + @NotNull ValueType type, @NotNull Object data + ) throws Exception; + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueSerializer.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueSerializer.java index d27e8c9..44db8a9 100644 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueSerializer.java +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueSerializer.java @@ -6,12 +6,14 @@ import org.jetbrains.annotations.NotNull; /** * Value serializer, convert target value to base data. * - * @param The type of base data - * @param The type of value + * @param The type of value */ @FunctionalInterface -public interface ValueSerializer { +public interface ValueSerializer { - B serialize(@NotNull ConfigurationProvider provider, @NotNull V value) throws Exception; + Object serialize( + @NotNull ConfigurationProvider provider, + @NotNull ValueType type, @NotNull TYPE value + ) throws Exception; } diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java new file mode 100644 index 0000000..ca2edaf --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueType.java @@ -0,0 +1,150 @@ +package cc.carm.lib.configuration.adapter; + +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.ParameterizedType; + +import java.lang.reflect.Type; +import java.util.Objects; + +/** + * Used to get the generic type. + */ +public abstract class ValueType { + + @SuppressWarnings("unchecked") + public static ValueType of(@NotNull T value) { + return of((Class) value.getClass()); + } + + public static ValueType of(final Type type) { + return new ValueType(type) { + }; + } + + public static ValueType of(final Class clazz) { + return of((Type) clazz); + } + + /** + * Get the generic type of the complex type. + * + * @param rawType The raw type + * @param types The type arguments + * @param The type + * @return The {@link ValueType} + */ + public static ValueType of(final Class rawType, final Type... types) { + ParameterizedType parameterizedType = new ParameterizedType() { + @Override + public @NotNull Type @NotNull [] getActualTypeArguments() { + return types; + } + + @Override + public @NotNull Type getRawType() { + return rawType; + } + + @Override + public Type getOwnerType() { + return null; + } + }; + return of(parameterizedType); + } + + private final Type type; + + protected ValueType() { + this.type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; + } + + private ValueType(Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + public boolean isSubtypeOf(Class target) { + Class rawType = getRawType(); + return target.isAssignableFrom(rawType); + } + + public boolean isSubtypeOf(ValueType target) { + return target.isSubtypeOf(getRawType()); + } + + public boolean isInstance(Object obj) { + return obj != null && getRawType().isInstance(obj); + } + + + /** + * 提取当前 ValueType 的原始类型(Class 对象)。 + * + * @return 对应的 Class 对象 + * @throws IllegalStateException 如果无法提取出原始类型 + */ + public Class getRawType() { + if (type instanceof Class) { + return (Class) type; + } + if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + Type raw = pt.getRawType(); + if (raw instanceof Class) { + return (Class) raw; + } + } + throw new IllegalStateException("Unsupported type: " + type); + } + + @SuppressWarnings("unchecked") + public T cast(Object obj) { + if (!isInstance(obj)) { + throw new ClassCastException("Cannot cast object " + obj + " to type " + this); + } + return (T) obj; + } + + @Override + public String toString() { + if (type instanceof Class) { + return ((Class) type).getName(); + } + if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + Type raw = pt.getRawType(); + StringBuilder sb = new StringBuilder(); + sb.append(raw.getTypeName()); + sb.append('<'); + Type[] args = pt.getActualTypeArguments(); + for (int i = 0; i < args.length; i++) { + if (i > 0) { + sb.append(", "); + } + sb.append(args[i].getTypeName()); + } + return sb.toString(); + } + return type.getTypeName(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj instanceof ValueType) { + return Objects.equals(type, ((ValueType) obj).type); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(type); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/EnumAdapter.java b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/EnumAdapter.java deleted file mode 100644 index ee4a3a4..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/EnumAdapter.java +++ /dev/null @@ -1,29 +0,0 @@ -package cc.carm.lib.configuration.adapter.strandard; - -import cc.carm.lib.configuration.adapter.ValueAdapter; -import cc.carm.lib.configuration.source.ConfigurationProvider; -import org.jetbrains.annotations.NotNull; - -@SuppressWarnings({"unchecked", "rawtypes"}) -public class EnumAdapter extends ValueAdapter { - - public EnumAdapter() { - super(String.class, Enum.class); - } - - @Override - public String serialize(@NotNull ConfigurationProvider provider, @NotNull Enum value) throws Exception { - return value.name(); - } - - @Override - public Enum deserialize(@NotNull ConfigurationProvider provider, @NotNull Class clazz, @NotNull String data) throws Exception { - return Enum.valueOf(clazz, data); - } - - @Override - public boolean isAdaptedTo(Class clazz) { - return clazz.isEnum(); - } - -} diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java index 5a36a73..f522bed 100644 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java @@ -1,11 +1,27 @@ package cc.carm.lib.configuration.adapter.strandard; import cc.carm.lib.configuration.adapter.ValueAdapter; +import cc.carm.lib.configuration.adapter.ValueParser; +import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.function.ConfigDataFunction; -import cc.carm.lib.configuration.source.ConfigurationProvider; import org.jetbrains.annotations.NotNull; -public abstract class PrimitiveAdapters extends ValueAdapter { +public class PrimitiveAdapters extends ValueAdapter { + + public static final PrimitiveAdapters[] ADAPTERS = new PrimitiveAdapters[]{ + ofString(), ofBoolean(), ofBooleanType(), ofCharacter(), ofCharacterType(), + ofInteger(), ofIntegerType(), ofLong(), ofLongType(), ofDouble(), ofDoubleType(), + ofFloat(), ofFloatType(), ofShort(), ofShortType(), ofByte(), ofByteType() + }; + + @SuppressWarnings({"unchecked", "rawtypes"}) + public static ValueAdapter> ofEnum() { + ValueAdapter> adapter = new ValueAdapter<>(new ValueType>() { + }); + adapter.deserializer((provider, type, data) -> Enum.valueOf((Class) type.getRawType(), data.toString())); + adapter.serializer((provider, type, value) -> value.name()); + return adapter; + } public static PrimitiveAdapters ofString() { return of(String.class, o -> o instanceof String ? (String) o : o.toString()); @@ -15,56 +31,79 @@ public abstract class PrimitiveAdapters extends ValueAdapter { return of(Boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString())); } + public static PrimitiveAdapters ofBooleanType() { + return of(boolean.class, o -> o instanceof Boolean ? (Boolean) o : Boolean.parseBoolean(o.toString())); + } + public static PrimitiveAdapters ofCharacter() { return of(Character.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0)); } + public static PrimitiveAdapters ofCharacterType() { + return of(char.class, o -> o instanceof Character ? (Character) o : o.toString().charAt(0)); + } + public static PrimitiveAdapters ofInteger() { return ofNumber(Integer.class, Number::intValue, Integer::parseInt); } + public static PrimitiveAdapters ofIntegerType() { + return ofNumber(int.class, Number::intValue, Integer::parseInt); + } + public static PrimitiveAdapters ofLong() { return ofNumber(Long.class, Number::longValue, Long::parseLong); } + public static PrimitiveAdapters ofLongType() { + return ofNumber(long.class, Number::longValue, Long::parseLong); + } + public static PrimitiveAdapters ofDouble() { return ofNumber(Double.class, Number::doubleValue, Double::parseDouble); } + public static PrimitiveAdapters ofDoubleType() { + return ofNumber(double.class, Number::doubleValue, Double::parseDouble); + } + public static PrimitiveAdapters ofFloat() { return ofNumber(Float.class, Number::floatValue, Float::parseFloat); } + public static PrimitiveAdapters ofFloatType() { + return ofNumber(float.class, Number::floatValue, Float::parseFloat); + } + public static PrimitiveAdapters ofShort() { return ofNumber(Short.class, Number::shortValue, Short::parseShort); } + public static PrimitiveAdapters ofShortType() { + return ofNumber(short.class, Number::shortValue, Short::parseShort); + } + public static PrimitiveAdapters ofByte() { return ofNumber(Byte.class, Number::byteValue, Byte::parseByte); } - protected PrimitiveAdapters(Class valueType) { - super(Object.class, valueType); - } - - @Override - public Object serialize(@NotNull ConfigurationProvider provider, @NotNull T value) throws Exception { - return value; + public static PrimitiveAdapters ofByteType() { + return ofNumber(byte.class, Number::byteValue, Byte::parseByte); } public static PrimitiveAdapters of(@NotNull Class clazz, @NotNull ConfigDataFunction function) { - return new PrimitiveAdapters(clazz) { - @Override - public T deserialize(@NotNull ConfigurationProvider provider, @NotNull Class clazz, @NotNull Object data) throws Exception { - return function.parse(data); - } - }; + return new PrimitiveAdapters<>(clazz, (p, type, data) -> function.handle(data)); } public static PrimitiveAdapters ofNumber(@NotNull Class numberClass, @NotNull ConfigDataFunction castFunction, @NotNull ConfigDataFunction parseFunction) { - return of(numberClass, o -> o instanceof Number ? castFunction.parse((Number) o) : parseFunction.parse(o.toString())); + return of(numberClass, o -> o instanceof Number ? castFunction.handle((Number) o) : parseFunction.handle(o.toString())); } + + protected PrimitiveAdapters(@NotNull Class valueType, @NotNull ValueParser deserializer) { + super(ValueType.of(valueType), (provider, type, value) -> value, deserializer); + } + } diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/StandardAdapters.java b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/StandardAdapters.java new file mode 100644 index 0000000..3b713d5 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/StandardAdapters.java @@ -0,0 +1,19 @@ +package cc.carm.lib.configuration.adapter.strandard; + +import cc.carm.lib.configuration.adapter.ValueAdapter; +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.source.section.ConfigurationSection; + +public interface StandardAdapters { + + ValueAdapter SECTION_ADAPTER = new ValueAdapter<>( + ValueType.of(ConfigurationSection.class), + (provider, type, value) -> value, + (provider, type, value) -> { + if (value instanceof ConfigurationSection) { + return (ConfigurationSection) value; + } else throw new IllegalArgumentException("Value is not a ConfigurationSection"); + } + ); + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/annotation/ConfigPath.java b/core/src/main/java/cc/carm/lib/configuration/annotation/ConfigPath.java index c843e17..9d21c85 100644 --- a/core/src/main/java/cc/carm/lib/configuration/annotation/ConfigPath.java +++ b/core/src/main/java/cc/carm/lib/configuration/annotation/ConfigPath.java @@ -1,6 +1,6 @@ package cc.carm.lib.configuration.annotation; -import cc.carm.lib.configuration.loader.PathGenerator; +import cc.carm.lib.configuration.source.loader.PathGenerator; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/AbstractConfigBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/AbstractConfigBuilder.java new file mode 100644 index 0000000..0481d70 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/builder/AbstractConfigBuilder.java @@ -0,0 +1,51 @@ +package cc.carm.lib.configuration.builder; + +import cc.carm.lib.configuration.source.ConfigurationProvider; +import cc.carm.lib.configuration.value.ConfigValue; +import cc.carm.lib.configuration.value.ValueManifest; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; + +public abstract class AbstractConfigBuilder, P extends ConfigurationProvider> { + + protected final Class providerClass; + + protected @Nullable P provider; + protected @Nullable String path; + + protected @NotNull Supplier defaultValueSupplier = () -> null; + + protected AbstractConfigBuilder(Class providerClass) { + this.providerClass = providerClass; + } + + protected abstract @NotNull B self(); + + public abstract @NotNull ConfigValue build(); + + public @NotNull B from(@Nullable P provider) { + this.provider = provider; + return self(); + } + + public @NotNull B path(@Nullable String path) { + this.path = path; + return self(); + } + + public @NotNull B defaults(@Nullable T defaultValue) { + return defaults(() -> defaultValue); + } + + public @NotNull B defaults(@NotNull Supplier<@Nullable T> supplier) { + this.defaultValueSupplier = supplier; + return self(); + } + + protected @NotNull ValueManifest buildManifest() { + return null; + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/CommonConfigBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/CommonConfigBuilder.java new file mode 100644 index 0000000..10a1fe1 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/builder/CommonConfigBuilder.java @@ -0,0 +1,12 @@ +package cc.carm.lib.configuration.builder; + +import cc.carm.lib.configuration.source.ConfigurationProvider; + +public abstract class CommonConfigBuilder> + extends AbstractConfigBuilder> { + + protected CommonConfigBuilder() { + super(ConfigurationProvider.class); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/value/ConfigValueBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/value/ConfigValueBuilder.java new file mode 100644 index 0000000..113fabf --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/builder/value/ConfigValueBuilder.java @@ -0,0 +1,78 @@ +package cc.carm.lib.configuration.builder.value; + +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.function.ConfigDataFunction; +import cc.carm.lib.configuration.function.ConfigValueHandler; +import cc.carm.lib.configuration.source.section.ConfigurationSection; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public class ConfigValueBuilder { + + protected final @NotNull ValueType type; + + public ConfigValueBuilder(@NotNull ValueType type) { + this.type = type; + } + + public @NotNull SourceValueBuilder from(@NotNull Class clazz) { + return new SourceValueBuilder<>(ValueType.of(clazz), this.type); + } + + public @NotNull SourceValueBuilder from(@NotNull ValueType sourceType) { + return new SourceValueBuilder<>(sourceType, this.type); + } + + public @NotNull SourceValueBuilder from(@NotNull ValueType sourceType, + @NotNull ConfigValueHandler valueParser, + @NotNull ConfigValueHandler valueSerializer) { + return new SourceValueBuilder<>(sourceType, this.type, valueParser, valueSerializer); + } + + public @NotNull SourceValueBuilder fromString() { + return from(String.class); + } + + public @NotNull SourceValueBuilder fromInteger() { + return from(Integer.class); + } + + public @NotNull SourceValueBuilder fromLong() { + return from(Long.class); + } + + public @NotNull SourceValueBuilder fromDouble() { + return from(Double.class); + } + + public @NotNull SourceValueBuilder fromFloat() { + return from(Float.class); + } + + public @NotNull SourceValueBuilder fromBoolean() { + return from(Boolean.class); + } + + public @NotNull SourceValueBuilder fromCharacter() { + return from(Character.class); + } + + public @NotNull SourceValueBuilder fromByte() { + return from(Byte.class); + } + + public @NotNull SourceValueBuilder fromShort() { + return from(Short.class); + } + + public @NotNull SectionValueBuilder fromSection() { + return new SectionValueBuilder<>(this.type); + } + + public @NotNull SectionValueBuilder fromSection(@NotNull ConfigValueHandler valueParser, + @NotNull ConfigValueHandler> valueSerializer) { + return new SectionValueBuilder<>(this.type, valueParser, valueSerializer); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/value/SectionValueBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/value/SectionValueBuilder.java new file mode 100644 index 0000000..a4a4dae --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/builder/value/SectionValueBuilder.java @@ -0,0 +1,81 @@ +package cc.carm.lib.configuration.builder.value; + +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.builder.CommonConfigBuilder; +import cc.carm.lib.configuration.function.ConfigDataFunction; +import cc.carm.lib.configuration.function.ConfigValueHandler; +import cc.carm.lib.configuration.source.section.ConfigurationSection; +import cc.carm.lib.configuration.value.standard.ConfiguredValue; +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Consumer; + +public class SectionValueBuilder extends CommonConfigBuilder> { + + protected final @NotNull ValueType valueType; + + protected @NotNull ConfigValueHandler parser; + protected @NotNull ConfigValueHandler> serializer; + + public SectionValueBuilder(@NotNull ValueType valueType) { + this(valueType, ConfigValueHandler.required(), ConfigValueHandler.required()); + } + + public SectionValueBuilder(@NotNull ValueType valueType, + @NotNull ConfigValueHandler parser, + @NotNull ConfigValueHandler> serializer) { + this.valueType = valueType; + this.parser = parser; + this.serializer = serializer; + } + + @Override + protected @NotNull SectionValueBuilder self() { + return this; + } + + public @NotNull SectionValueBuilder parse(ConfigDataFunction valueParser) { + return parse((p, section) -> valueParser.handle(section)); + } + + public @NotNull SectionValueBuilder parse(ConfigValueHandler valueParser) { + this.parser = valueParser; + return this; + } + + public @NotNull SectionValueBuilder serialize(ConfigDataFunction> serializer) { + return serialize((p, value) -> serializer.handle(value)); + } + + public @NotNull SectionValueBuilder serialize(ConfigValueHandler> serializer) { + this.serializer = serializer; + return this; + } + + public @NotNull SectionValueBuilder serialize(Consumer> serializer) { + return serialize((p, value) -> { + Map map = new LinkedHashMap<>(); + serializer.accept(map); + return map; + }); + } + + @Override + public @NotNull ConfiguredValue build() { + return new ConfiguredValue<>( + buildManifest(), + (p, type, data) -> { + ConfigurationSection section = p.deserialize(ConfigurationSection.class, data); + if (section == null) return null; + return this.parser.handle(p, section); + }, + (p, type, data) -> { + Map map = this.serializer.handle(p, data); + return map == null || map.isEmpty() ? null : map; // Map is a type of original data + } + ); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/value/SourceValueBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/value/SourceValueBuilder.java new file mode 100644 index 0000000..fd8bc29 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/builder/value/SourceValueBuilder.java @@ -0,0 +1,68 @@ +package cc.carm.lib.configuration.builder.value; + +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.builder.CommonConfigBuilder; +import cc.carm.lib.configuration.function.ConfigDataFunction; +import cc.carm.lib.configuration.function.ConfigValueHandler; +import cc.carm.lib.configuration.value.standard.ConfiguredValue; +import org.jetbrains.annotations.NotNull; + +public class SourceValueBuilder extends CommonConfigBuilder> { + + protected final @NotNull ValueType sourceType; + protected final @NotNull ValueType valueType; + protected @NotNull ConfigValueHandler valueParser; + protected @NotNull ConfigValueHandler valueSerializer; + + public SourceValueBuilder(@NotNull ValueType sourceType, @NotNull ValueType valueType) { + this(sourceType, valueType, ConfigValueHandler.required(), ConfigValueHandler.required()); + } + + public SourceValueBuilder(@NotNull ValueType sourceType, @NotNull ValueType valueType, + @NotNull ConfigValueHandler valueParser, + @NotNull ConfigValueHandler valueSerializer) { + this.sourceType = sourceType; + this.valueType = valueType; + this.valueParser = valueParser; + this.valueSerializer = valueSerializer; + } + + @Override + protected @NotNull SourceValueBuilder self() { + return this; + } + + public @NotNull SourceValueBuilder parse(ConfigDataFunction parser) { + return parse((p, source) -> parser.handle(source)); + } + + public @NotNull SourceValueBuilder parse(@NotNull ConfigValueHandler parser) { + this.valueParser = parser; + return this; + } + + public @NotNull SourceValueBuilder serialize(@NotNull ConfigValueHandler serializer) { + this.valueSerializer = serializer; + return this; + } + + public @NotNull SourceValueBuilder serialize(@NotNull ConfigDataFunction serializer) { + return serialize((p, value) -> serializer.handle(value)); + } + + @Override + public @NotNull ConfiguredValue build() { + return new ConfiguredValue<>( + buildManifest(), + (p, type, data) -> { + S source = p.deserialize(this.sourceType, data); + return this.valueParser.handle(p, source); + }, + (p, type, value) -> { + S source = this.valueSerializer.handle(p, value); + return p.serialize(source); + } + ); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/function/ConfigDataFunction.java b/core/src/main/java/cc/carm/lib/configuration/function/ConfigDataFunction.java index 04d8cff..7571bcf 100644 --- a/core/src/main/java/cc/carm/lib/configuration/function/ConfigDataFunction.java +++ b/core/src/main/java/cc/carm/lib/configuration/function/ConfigDataFunction.java @@ -9,11 +9,11 @@ import java.util.Objects; @FunctionalInterface public interface ConfigDataFunction { - @NotNull R parse(@NotNull T data) throws Exception; + @NotNull R handle(@NotNull T data) throws Exception; default @NotNull ConfigDataFunction andThen(@NotNull ConfigDataFunction after) { Objects.requireNonNull(after); - return data -> after.parse(parse(data)); + return data -> after.handle(handle(data)); } @Contract(pure = true) diff --git a/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueHandler.java b/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueHandler.java new file mode 100644 index 0000000..165f471 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueHandler.java @@ -0,0 +1,67 @@ +package cc.carm.lib.configuration.function; + + +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.source.ConfigurationProvider; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +@FunctionalInterface +public interface ConfigValueHandler { + + @Nullable R handle(@NotNull ConfigurationProvider provider, @NotNull T data) throws Exception; + + default ConfigValueHandler andThen(@NotNull ConfigValueHandler after) { + Objects.requireNonNull(after); + return ((provider, data) -> { + R result = handle(provider, data); + if (result == null) return null; + else return after.handle(provider, result); + }); + } + + default ConfigValueHandler compose(@NotNull ConfigValueHandler before) { + Objects.requireNonNull(before); + return ((provider, data) -> { + T result = before.handle(provider, data); + if (result == null) return null; + return handle(provider, result); + }); + } + + default ConfigValueHandler compose(@NotNull ConfigDataFunction before) { + Objects.requireNonNull(before); + return ((provider, data) -> { + T result = before.handle(data); + return handle(provider, result); + }); + } + + @Contract(pure = true) + static @NotNull ConfigValueHandler identity() { + return (provider, input) -> input; + } + + @Contract(pure = true) + static @NotNull ConfigValueHandler toObject() { + return ConfigurationProvider::serialize; + } + + @Contract(pure = true) + static @NotNull ConfigValueHandler fromObject(ValueType type) { + return (provider, input) -> provider.deserialize(type, input); + } + + + @Contract(pure = true) + static @NotNull ConfigValueHandler required() { + return (provider, input) -> { + throw new IllegalArgumentException("Please specify the value parser."); + }; + } +} + + diff --git a/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueParser.java b/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueParser.java deleted file mode 100644 index 9554776..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/function/ConfigValueParser.java +++ /dev/null @@ -1,62 +0,0 @@ -package cc.carm.lib.configuration.function; - - -import cc.carm.lib.configuration.source.ConfigurationProvider; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Objects; - -@FunctionalInterface -public interface ConfigValueParser { - - @Nullable R parse(@NotNull ConfigurationProvider provider, - @NotNull T data, @Nullable R defaultValue) throws Exception; - - default ConfigValueParser andThen(@NotNull ConfigValueParser after) { - Objects.requireNonNull(after); - return ((provider, data, defaultValue) -> { - R result = parse(provider, data, null); - if (result == null) return defaultValue; - else return after.parse(provider, result, defaultValue); - }); - } - - default ConfigValueParser compose(@NotNull ConfigValueParser before) { - Objects.requireNonNull(before); - return ((provider, data, defaultValue) -> { - T result = before.parse(provider, data, null); - if (result == null) return null; - return parse(provider, result, defaultValue); - }); - } - - default ConfigValueParser compose(@NotNull ConfigDataFunction before) { - Objects.requireNonNull(before); - return ((provider, data, defaultValue) -> { - T result = before.parse(data); - return parse(provider, result, defaultValue); - }); - } - - @Contract(pure = true) - static @NotNull ConfigValueParser identity() { - return (provider, input, defaultValue) -> input; - } - - @Contract(pure = true) - static @NotNull ConfigValueParser toObject() { - return (provider, input, defaultValue) -> input; - } - - @Contract(pure = true) - static @NotNull ConfigValueParser required() { - return (provider, input, defaultValue) -> { - throw new IllegalArgumentException("Please specify the value parser."); - }; - } - -} - - diff --git a/core/src/main/java/cc/carm/lib/configuration/meta/PathMetadata.java b/core/src/main/java/cc/carm/lib/configuration/meta/PathMetadata.java new file mode 100644 index 0000000..a2df1b1 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/meta/PathMetadata.java @@ -0,0 +1,58 @@ +package cc.carm.lib.configuration.meta; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Function; +import java.util.function.Supplier; + +public class PathMetadata { + + public static PathMetadata of() { + return of(() -> null); + } + + public static PathMetadata of(T defaults) { + return of(() -> defaults); + } + + public static PathMetadata of(@NotNull Supplier<@Nullable T> defaults) { + return of(v -> defaults.get()); + } + + public static PathMetadata of(@NotNull Function defaults) { + return new PathMetadata<>(defaults); + } + + protected Function defaultFunction; + + public PathMetadata(@NotNull Function defaults) { + this.defaultFunction = defaults; + } + + public boolean isDefault(String path, @NotNull T value) { + return value.equals(defaults(path)); + } + + public boolean hasDefaults(String path) { + return defaults(path) != null; + } + + public T getDefault(String path, @Nullable T suppliedValue) { + T defaults = defaults(path); + return defaults == null ? suppliedValue : defaults; + } + + public @Nullable T defaults(String path) { + return defaultFunction.apply(path); + } + + public void setDefaults(Function defaultFunction) { + this.defaultFunction = defaultFunction; + } + + public void setDefaults(T value) { + setDefaults((v) -> value); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/option/ConfigurationOptions.java b/core/src/main/java/cc/carm/lib/configuration/option/ConfigurationOptions.java deleted file mode 100644 index 6e17d6c..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/option/ConfigurationOptions.java +++ /dev/null @@ -1,25 +0,0 @@ -package cc.carm.lib.configuration.option; - - -import cc.carm.lib.easyoptions.OptionType; - -import static cc.carm.lib.easyoptions.OptionType.of; - -public interface ConfigurationOptions { - - /** - * The configuration path separator. - */ - OptionType PATH_SEPARATOR = of('.'); - - /** - * Whether to set & save default values if offered and not exists in configuration. - */ - OptionType SET_DEFAULTS = of(true); - - /** - * Whether to load subclasses of configuration class. - */ - OptionType LOAD_SUB_CLASSES = of(true); - -} diff --git a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java index 2e7b229..3046267 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationFactory.java @@ -1,85 +1,84 @@ package cc.carm.lib.configuration.source; -import cc.carm.lib.configuration.adapter.ValueAdapter; import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; -import cc.carm.lib.configuration.function.ConfigDataFunction; -import cc.carm.lib.configuration.loader.ConfigurationLoader; -import cc.carm.lib.configuration.loader.PathGenerator; -import cc.carm.lib.easyoptions.OptionHolder; -import cc.carm.lib.easyoptions.OptionType; +import cc.carm.lib.configuration.source.loader.ConfigurationLoader; +import cc.carm.lib.configuration.source.loader.PathGenerator; +import cc.carm.lib.configuration.source.option.ConfigurationOption; +import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder; +import cc.carm.lib.configuration.source.section.ConfigurationSource; import org.jetbrains.annotations.NotNull; import java.util.function.Consumer; import java.util.function.Function; -public abstract class ConfigurationFactory

, C> { +public abstract class ConfigurationFactory, PROVIDER extends ConfigurationProvider, SELF> { - protected Function loaderFunction = p -> new ConfigurationLoader(); + protected Function loaderFunction = PROVIDER -> new ConfigurationLoader(); protected Consumer loaderConsumer = loader -> { }; protected ValueAdapterRegistry adapters = new ValueAdapterRegistry(); - protected OptionHolder options = new OptionHolder(); + protected ConfigurationOptionHolder options = new ConfigurationOptionHolder(); - public abstract C getThis(); + public abstract SELF self(); - public C loader(Function loaderFunction) { + public SELF loader(Function loaderFunction) { this.loaderFunction = loaderFunction; - return getThis(); + return self(); } - public C loader(ConfigurationLoader loader) { - return loader(p -> loader); + public SELF loader(ConfigurationLoader loader) { + return loader(PROVIDER -> loader); } - public C loader(Consumer loaderConsumer) { + public SELF loader(Consumer loaderConsumer) { this.loaderConsumer = this.loaderConsumer.andThen(loaderConsumer); - return getThis(); + return self(); } - public C pathGenerator(PathGenerator pathGenerator) { + public SELF pathGenerator(PathGenerator pathGenerator) { return loader(loader -> { loader.setPathGenerator(pathGenerator); }); } - public C adapters(ValueAdapterRegistry adapters) { + public SELF adapters(ValueAdapterRegistry adapters) { this.adapters = adapters; - return getThis(); + return self(); } - public C adapter(Consumer adapterRegistryConsumer) { + public SELF adapter(Consumer adapterRegistryConsumer) { adapterRegistryConsumer.accept(adapters); - return getThis(); + return self(); } - public C adapter(@NotNull ValueAdapter adapter) { - return adapter(a -> a.register(adapter)); - } +// public SELF adapter(@NotNull ValueAdapter adapter) { +// return adapter(a -> a.register(adapter)); +// } +// +// public SELF adapter(Class clazz, @NotNull ValueAdapter adapter) { +// return adapter(a -> a.register(clazz, adapter)); +// } +// +// public SELF adapter(Class baseClass, Class valueClass, +// ConfigDataFunction parser, ConfigDataFunction serializer) { +// return adapter(a -> a.register(baseClass, valueClass, parser, serializer)); +// } - public C adapter(Class clazz, @NotNull ValueAdapter adapter) { - return adapter(a -> a.register(clazz, adapter)); - } - - public C adapter(Class baseClass, Class valueClass, - ConfigDataFunction parser, ConfigDataFunction serializer) { - return adapter(a -> a.register(baseClass, valueClass, parser, serializer)); - } - - public C options(OptionHolder options) { + public SELF options(ConfigurationOptionHolder options) { this.options = options; - return getThis(); + return self(); } - public C option(Consumer optionsConsumer) { + public SELF option(Consumer optionsConsumer) { optionsConsumer.accept(options); - return getThis(); + return self(); } - public C option(OptionType option, O value) { + public SELF option(ConfigurationOption option, O value) { return option(o -> o.set(option, value)); } - public abstract @NotNull P build(); + public abstract @NotNull PROVIDER build(); } diff --git a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationProvider.java b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationProvider.java index 82cc98b..68f7097 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationProvider.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationProvider.java @@ -2,24 +2,36 @@ package cc.carm.lib.configuration.source; import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; -import cc.carm.lib.configuration.loader.ConfigurationLoader; -import cc.carm.lib.easyoptions.OptionHolder; -import cc.carm.lib.easyoptions.OptionType; +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.meta.PathMetadata; +import cc.carm.lib.configuration.source.loader.ConfigurationLoader; +import cc.carm.lib.configuration.source.option.ConfigurationOption; +import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder; +import cc.carm.lib.configuration.source.section.ConfigurationSource; +import cc.carm.lib.configuration.value.ValueManifest; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; public class ConfigurationProvider> { protected final @NotNull S source; protected final @NotNull ConfigurationLoader loader; protected final @NotNull ValueAdapterRegistry adapters; - protected final @NotNull OptionHolder options; + protected final @NotNull ConfigurationOptionHolder options; + protected final @NotNull Map, Object>> pathMetadata; public ConfigurationProvider(@NotNull S source, @NotNull ConfigurationLoader loader, - @NotNull ValueAdapterRegistry adapters, @NotNull OptionHolder options) { + @NotNull ValueAdapterRegistry adapters, + @NotNull ConfigurationOptionHolder options, + @NotNull Map, Object>> pathMetadata) { this.source = source; this.loader = loader; this.adapters = adapters; this.options = options; + this.pathMetadata = pathMetadata; } public @NotNull S source() { @@ -34,15 +46,15 @@ public class ConfigurationProvider> { source().save(); } - public OptionHolder options() { + public ConfigurationOptionHolder options() { return options; } - public @NotNull T option(@NotNull OptionType option) { + public @NotNull T option(@NotNull ConfigurationOption option) { return options.get(option); } - public void option(@NotNull OptionType option, @NotNull T value) { + public void option(@NotNull ConfigurationOption option, @NotNull T value) { options.set(option, value); } @@ -50,11 +62,117 @@ public class ConfigurationProvider> { return this.adapters; } - public ConfigurationLoader loader() { return loader; } + public @NotNull Map, Object>> pathMetadata() { + return pathMetadata; + } + + public @NotNull Map, Object> metadata(@NotNull String path) { + return pathMetadata().computeIfAbsent(path, k -> new java.util.HashMap<>()); + } + + /** + * Get the value of option. + * + * @param type {@link PathMetadata} + * @param defaultValue Default value if the value of option is not set. + * @param Value type + * @return Value of option + */ + @SuppressWarnings("unchecked") + @Contract("_,_, !null -> !null") + public @Nullable V meta(@NotNull String path, + @NotNull PathMetadata type, @Nullable V defaultValue) { + return (V) metadata(path).getOrDefault(type, type.getDefault(path, defaultValue)); + } + + /** + * Get the value of option. + * + * @param type {@link PathMetadata} + * @param Value type + * @return Value of option + */ + public @Nullable V meta(@NotNull String path, @NotNull PathMetadata type) { + return meta(path, type, null); + } + + public boolean hasMeta(@NotNull String path, @NotNull PathMetadata type) { + return metadata(path).containsKey(type) || type.hasDefaults(path); + } + + /** + * Set the value of meta, if the value is null, the meta will be removed. + *
Will only be changed in current holder. + * + * @param type {@link PathMetadata} + * @param value Value of meta + * @param Value type + * @return Previous value of meta + */ + @SuppressWarnings("unchecked") + public @Nullable V setMeta(@NotNull String path, @NotNull PathMetadata type, @Nullable V value) { + if (value == null || type.isDefault(path, value)) { + return (V) metadata(path).remove(type); + } else { + return (V) metadata(path).put(type, value); + } + } + + /** + * Set the value of meta, if the value is null, the meta will not be changed. + *
Will only be changed in current holder. + * + * @param type {@link PathMetadata} + * @param value Value of meta + * @param Value type + */ + public void setMetaIfAbsent(@NotNull String path, @NotNull PathMetadata type, @Nullable V value) { + if (value == null || type.isDefault(path, value)) { + metadata(path).remove(type); + } else { + metadata(path).putIfAbsent(type, value); + } + } + + /** + * Set the value of meta, if the value is null, the meta will not be changed. + *
Will only be changed in current holder. + * + * @param type {@link PathMetadata} + * @param value Value of meta + * @param Value type + */ + @SuppressWarnings("unchecked") + public @Nullable V setMetaIfPresent(@NotNull String path, @NotNull PathMetadata type, @Nullable V value) { + Object exists = metadata(path).get(type); + if (exists == null) return null; + + if (value == null || type.isDefault(path, value)) { + return (V) metadata(path).remove(type); + } else { + return (V) metadata(path).put(type, value); + } + } + + @Contract("_,null -> null") + public T deserialize(@NotNull Class type, @Nullable Object source) throws Exception { + return adapters().deserialize(this, type, source); + } + + @Contract("_,null -> null") + public T deserialize(@NotNull ValueType type, @Nullable Object source) throws Exception { + return adapters().deserialize(this, type, source); + } + + @Contract("null -> null") + public Object serialize(@Nullable T value) throws Exception { + return adapters().serialize(this, value); + } + public void load(Class configClass) { try { loader.load(this, configClass); @@ -71,4 +189,8 @@ public class ConfigurationProvider> { } } + public void load(@NotNull ValueManifest value) { + value.provider(this); + } + } diff --git a/core/src/main/java/cc/carm/lib/configuration/loader/ConfigurationLoader.java b/core/src/main/java/cc/carm/lib/configuration/source/loader/ConfigurationLoader.java similarity index 72% rename from core/src/main/java/cc/carm/lib/configuration/loader/ConfigurationLoader.java rename to core/src/main/java/cc/carm/lib/configuration/source/loader/ConfigurationLoader.java index d2d341a..7c4052f 100644 --- a/core/src/main/java/cc/carm/lib/configuration/loader/ConfigurationLoader.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/loader/ConfigurationLoader.java @@ -1,11 +1,14 @@ -package cc.carm.lib.configuration.loader; +package cc.carm.lib.configuration.source.loader; import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.source.ConfigurationProvider; -import cc.carm.lib.configuration.option.ConfigurationOptions; +import cc.carm.lib.configuration.source.option.ConfigurationOptions; +import cc.carm.lib.configuration.value.ConfigValue; +import cc.carm.lib.configuration.value.ValueManifest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.lang.reflect.Field; import java.util.Arrays; @@ -15,6 +18,20 @@ import java.util.Arrays; */ public class ConfigurationLoader { + public static final Field PATH_FIELD; + public static final Field PROVIDER_FIELD; + + static { + try { + PATH_FIELD = ValueManifest.class.getDeclaredField("path"); + PATH_FIELD.setAccessible(true); + PROVIDER_FIELD = ValueManifest.class.getDeclaredField("provider"); + PROVIDER_FIELD.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + protected PathGenerator pathGenerator; public ConfigurationLoader() { @@ -83,13 +100,15 @@ public class ConfigurationLoader { field.setAccessible(true); Object object = field.get(source); // -// if (object instanceof ConfigValue) { -// // 目标是 ConfigValue 实例,进行具体的初始化注入 -// -// } else - - if (source instanceof Configuration && object instanceof Configuration) { - // 当且仅当 源字段与字段 均为ConfigurationRoot实例时,才对目标字段进行下一步初始化加载。 + if (object instanceof ConfigValue) { + // 目标是 ConfigValue 实例,进行具体的初始化注入 + ConfigValue value = (ConfigValue) object; + String path = getFieldPath(provider, parent, field); + if (path == null) return; + insertIfAbsent(value, PATH_FIELD, path); + insertIfAbsent(value, PROVIDER_FIELD, provider); + } else if (source instanceof Configuration && object instanceof Configuration) { + // 当且仅当 源字段与字段 均为Configuration实例时,才对目标字段进行下一步初始化加载。 initializeInstance(provider, (Configuration) object, parent, field); } else if (source instanceof Class && object instanceof Class) { // 当且仅当 源字段与字段 均为静态类时,才对目标字段进行下一步初始化加载。 @@ -97,11 +116,18 @@ public class ConfigurationLoader { } // 以上判断实现以下规范: - // - 实例类中仅加载 ConfigValue实例 与 ConfigurationRoot实例 - // - 静态类中仅加载 静态ConfigValue实例 与 静态ConfigurationRoot类 + // - 实例类中仅加载 ConfigValue实例 与 Configuration实例 + // - 静态类中仅加载 静态ConfigValue实例 与 静态Configuration类 } catch (IllegalAccessException ignored) { } } + private void insertIfAbsent(@NotNull ValueManifest value, @NotNull Field field, @NotNull Object obj) { + try { + if (field.get(obj) == null) field.set(obj, value); + } catch (IllegalAccessException ignored) { + } + } + } diff --git a/core/src/main/java/cc/carm/lib/configuration/loader/PathGenerator.java b/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java similarity index 97% rename from core/src/main/java/cc/carm/lib/configuration/loader/PathGenerator.java rename to core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java index d2ad485..f7d508e 100644 --- a/core/src/main/java/cc/carm/lib/configuration/loader/PathGenerator.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/loader/PathGenerator.java @@ -1,4 +1,4 @@ -package cc.carm.lib.configuration.loader; +package cc.carm.lib.configuration.source.loader; import cc.carm.lib.configuration.source.ConfigurationProvider; import org.jetbrains.annotations.NotNull; diff --git a/core/src/main/java/cc/carm/lib/configuration/loader/StandardPathGenerator.java b/core/src/main/java/cc/carm/lib/configuration/source/loader/StandardPathGenerator.java similarity index 96% rename from core/src/main/java/cc/carm/lib/configuration/loader/StandardPathGenerator.java rename to core/src/main/java/cc/carm/lib/configuration/source/loader/StandardPathGenerator.java index 4513647..2612e0a 100644 --- a/core/src/main/java/cc/carm/lib/configuration/loader/StandardPathGenerator.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/loader/StandardPathGenerator.java @@ -1,8 +1,8 @@ -package cc.carm.lib.configuration.loader; +package cc.carm.lib.configuration.source.loader; import cc.carm.lib.configuration.annotation.ConfigPath; import cc.carm.lib.configuration.source.ConfigurationProvider; -import cc.carm.lib.configuration.option.ConfigurationOptions; +import cc.carm.lib.configuration.source.option.ConfigurationOptions; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOption.java b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOption.java new file mode 100644 index 0000000..fdc6ed4 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOption.java @@ -0,0 +1,46 @@ +package cc.carm.lib.configuration.source.option; + +import org.jetbrains.annotations.NotNull; + +public class ConfigurationOption { + + @SuppressWarnings("unchecked") + public static ConfigurationOption of(@NotNull T defaultValue) { + return of((Class) defaultValue.getClass(), defaultValue); + } + + public static ConfigurationOption of(@NotNull Class valueClazz, @NotNull T defaultValue) { + return new ConfigurationOption<>(valueClazz, defaultValue); + } + + private final @NotNull Class valueClazz; + private @NotNull V defaultValue; + + public ConfigurationOption(@NotNull Class valueClazz, @NotNull V defaultValue) { + this.valueClazz = valueClazz; + this.defaultValue = defaultValue; + } + + @NotNull + public Class valueClass() { + return this.valueClazz; + } + + public @NotNull V defaults() { + return defaultValue; + } + + /** + * Set the default value of option. + * + * @param defaultValue Default value + */ + public void defaults(@NotNull V defaultValue) { + this.defaultValue = defaultValue; + } + + public boolean isDefault(@NotNull V value) { + return value.equals(defaultValue); + } + +} \ No newline at end of file diff --git a/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptionHolder.java b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptionHolder.java new file mode 100644 index 0000000..abacb5d --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptionHolder.java @@ -0,0 +1,70 @@ +package cc.carm.lib.configuration.source.option; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; + +public class ConfigurationOptionHolder { + + public static @NotNull ConfigurationOptionHolder of(@NotNull Map, V> options) { + return new ConfigurationOptionHolder(new ConcurrentHashMap<>(options)); + } + + protected final Map, Object> options; + + public ConfigurationOptionHolder() { + this(new ConcurrentHashMap<>()); + } + + public ConfigurationOptionHolder(Map, Object> options) { + this.options = options; + } + + public @NotNull Map, Object> options() { + return options; + } + + /** + * Get the value of option. + * + * @param type {@link ConfigurationOption} + * @param Value type + * @return Value of option + */ + @SuppressWarnings("unchecked") + public @NotNull V get(@NotNull ConfigurationOption type) { + return Optional.ofNullable(options().get(type)).map(v -> (V) v).orElseGet(type::defaults); + } + + /** + * Set the value of option. + * + * @param type {@link ConfigurationOption} + * @param value Value of option + * @param Value type + * @return Previous value of option + */ + @SuppressWarnings("unchecked") + public @Nullable V set(@NotNull ConfigurationOption type, @Nullable V value) { + if (value == null) { + return (V) options().remove(type); + } else { + return (V) options().put(type, value); + } + } + + /** + * Set the value of option to option's {@link ConfigurationOption#defaults()}. + * + * @param type {@link ConfigurationOption} + * @param Value type + * @return Previous value of option + */ + public @Nullable V clear(@NotNull ConfigurationOption type) { + return set(type, null); + } + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptions.java b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptions.java new file mode 100644 index 0000000..377a273 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/source/option/ConfigurationOptions.java @@ -0,0 +1,33 @@ +package cc.carm.lib.configuration.source.option; + +import cc.carm.lib.configuration.Configuration; + +import static cc.carm.lib.configuration.source.option.ConfigurationOption.of; + +public interface ConfigurationOptions { + + /** + * The configuration path separator. + */ + ConfigurationOption PATH_SEPARATOR = of('.'); + + /** + * Whether to set & save default values if offered and not exists in configuration. + */ + ConfigurationOption SET_DEFAULTS = of(true); + + /** + * Whether to load subclasses of configuration class. + */ + ConfigurationOption LOAD_SUB_CLASSES = of(true); + + /** + * Whether to pre parse the config values. + *
if false, the values will be parsed when calling + * {@link cc.carm.lib.configuration.value.ConfigValue#get()} + *
if true, the values will be parsed when + * {@link cc.carm.lib.configuration.source.ConfigurationProvider#load(Configuration)}. + */ + ConfigurationOption PRELOAD = of(false); + +} diff --git a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSection.java b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSection.java similarity index 87% rename from core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSection.java rename to core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSection.java index c058695..088c1d8 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSection.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSection.java @@ -1,7 +1,6 @@ -package cc.carm.lib.configuration.source; +package cc.carm.lib.configuration.source.section; import cc.carm.lib.configuration.function.ConfigDataFunction; -import cc.carm.lib.configuration.function.ConfigValueParser; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,7 +11,9 @@ import java.util.*; public interface ConfigurationSection { @NotNull - Set getKeys(boolean deep); + default Set getKeys(boolean deep) { + return getValues(deep).keySet(); + } @NotNull Map getValues(boolean deep); @@ -40,22 +41,22 @@ public interface ConfigurationSection { return get(path, null, clazz); } - default @Nullable T get(@NotNull String path, @NotNull ConfigValueParser parser) { + default @Nullable T get(@NotNull String path, @NotNull ConfigDataFunction parser) { return get(path, null, parser); } @Contract("_,!null,_->!null") default @Nullable T get(@NotNull String path, @Nullable T defaultValue, @NotNull Class clazz) { - return get(path, defaultValue, ConfigValueParser.castObject(clazz)); + return get(path, defaultValue, ConfigDataFunction.castObject(clazz)); } @Contract("_,!null,_->!null") default @Nullable T get(@NotNull String path, @Nullable T defaultValue, - @NotNull ConfigValueParser parser) { + @NotNull ConfigDataFunction parser) { Object value = get(path); if (value != null) { try { - return parser.parse(value, defaultValue); + return parser.handle(value); } catch (Exception e) { e.printStackTrace(); } @@ -74,7 +75,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Boolean getBoolean(@NotNull String path, @Nullable Boolean def) { - return get(path, def, ConfigValueParser.booleanValue()); + return get(path, def, ConfigDataFunction.booleanValue()); } default @Nullable Boolean isByte(@NotNull String path) { @@ -87,7 +88,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Byte getByte(@NotNull String path, @Nullable Byte def) { - return get(path, def, ConfigValueParser.byteValue()); + return get(path, def, ConfigDataFunction.byteValue()); } default boolean isShort(@NotNull String path) { @@ -100,7 +101,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Short getShort(@NotNull String path, @Nullable Short def) { - return get(path, def, ConfigValueParser.shortValue()); + return get(path, def, ConfigDataFunction.shortValue()); } @@ -114,7 +115,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Integer getInt(@NotNull String path, @Nullable Integer def) { - return get(path, def, ConfigValueParser.intValue()); + return get(path, def, ConfigDataFunction.intValue()); } @@ -128,7 +129,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Long getLong(@NotNull String path, @Nullable Long def) { - return get(path, def, ConfigValueParser.longValue()); + return get(path, def, ConfigDataFunction.longValue()); } @@ -142,7 +143,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Float getFloat(@NotNull String path, @Nullable Float def) { - return get(path, def, ConfigValueParser.floatValue()); + return get(path, def, ConfigDataFunction.floatValue()); } @@ -156,7 +157,7 @@ public interface ConfigurationSection { @Contract("_, !null -> !null") default @Nullable Double getDouble(@NotNull String path, @Nullable Double def) { - return get(path, def, ConfigValueParser.doubleValue()); + return get(path, def, ConfigDataFunction.doubleValue()); } @@ -232,7 +233,7 @@ public interface ConfigurationSection { List values = new ArrayList<>(); for (Object o : list) { try { - values.add(parser.parse(o)); + values.add(parser.handle(o)); } catch (Exception ignored) { } } diff --git a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSource.java b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSource.java similarity index 54% rename from core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSource.java rename to core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSource.java index 72723ed..fd27553 100644 --- a/core/src/main/java/cc/carm/lib/configuration/source/ConfigurationSource.java +++ b/core/src/main/java/cc/carm/lib/configuration/source/section/ConfigurationSource.java @@ -1,10 +1,9 @@ -package cc.carm.lib.configuration.source; +package cc.carm.lib.configuration.source.section; import org.jetbrains.annotations.NotNull; -import java.util.Set; - -public abstract class ConfigurationSource, O> implements ConfigurationSection { +public abstract class ConfigurationSource, ORIGINAL> + implements ConfigurationSection { protected long updateMillis; @@ -17,25 +16,23 @@ public abstract class ConfigurationSource, O this.updateMillis = System.currentTimeMillis(); } - protected abstract S getThis(); + protected abstract SELF self(); + + /** + * @return Original configuration object + */ + public abstract @NotNull ORIGINAL original(); public abstract void save() throws Exception; protected abstract void onReload() throws Exception; - public abstract @NotNull O original(); - - @NotNull - public Set getKeys(boolean deep) { - return getValues(deep).keySet(); - } - public long getUpdateMillis() { return this.updateMillis; } - public boolean isExpired(long time) { - return getUpdateMillis() > time; + public boolean isExpired(long parsedTime) { + return getUpdateMillis() > parsedTime; } } diff --git a/core/src/main/java/cc/carm/lib/configuration/value/ConfigValue.java b/core/src/main/java/cc/carm/lib/configuration/value/ConfigValue.java index e2901d9..c198c18 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/ConfigValue.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/ConfigValue.java @@ -9,12 +9,8 @@ import java.util.Optional; public abstract class ConfigValue extends ValueManifest { -// public static @NotNull ConfigBuilder builder() { -// return new ConfigBuilder(); -// } - protected ConfigValue(@NotNull ValueManifest manifest) { - super(manifest.metadata, manifest.provider, manifest.defaultSupplier); + super(manifest.type, manifest.provider, manifest.path, manifest.defaultSupplier); } /** @@ -41,7 +37,7 @@ public abstract class ConfigValue extends ValueManifest { * @throws NullPointerException 对应数据为空时抛出 */ public @NotNull T getNotNull() { - return Objects.requireNonNull(getOrDefault(), "Value(" + path() + ") is null."); + return Objects.requireNonNull(getOrDefault(), "Value(" + path() + ") [" + type() + "] is null."); } public @NotNull Optional<@Nullable T> optional() { diff --git a/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java b/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java index fb4b36d..f508cd7 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/ValueManifest.java @@ -1,30 +1,56 @@ package cc.carm.lib.configuration.value; +import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.source.ConfigurationProvider; -import cc.carm.lib.configuration.source.ConfigurationSource; -import cc.carm.lib.configuration.value.meta.ValueMetaList; -import cc.carm.lib.configuration.value.meta.ValueMetaType; -import org.jetbrains.annotations.Contract; +import cc.carm.lib.configuration.source.section.ConfigurationSource; +import cc.carm.lib.configuration.meta.PathMetadata; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.lang.reflect.Type; import java.util.Map; import java.util.function.Supplier; public class ValueManifest { - protected final @NotNull Map, Object> metadata; + protected final @NotNull ValueType type; protected @Nullable ConfigurationProvider provider; + protected @Nullable String path; // Section path + protected @NotNull Supplier<@Nullable T> defaultSupplier; - public ValueManifest(@NotNull Map, Object> metadata, - @Nullable ConfigurationProvider provider, @NotNull Supplier<@Nullable T> defaultSupplier) { - this.metadata = metadata; + public ValueManifest(ValueType type) { + this(type, null, null, () -> null); + } + + public ValueManifest(@NotNull T defaultValue) { + this(ValueType.of(defaultValue), null, null, () -> defaultValue); + } + + public ValueManifest(@NotNull ValueType type, @NotNull Supplier<@Nullable T> defaultSupplier) { + this(type, null, null, defaultSupplier); + } + + public ValueManifest(@NotNull ValueType type, + @Nullable ConfigurationProvider provider, @Nullable String path, + @NotNull Supplier<@Nullable T> defaultSupplier) { + this.type = type; this.provider = provider; + this.path = path; this.defaultSupplier = defaultSupplier; } + public @NotNull ValueType type() { + return this.type; + } + + public void provider(@NotNull ConfigurationProvider provider) { + this.provider = provider; + } + + public void path(@NotNull String path) { + this.path = path; + } + public @Nullable T defaults() { return this.defaultSupplier.get(); } @@ -37,6 +63,15 @@ public class ValueManifest { this.defaultSupplier = defaultValue; } + public boolean hasDefaults() { + return this.defaultSupplier.get() != null; + } + + public @NotNull String path() { + if (path != null) return path; + else throw new IllegalStateException("No section path provided."); + } + public @NotNull ConfigurationProvider provider() { if (this.provider != null) return this.provider; throw new IllegalStateException("Value does not have a provider."); @@ -46,106 +81,16 @@ public class ValueManifest { return provider().source(); } - public @NotNull String path() { - String path = getMeta(ValueMetaList.PATH); - if (path != null) return path; - else throw new IllegalStateException("No section path provided."); - } - - protected Object getValue() { + protected Object getData() { return config().get(path()); } - protected void setValue(@Nullable Object value) { + protected void setData(@Nullable Object value) { config().set(path(), value); } - public Map, Object> metadata() { - return metadata; + public Map, Object> metadata() { + return provider().metadata(path()); } - /** - * Get the value of option. - * - * @param type {@link ValueMetaType} - * @param defaultValue Default value if the value of option is not set. - * @param Value type - * @return Value of option - */ - @SuppressWarnings("unchecked") - @Contract("_, !null -> !null") - public @Nullable V getMeta(@NotNull ValueMetaType type, @Nullable V defaultValue) { - return (V) metadata().getOrDefault(type, type.getDefault(this, defaultValue)); - } - - /** - * Get the value of option. - * - * @param type {@link ValueMetaType} - * @param Value type - * @return Value of option - */ - public @Nullable V getMeta(@NotNull ValueMetaType type) { - return getMeta(type, null); - } - - public boolean hasMeta(@NotNull ValueMetaType type) { - return metadata().containsKey(type) || type.hasDefaults(this); - } - - /** - * Set the value of meta, if the value is null, the meta will be removed. - *
Will only be changed in current holder. - * - * @param type {@link ValueMetaType} - * @param value Value of meta - * @param Value type - * @return Previous value of meta - */ - @SuppressWarnings("unchecked") - public @Nullable V setMeta(@NotNull ValueMetaType type, @Nullable V value) { - if (value == null || type.isDefault(this, value)) { - return (V) metadata().remove(type); - } else { - return (V) metadata().put(type, value); - } - } - - /** - * Set the value of meta, if the value is null, the meta will not be changed. - *
Will only be changed in current holder. - * - * @param type {@link ValueMetaType} - * @param value Value of meta - * @param Value type - */ - public void setMetaIfAbsent(@NotNull ValueMetaType type, @Nullable V value) { - if (value == null || type.isDefault(this, value)) { - metadata().remove(type); - } else { - metadata().putIfAbsent(type, value); - } - } - - /** - * Set the value of meta, if the value is null, the meta will not be changed. - *
Will only be changed in current holder. - * - * @param type {@link ValueMetaType} - * @param value Value of meta - * @param Value type - */ - @SuppressWarnings("unchecked") - public @Nullable V setMetaIfPresent(@NotNull ValueMetaType type, @Nullable V value) { - Object exists = metadata().get(type); - if (exists == null) return null; - - if (value == null || type.isDefault(this, value)) { - return (V) metadata().remove(type); - } else { - return (V) metadata().put(type, value); - } - } - - } diff --git a/core/src/main/java/cc/carm/lib/configuration/value/impl/CachedConfigValue.java b/core/src/main/java/cc/carm/lib/configuration/value/impl/CachedConfigValue.java index 6cd50ea..13b852d 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/impl/CachedConfigValue.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/impl/CachedConfigValue.java @@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class CachedConfigValue extends ConfigValue { - + protected @Nullable T cachedValue; protected long parsedTime = -1; @@ -30,13 +30,24 @@ public abstract class CachedConfigValue extends ConfigValue { } protected final T getDefaultFirst(@Nullable T value) { - return updateCache(this.defaultSupplier == null ? value : this.defaultSupplier); + return updateCache(this.defaults() == null ? value : this.defaults()); } + /** + * Get the cached value or the default value if the cached value is null + * + * @return the cached value or the default value + */ protected @Nullable T getCachedOrDefault() { return getCachedOrDefault(null); } + /** + * Get the cached value or the default value if the cached value is null + * + * @param emptyValue the value to return if the cached value and the default value are null + * @return the cached value or the default value + */ @Contract("!null->!null") protected T getCachedOrDefault(@Nullable T emptyValue) { if (getCachedValue() != null) return getCachedValue(); diff --git a/core/src/main/java/cc/carm/lib/configuration/value/impl/ConfigValueMap.java b/core/src/main/java/cc/carm/lib/configuration/value/impl/ConfigValueMap.java deleted file mode 100644 index e4f8c8b..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/impl/ConfigValueMap.java +++ /dev/null @@ -1,213 +0,0 @@ -//package cc.carm.lib.configuration.value.impl; -// -//import cc.carm.lib.configuration.builder.map.ConfigMapCreator; -//import cc.carm.lib.configuration.function.ConfigDataFunction; -//import cc.carm.lib.configuration.value.ValueManifest; -//import org.jetbrains.annotations.NotNull; -//import org.jetbrains.annotations.Nullable; -//import org.jetbrains.annotations.Unmodifiable; -// -//import java.util.*; -//import java.util.function.Consumer; -//import java.util.function.Function; -//import java.util.function.Supplier; -// -//public abstract class ConfigValueMap extends CachedConfigValue> implements Map { -// -// public static @NotNull ConfigMapCreator builderOf(@NotNull Class keyClass, -// @NotNull Class valueClass) { -// return builder().asMap(keyClass, valueClass); -// } -// -// protected final @NotNull Supplier> supplier; -// -// protected final @NotNull Class sourceClass; -// protected final @NotNull Class keyClass; -// protected final @NotNull Class valueClass; -// -// protected final @NotNull ConfigDataFunction keyParser; -// protected final @NotNull ConfigDataFunction valueParser; -// -// protected final @NotNull ConfigDataFunction keySerializer; -// protected final @NotNull ConfigDataFunction valueSerializer; -// -// -// protected ConfigValueMap(@NotNull ValueManifest> manifest, @NotNull Class sourceClass, -// @NotNull Supplier> mapObjSupplier, -// @NotNull Class keyClass, @NotNull ConfigDataFunction keyParser, -// @NotNull Class valueClass, @NotNull ConfigDataFunction valueParser, -// @NotNull ConfigDataFunction keySerializer, -// @NotNull ConfigDataFunction valueSerializer) { -// super(manifest); -// this.supplier = mapObjSupplier; -// this.sourceClass = sourceClass; -// this.keyClass = keyClass; -// this.valueClass = valueClass; -// this.keyParser = keyParser; -// this.valueParser = valueParser; -// this.keySerializer = keySerializer; -// this.valueSerializer = valueSerializer; -// } -// -// public @NotNull Class getSourceClass() { -// return sourceClass; -// } -// -// public @NotNull Class getKeyClass() { -// return keyClass; -// } -// -// public @NotNull Class getValueClass() { -// return valueClass; -// } -// -// public @NotNull ConfigDataFunction getKeyParser() { -// return keyParser; -// } -// -// public @NotNull ConfigDataFunction getValueParser() { -// return valueParser; -// } -// -// public @NotNull ConfigDataFunction getKeySerializer() { -// return keySerializer; -// } -// -// public @NotNull ConfigDataFunction getValueSerializer() { -// return valueSerializer; -// } -// -// public abstract S getSource(ConfigurationWrapper section, String dataKey); -// -// @Override -// public @NotNull Map get() { -// if (!isExpired()) return getCachedOrDefault(supplier.get()); -// -// // 已过时的数据,需要重新解析一次。 -// Map map = supplier.get(); -// -// ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath()); -// if (section == null) return getDefaultFirst(map); -// -// Set keys = section.getKeys(false); -// if (keys.isEmpty()) return getDefaultFirst(map); -// -// for (String dataKey : keys) { -// S dataVal = getSource(section, dataKey); -// if (dataVal == null) continue; -// try { -// K key = keyParser.parse(dataKey); -// V value = valueParser.parse(dataVal); -// map.put(key, value); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// -// return updateCache(map); -// } -// -// @Override -// public V get(Object key) { -// return get().get(key); -// } -// -// public V getNotNull(Object key) { -// return Objects.requireNonNull(get(key)); -// } -// -// @Override -// public void set(@Nullable Map value) { -// updateCache(value); -// if (value == null) setValue(null); -// else { -// Map data = new LinkedHashMap<>(); -// for (Map.Entry entry : value.entrySet()) { -// try { -// data.put( -// keySerializer.parse(entry.getKey()), -// valueSerializer.parse(entry.getValue()) -// ); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// setValue(data); -// } -// } -// -// public @NotNull T modifyValue(Function, T> function) { -// Map m = get(); -// T result = function.apply(m); -// set(m); -// return result; -// } -// -// public @NotNull Map modifyMap(Consumer> consumer) { -// Map m = get(); -// consumer.accept(m); -// set(m); -// return m; -// } -// -// @Override -// public int size() { -// return get().size(); -// } -// -// @Override -// public boolean isEmpty() { -// return get().isEmpty(); -// } -// -// @Override -// public boolean containsKey(Object key) { -// return get().containsKey(key); -// } -// -// @Override -// public boolean containsValue(Object value) { -// return get().containsValue(value); -// } -// -// @Nullable -// @Override -// public V put(K key, V value) { -// return modifyValue(m -> m.put(key, value)); -// } -// -// @Override -// public V remove(Object key) { -// return modifyValue(m -> m.remove(key)); -// } -// -// @Override -// public void putAll(@NotNull Map m) { -// modifyMap(map -> map.putAll(m)); -// } -// -// @Override -// public void clear() { -// modifyMap(Map::clear); -// } -// -// @NotNull -// @Override -// public Set keySet() { -// return get().keySet(); -// } -// -// @NotNull -// @Override -// public Collection values() { -// return get().values(); -// } -// -// @NotNull -// @Override -// @Unmodifiable -// public Set> entrySet() { -// return get().entrySet(); -// } -// -//} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaList.java b/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaList.java deleted file mode 100644 index abd0614..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaList.java +++ /dev/null @@ -1,11 +0,0 @@ -package cc.carm.lib.configuration.value.meta; - -public interface ValueMetaList { - - /** - * The value path in configuration. - * Also see {@link cc.carm.lib.configuration.option.ConfigurationOptions#PATH_SEPARATOR} - */ - ValueMetaType PATH = ValueMetaType.of(); - -} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaType.java b/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaType.java deleted file mode 100644 index 6c5d825..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/meta/ValueMetaType.java +++ /dev/null @@ -1,59 +0,0 @@ -package cc.carm.lib.configuration.value.meta; - -import cc.carm.lib.configuration.value.ValueManifest; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Function; -import java.util.function.Supplier; - -public class ValueMetaType { - - public static ValueMetaType of() { - return of(() -> null); - } - - public static ValueMetaType of(T defaults) { - return of(() -> defaults); - } - - public static ValueMetaType of(@NotNull Supplier<@Nullable T> defaults) { - return of(v -> defaults.get()); - } - - public static ValueMetaType of(@NotNull Function, @Nullable T> defaults) { - return new ValueMetaType<>(defaults); - } - - protected Function, @Nullable T> defaultFunction; - - public ValueMetaType(@NotNull Function, @Nullable T> defaults) { - this.defaultFunction = defaults; - } - - public boolean isDefault(ValueManifest manifest, @NotNull T value) { - return value.equals(defaults(manifest)); - } - - public boolean hasDefaults(ValueManifest manifest) { - return defaults(manifest) != null; - } - - public T getDefault(ValueManifest manifest, @Nullable T suppliedValue) { - T defaults = defaults(manifest); - return defaults == null ? suppliedValue : defaults; - } - - public @Nullable T defaults(ValueManifest manifest) { - return defaultFunction.apply(manifest); - } - - public void setDefaults(Function, T> defaultFunction) { - this.defaultFunction = defaultFunction; - } - - public void setDefaults(T value) { - setDefaults((v) -> value); - } - -} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredList.java b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredList.java index b7c9713..e5907ff 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredList.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredList.java @@ -1,229 +1,231 @@ -//package cc.carm.lib.configuration.value.standard; -// -//import cc.carm.lib.configuration.builder.list.ConfigListBuilder; -//import cc.carm.lib.configuration.function.ConfigDataFunction; -//import cc.carm.lib.configuration.value.ValueManifest; -//import cc.carm.lib.configuration.value.impl.CachedConfigValue; -//import org.jetbrains.annotations.NotNull; -//import org.jetbrains.annotations.Nullable; -// -//import java.util.*; -//import java.util.function.Consumer; -//import java.util.function.Function; -// -//public class ConfiguredList extends CachedConfigValue> implements List { -// -// public static @NotNull ConfigListBuilder builderOf(@NotNull Class valueClass) { -// return builder().asList(valueClass); -// } -// -// public static @NotNull ConfiguredList of(@NotNull Class valueClass, @NotNull Collection defaults) { -// return builderOf(valueClass).fromObject().defaults(defaults).build(); -// } -// -// @SafeVarargs -// public static @NotNull ConfiguredList of(@NotNull Class valueClass, @NotNull V... defaults) { -// return builderOf(valueClass).fromObject().defaults(defaults).build(); -// } -// -// @SafeVarargs -// @SuppressWarnings("unchecked") -// public static @NotNull ConfiguredList of(@NotNull V defaultValue, @NotNull V... moreDefaults) { -// Collection values = new ArrayList<>(); -// values.add(defaultValue); -// values.addAll(Arrays.asList(moreDefaults)); -// return of((Class) defaultValue.getClass(), values); -// } -// -// protected final @NotNull Class valueClass; -// -// protected final @NotNull ConfigDataFunction parser; -// protected final @NotNull ConfigDataFunction serializer; -// -// public ConfiguredList(@NotNull ValueManifest> manifest, @NotNull Class valueClass, -// @NotNull ConfigDataFunction parser, -// @NotNull ConfigDataFunction serializer) { -// super(manifest); -// this.valueClass = valueClass; -// this.parser = parser; -// this.serializer = serializer; -// } -// -// @Override -// public @NotNull List get() { -// if (!isExpired()) return getCachedOrDefault(new ArrayList<>()); -// // Data that is outdated and needs to be parsed again. -// List list = new ArrayList<>(); -// List data = getConfiguration().contains(getConfigPath()) ? -// getConfiguration().getList(getConfigPath()) : null; -// if (data == null) return getDefaultFirst(list); -// for (Object dataVal : data) { -// if (dataVal == null) continue; -// try { -// list.add(parser.parse(dataVal)); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// return updateCache(list); -// } -// -// @Override -// public V get(int index) { -// return get().get(index); -// } -// -// public @NotNull List copy() { -// return new ArrayList<>(get()); -// } -// -// public @NotNull T handle(Function, T> function) { -// List list = get(); -// T result = function.apply(list); -// set(list); -// return result; -// } -// -// public @NotNull List modify(Consumer> consumer) { -// List list = get(); -// consumer.accept(list); -// set(list); -// return list; -// } -// -// @Override -// public void set(@Nullable List value) { -// updateCache(value); -// if (value == null) setValue(null); -// else { -// List data = new ArrayList<>(); -// for (V val : value) { -// if (val == null) continue; -// try { -// data.add(serializer.parse(val)); -// } catch (Exception ex) { -// ex.printStackTrace(); -// } -// } -// setValue(data); -// } -// } -// -// @Override -// public V set(int index, V element) { -// return handle(list -> list.set(index, element)); -// } -// -// @Override -// public int size() { -// return get().size(); -// } -// -// @Override -// public boolean isEmpty() { -// return get().isEmpty(); -// } -// -// @Override -// public boolean contains(Object o) { -// return get().contains(o); -// } -// -// @NotNull -// @Override -// public Iterator iterator() { -// return get().iterator(); -// } -// -// @NotNull -// @Override -// public Object @NotNull [] toArray() { -// return get().toArray(); -// } -// -// @NotNull -// @Override -// public T @NotNull [] toArray(@NotNull T[] a) { -// return get().toArray(a); -// } -// -// @Override -// public boolean containsAll(@NotNull Collection c) { -// return new HashSet<>(get()).containsAll(c); -// } -// -// @Override -// public boolean add(V v) { -// handle(list -> list.add(v)); -// return true; -// } -// -// @Override -// public void add(int index, V element) { -// modify(list -> list.add(index, element)); -// } -// -// @Override -// public boolean addAll(@NotNull Collection c) { -// return handle(list -> list.addAll(c)); -// } -// -// @Override -// public boolean addAll(int index, @NotNull Collection c) { -// return handle(list -> list.addAll(index, c)); -// } -// -// @Override -// public boolean remove(Object o) { -// return handle(list -> list.remove(o)); -// } -// -// @Override -// public V remove(int index) { -// return handle(list -> list.remove(index)); -// } -// -// @Override -// public boolean removeAll(@NotNull Collection c) { -// return handle(list -> list.removeAll(c)); -// } -// -// @Override -// public boolean retainAll(@NotNull Collection c) { -// return handle(list -> list.retainAll(c)); -// } -// -// @Override -// public void clear() { -// modify(List::clear); -// } -// -// @Override -// public int indexOf(Object o) { -// return get().indexOf(o); -// } -// -// @Override -// public int lastIndexOf(Object o) { -// return get().lastIndexOf(o); -// } -// -// @NotNull -// @Override -// public ListIterator listIterator() { -// return get().listIterator(); -// } -// -// @NotNull -// @Override -// public ListIterator listIterator(int index) { -// return get().listIterator(index); -// } -// -// @NotNull -// @Override -// public List subList(int fromIndex, int toIndex) { -// return get().subList(fromIndex, toIndex); -// } -// -//} +package cc.carm.lib.configuration.value.standard; + +import cc.carm.lib.configuration.adapter.ValueParser; +import cc.carm.lib.configuration.adapter.ValueSerializer; +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.value.ValueManifest; +import cc.carm.lib.configuration.value.impl.CachedConfigValue; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; + +public class ConfiguredList extends CachedConfigValue> implements List { + + protected final @NotNull ValueType valueType; + protected final @Nullable ValueParser parser; + protected final @Nullable ValueSerializer serializer; + + private ConfiguredList(@NotNull ValueManifest> manifest, @NotNull ValueType valueType, + @Nullable ValueParser parser, @Nullable ValueSerializer serializer) { + super(manifest); + this.valueType = valueType; + this.parser = parser; + this.serializer = serializer; + } + + /** + * @return Value's parser, parse base object to value. + */ + public @Nullable ValueParser parser() { + return parser; + } + + /** + * @return Value's serializer, parse value to base object. + */ + public @Nullable ValueSerializer serializer() { + return serializer; + } + + public @NotNull ValueType valueType() { + return valueType; + } + + @Override + public @NotNull List get() { + if (!isExpired()) return getCachedOrDefault(new ArrayList<>()); + // Data that is outdated and needs to be parsed again. + List list = new ArrayList<>(); + List data = config().contains(path()) ? config().getList(path()) : null; + if (data == null) return getDefaultFirst(list); + + ValueParser parser = this.parser; + if (parser == null) return getDefaultFirst(list); + + for (Object dataVal : data) { + if (dataVal == null) continue; + try { + list.add(parser.deserialize(provider(), valueType(), dataVal)); + } catch (Exception e) { + e.printStackTrace(); + } + } + return updateCache(list); + } + + @Override + public void set(@Nullable List value) { + updateCache(value); + if (value == null) { + setData(null); + return; + } + + ValueSerializer serializer = serializer(); + if (serializer == null) return; + List data = new ArrayList<>(); + for (V val : value) { + if (val == null) continue; + try { + data.add(serializer.serialize(provider(), valueType, val)); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + setData(data); + } + + @Override + public V get(int index) { + return getNotNull().get(index); + } + + public @NotNull List copy() { + return new ArrayList<>(getNotNull()); + } + + public @NotNull T handle(Function, T> function) { + List list = getNotNull(); + T result = function.apply(list); + set(list); + return result; + } + + public @NotNull ConfiguredList modify(Consumer> consumer) { + List list = getNotNull(); + consumer.accept(list); + set(list); + return this; + } + + @Override + public V set(int index, V element) { + return handle(list -> list.set(index, element)); + } + + @Override + public int size() { + return getNotNull().size(); + } + + @Override + public boolean isEmpty() { + return getNotNull().isEmpty(); + } + + @Override + public boolean contains(Object o) { + return getNotNull().contains(o); + } + + @NotNull + @Override + public Iterator iterator() { + return getNotNull().iterator(); + } + + @NotNull + @Override + public Object @NotNull [] toArray() { + return getNotNull().toArray(); + } + + @NotNull + @Override + public T @NotNull [] toArray(@NotNull T[] a) { + return getNotNull().toArray(a); + } + + @Override + public boolean containsAll(@NotNull Collection c) { + return new HashSet<>(getNotNull()).containsAll(c); + } + + @Override + public boolean add(V v) { + handle(list -> list.add(v)); + return true; + } + + @Override + public void add(int index, V element) { + modify(list -> list.add(index, element)); + } + + @Override + public boolean addAll(@NotNull Collection c) { + return handle(list -> list.addAll(c)); + } + + @Override + public boolean addAll(int index, @NotNull Collection c) { + return handle(list -> list.addAll(index, c)); + } + + @Override + public boolean remove(Object o) { + return handle(list -> list.remove(o)); + } + + @Override + public V remove(int index) { + return handle(list -> list.remove(index)); + } + + @Override + public boolean removeAll(@NotNull Collection c) { + return handle(list -> list.removeAll(c)); + } + + @Override + public boolean retainAll(@NotNull Collection c) { + return handle(list -> list.retainAll(c)); + } + + @Override + public void clear() { + modify(List::clear); + } + + @Override + public int indexOf(Object o) { + return getNotNull().indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return getNotNull().lastIndexOf(o); + } + + @NotNull + @Override + public ListIterator listIterator() { + return getNotNull().listIterator(); + } + + @NotNull + @Override + public ListIterator listIterator(int index) { + return getNotNull().listIterator(index); + } + + @NotNull + @Override + public List subList(int fromIndex, int toIndex) { + return getNotNull().subList(fromIndex, toIndex); + } + +} \ No newline at end of file diff --git a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredMap.java b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredMap.java deleted file mode 100644 index 1513734..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredMap.java +++ /dev/null @@ -1,27 +0,0 @@ -//package cc.carm.lib.configuration.value.standard; -// -//import cc.carm.lib.configuration.function.ConfigDataFunction; -//import cc.carm.lib.configuration.value.ValueManifest; -//import cc.carm.lib.configuration.value.impl.ConfigValueMap; -//import org.jetbrains.annotations.NotNull; -// -//import java.util.Map; -//import java.util.function.Supplier; -// -//public class ConfiguredMap extends ConfigValueMap { -// -// public ConfiguredMap(@NotNull ValueManifest> manifest, -// @NotNull Supplier> mapObjSupplier, -// @NotNull Class keyClass, @NotNull ConfigDataFunction keyParser, -// @NotNull Class valueClass, @NotNull ConfigDataFunction valueParser, -// @NotNull ConfigDataFunction keySerializer, -// @NotNull ConfigDataFunction valueSerializer) { -// super(manifest, Object.class, mapObjSupplier, keyClass, keyParser, valueClass, valueParser, keySerializer, valueSerializer); -// } -// -// @Override -// public Object getSource(ConfigurationWrapper section, String dataKey) { -// return section.get(dataKey); -// } -// -//} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSection.java b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSection.java deleted file mode 100644 index 2630953..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSection.java +++ /dev/null @@ -1,96 +0,0 @@ -//package cc.carm.lib.configuration.value.standard; -// -//import cc.carm.lib.configuration.builder.value.SectionValueBuilder; -//import cc.carm.lib.configuration.function.ConfigDataFunction; -//import cc.carm.lib.configuration.function.ConfigValueParser; -//import cc.carm.lib.configuration.value.ValueManifest; -//import cc.carm.lib.configuration.value.impl.CachedConfigValue; -//import org.jetbrains.annotations.NotNull; -//import org.jetbrains.annotations.Nullable; -// -//import java.util.Map; -// -//public class ConfiguredSection extends CachedConfigValue { -// -// public static @NotNull SectionValueBuilder builderOf(@NotNull Class valueClass) { -// return builder().asValue(valueClass).fromSection(); -// } -// -// protected final @NotNull Class valueClass; -// -// protected final @NotNull ConfigValueParser, V> parser; -// protected final @NotNull ConfigDataFunction> serializer; -// -// public ConfiguredSection(@NotNull ValueManifest manifest, @NotNull Class valueClass, -// @NotNull ConfigValueParser, V> parser, -// @NotNull ConfigDataFunction> serializer) { -// super(manifest); -// this.valueClass = valueClass; -// this.parser = parser; -// this.serializer = serializer; -// } -// -// /** -// * @return Value's type class -// */ -// public @NotNull Class getValueClass() { -// return valueClass; -// } -// -// /** -// * @return Value's parser, cast value from section. -// */ -// public @NotNull ConfigValueParser, V> getParser() { -// return parser; -// } -// -// /** -// * @return Value's serializer, serialize value to section. -// */ -// public @NotNull ConfigDataFunction> getSerializer() { -// return serializer; -// } -// -// /** -// * @return Get the value that parsed from the configuration section. -// */ -// @Override -// public @Nullable V get() { -// if (!isExpired()) return getCachedOrDefault(); -// // Data that is outdated and needs to be parsed again. -// -// ConfigurationWrapper section = getConfiguration().getConfigurationSection(getConfigPath()); -// if (section == null) return getDefaultValue(); -// -// try { -// // If there are no errors, update the cache and return. -// return updateCache(this.parser.parse(section, this.defaultValue)); -// } catch (Exception e) { -// // There was a parsing error, prompted and returned the default value. -// e.printStackTrace(); -// return getDefaultValue(); -// } -// -// } -// -// /** -// * Use the specified value to update the configuration section. -// * Will use {@link #getSerializer()} to serialize the value to section. -// * -// * @param value The value that needs to be set in the configuration. -// */ -// @Override -// public void set(V value) { -// updateCache(value); -// if (value == null) setValue(null); -// else { -// try { -// setValue(serializer.parse(value)); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } -// -// -//} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSectionMap.java b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSectionMap.java deleted file mode 100644 index 82434df..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredSectionMap.java +++ /dev/null @@ -1,31 +0,0 @@ -//package cc.carm.lib.configuration.value.standard; -// -//import cc.carm.lib.configuration.function.ConfigDataFunction; -//import cc.carm.lib.configuration.value.ValueManifest; -//import cc.carm.lib.configuration.value.impl.ConfigValueMap; -//import org.jetbrains.annotations.NotNull; -// -//import java.util.Map; -//import java.util.function.Supplier; -// -//public class ConfiguredSectionMap extends ConfigValueMap> { -// -// public ConfiguredSectionMap(@NotNull ValueManifest> manifest, -// @NotNull Supplier> mapObjSupplier, -// @NotNull Class keyClass, @NotNull ConfigDataFunction keyParser, -// @NotNull Class valueClass, @NotNull ConfigDataFunction, V> valueParser, -// @NotNull ConfigDataFunction keySerializer, -// @NotNull ConfigDataFunction> valueSerializer) { -// super( -// manifest, ConfigurationWrapper.class, mapObjSupplier, -// keyClass, keyParser, valueClass, valueParser, -// keySerializer, valueSerializer.andThen(s -> (Object) s) -// ); -// } -// -// @Override -// public ConfigurationWrapper getSource(ConfigurationWrapper section, String dataKey) { -// return section.getConfigurationSection(dataKey); -// } -// -//} diff --git a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredValue.java b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredValue.java index 5117d26..d444034 100644 --- a/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredValue.java +++ b/core/src/main/java/cc/carm/lib/configuration/value/standard/ConfiguredValue.java @@ -1,62 +1,79 @@ package cc.carm.lib.configuration.value.standard; -import cc.carm.lib.configuration.function.ConfigDataFunction; -import cc.carm.lib.configuration.function.ConfigValueParser; +import cc.carm.lib.configuration.adapter.ValueParser; +import cc.carm.lib.configuration.adapter.ValueSerializer; +import cc.carm.lib.configuration.adapter.ValueType; +import cc.carm.lib.configuration.builder.value.ConfigValueBuilder; +import cc.carm.lib.configuration.source.ConfigurationProvider; import cc.carm.lib.configuration.value.ValueManifest; import cc.carm.lib.configuration.value.impl.CachedConfigValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Supplier; public class ConfiguredValue extends CachedConfigValue { -// public static ConfigValueBuilder builderOf(Class valueClass) { -// return builder().asValue(valueClass); -// } -// -// @SuppressWarnings("unchecked") -// public static ConfiguredValue of(@NotNull V defaultValue) { -// return of((Class) defaultValue.getClass(), defaultValue); -// } -// -// public static ConfiguredValue of(Class valueClass) { -// return of(valueClass, null); -// } -// -// public static ConfiguredValue of(Class valueClass, @Nullable V defaultValue) { -// return builderOf(valueClass).fromObject().defaults(defaultValue).build(); -// } + public static ConfigValueBuilder builderOf(@NotNull Class type) { + return new ConfigValueBuilder<>(ValueType.of(type)); + } - protected final @NotNull Class valueClass; + public static ConfigValueBuilder builderOf(@NotNull ValueType type) { + return new ConfigValueBuilder<>(type); + } - protected final @NotNull ConfigValueParser parser; - protected final @NotNull ConfigDataFunction serializer; + public static ConfiguredValue of(@NotNull V defaults) { + return of(ValueType.of(defaults), () -> defaults); + } - public ConfiguredValue(@NotNull ValueManifest manifest, @NotNull Class valueClass, - @NotNull ConfigValueParser parser, - @NotNull ConfigDataFunction serializer) { + public static ConfiguredValue of(@NotNull Class type) { + return of(ValueType.of(type), () -> null); + } + + public static ConfiguredValue of(@NotNull Class type, @NotNull Supplier<@Nullable V> defaultSupplier) { + return of(ValueType.of(type), defaultSupplier); + } + + public static ConfiguredValue of(@NotNull ValueType type) { + return of(type, () -> null); + } + + public static ConfiguredValue of(@NotNull ValueType type, @NotNull Supplier<@Nullable V> defaultSupplier) { + return of( + new ValueManifest<>(type, defaultSupplier), + (provider, t, data) -> provider.deserialize(type, data), + (provider, t, value) -> provider.serialize(value) + ); + } + + public static ConfiguredValue of(@NotNull ValueManifest manifest, + @Nullable ValueParser parser, + @Nullable ValueSerializer serializer) { + return new ConfiguredValue<>(manifest, parser, serializer); + } + + protected final @Nullable ValueParser parser; + protected final @Nullable ValueSerializer serializer; + + public ConfiguredValue(@NotNull ValueManifest manifest, + @Nullable ValueParser parser, + @Nullable ValueSerializer serializer) { super(manifest); - this.valueClass = valueClass; this.parser = parser; this.serializer = serializer; } /** - * @return Value's type class + * @return Value's parser, parse base object to value. */ - public @NotNull Class getValueClass() { - return valueClass; - } - - /** - * @return Value's parser, cast value from base object. - */ - public @NotNull ConfigValueParser getParser() { + public @Nullable ValueParser parser() { return parser; } /** - * @return Value's serializer, serialize value to base object. + * @return Value's serializer, parse value to base object. */ - public @NotNull ConfigDataFunction getSerializer() { + public @Nullable ValueSerializer serializer() { return serializer; } @@ -65,12 +82,15 @@ public class ConfiguredValue extends CachedConfigValue { if (!isExpired()) return getCachedOrDefault(); // Data that is outdated and needs to be parsed again. - Object value = getValue(); - if (value == null) return defaults(); + Object data = getData(); + if (data == null) return defaults(); + + ValueParser parser = parser(); + if (parser == null) return defaults(); // No parser, return default value. try { // If there are no errors, update the cache and return. - return updateCache(this.parser.parse(provider(), value, defaults())); + return updateCache(parser.deserialize(provider(), type(), data)); } catch (Exception e) { // There was a parsing error, prompted and returned the default value. e.printStackTrace(); @@ -81,21 +101,27 @@ public class ConfiguredValue extends CachedConfigValue { /** * Set the value of the configuration path. - * Will use {@link #getSerializer()} to serialize the value. + * Will use {@link #serializer()} to serialize the value. * * @param value The value to be set */ @Override public void set(V value) { - updateCache(value); - if (value == null) setValue(null); - else { - try { - setValue(serializer.parse(value)); - } catch (Exception e) { - e.printStackTrace(); - } + updateCache(value); // Update cache + if (value == null) { + setData(null); + return; } + + ValueSerializer serializer = serializer(); + if (serializer == null) return; // No serializer, do nothing. + + try { + setData(serializer.serialize(provider(), type(), value)); + } catch (Exception e) { + e.printStackTrace(); + } + } } diff --git a/core/src/main/old/ValueManifestv.java b/core/src/main/old/ValueManifestv.java deleted file mode 100644 index eb282ce..0000000 --- a/core/src/main/old/ValueManifestv.java +++ /dev/null @@ -1,123 +0,0 @@ -package cc.carm.lib.configuration.value; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - -import java.util.List; -import java.util.Optional; - -/** - * ConfigValue Manifests. - * The basic information that describes a configuration value. - * - * @param Value type - * @author CarmJos - */ -public class ValueManifest { - - public static ValueManifest of(@Nullable ConfigurationProvider provider, @Nullable String configPath, - @Nullable List headerComments, @Nullable String inlineComments) { - return new ValueManifest<>(provider, configPath, headerComments, inlineComments, null); - } - - public static ValueManifest of(@Nullable ConfigurationProvider provider, @Nullable String configPath, - @Nullable List headerComments, @Nullable String inlineComments, - @Nullable V defaultValue) { - return new ValueManifest<>(provider, configPath, headerComments, inlineComments, defaultValue); - } - - protected @Nullable ConfigurationProvider provider; - protected @Nullable String configPath; - - protected @Nullable List headerComments; - protected @Nullable String inlineComment; - - protected @Nullable T defaultValue; - - /** - * @param provider Provider of config files {@link ConfigurationProvider} - * @param configPath Config path of this value - * @param headerComments Header comment contents - * @param inlineComment Inline comment content - * @param defaultValue The default value - */ - public ValueManifest(@Nullable ConfigurationProvider provider, @Nullable String configPath, - @Nullable List headerComments, @Nullable String inlineComment, - @Nullable T defaultValue) { - this.provider = provider; - this.configPath = configPath; - this.headerComments = headerComments; - this.inlineComment = inlineComment; - this.defaultValue = defaultValue; - } - - /** - * The initialize method for {@link ConfigInitializer}, which is used to initialize the value. - * - * @param provider Provider of config files {@link ConfigurationProvider} - * @param configPath Config path of this value - * @param headerComments Header comment contents - * @param inlineComment Inline comment content - */ - protected void initialize(@NotNull ConfigurationProvider provider, @NotNull String configPath, - @Nullable List headerComments, @Nullable String inlineComment) { - if (this.provider == null) this.provider = provider; - if (this.configPath == null) this.configPath = configPath; - if (this.headerComments == null) this.headerComments = headerComments; - if (this.inlineComment == null) this.inlineComment = inlineComment; - - if (getHeaderComments() != null) { - this.provider.setHeaderComment(getConfigPath(), getHeaderComments()); - } - if (getInlineComment() != null) { - this.provider.setInlineComment(getConfigPath(), getInlineComment()); - } - } - - public @Nullable T getDefaultValue() { - return this.defaultValue; - } - - public void setDefaultValue(@Nullable T defaultValue) { - this.defaultValue = defaultValue; - } - - public @NotNull ConfigurationProvider getProvider() { - return Optional.ofNullable(this.provider) - .orElseThrow(() -> new IllegalStateException("Value(" + configPath + ") does not have a provider.")); - } - - public final @NotNull ConfigurationWrapper getConfiguration() { - try { - return getProvider().getConfiguration(); - } catch (Exception ex) { - throw new IllegalStateException("Value(" + configPath + ") has not been initialized", ex); - } - } - - public @NotNull String getConfigPath() { - return Optional.ofNullable(this.configPath) - .orElseThrow(() -> new IllegalStateException("No section path provided.")); - } - - protected Object getValue() { - String path = getConfigPath(); // 当未指定路径时,优先抛出异常 - return getConfiguration().get(path); - } - - protected void setValue(@Nullable Object value) { - getConfiguration().set(getConfigPath(), value); - } - - public @Nullable String getInlineComment() { - return inlineComment; - } - - @Unmodifiable - public @Nullable List getHeaderComments() { - return headerComments; - } - - -} diff --git a/core/src/main/old/builder/AbstractConfigBuilder.java b/core/src/main/old/builder/AbstractConfigBuilder.java index 25429ba..c8f2270 100644 --- a/core/src/main/old/builder/AbstractConfigBuilder.java +++ b/core/src/main/old/builder/AbstractConfigBuilder.java @@ -31,12 +31,12 @@ public abstract class AbstractConfigBuilder comments) { this.headerComments = comments; - return getThis(); + return self(); } public @NotNull B inlineComment(@NotNull String comment) { this.inlineComment = comment; - return getThis(); + return self(); } public @NotNull B defaults(@Nullable T defaultValue) { this.defaultValue = defaultValue; - return getThis(); + return self(); } public @NotNull B defaults(@NotNull Supplier<@Nullable T> defaultValueSupplier) { diff --git a/core/src/main/old/builder/ConfigBuilder.java b/core/src/main/old/builder/ConfigBuilder.java deleted file mode 100644 index 2dd7dc0..0000000 --- a/core/src/main/old/builder/ConfigBuilder.java +++ /dev/null @@ -1,43 +0,0 @@ -package cc.carm.lib.configuration.builder; - -import cc.carm.lib.configuration.builder.map.ConfigMapBuilder; -import cc.carm.lib.configuration.builder.map.ConfigMapCreator; -import cc.carm.lib.configuration.builder.list.ConfigListBuilder; -import cc.carm.lib.configuration.builder.value.ConfigValueBuilder; -import org.jetbrains.annotations.NotNull; - -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.TreeMap; - -public class ConfigBuilder { - - public @NotNull ConfigValueBuilder asValue(@NotNull Class valueClass) { - return new ConfigValueBuilder<>(valueClass); - } - - public @NotNull ConfigListBuilder asList(@NotNull Class valueClass) { - return new ConfigListBuilder<>(valueClass); - } - - public @NotNull ConfigMapCreator asMap(@NotNull Class keyClass, - @NotNull Class valueClass) { - return new ConfigMapCreator<>(keyClass, valueClass); - } - - public @NotNull ConfigMapBuilder, K, V> asHashMap(@NotNull Class keyClass, - @NotNull Class valueClass) { - return asMap(keyClass, valueClass).asHashMap(); - } - - public @NotNull ConfigMapBuilder, K, V> asLinkedMap(@NotNull Class keyClass, - @NotNull Class valueClass) { - return asMap(keyClass, valueClass).asLinkedMap(); - } - - public , V> @NotNull ConfigMapBuilder, K, V> asTreeMap(@NotNull Class keyClass, - @NotNull Class valueClass) { - return asMap(keyClass, valueClass).asTreeMap(); - } - -} diff --git a/core/src/main/old/builder/value/SectionValueBuilder.java b/core/src/main/old/builder/value/SectionValueBuilder.java index dbdf6de..4670fc8 100644 --- a/core/src/main/old/builder/value/SectionValueBuilder.java +++ b/core/src/main/old/builder/value/SectionValueBuilder.java @@ -3,7 +3,6 @@ package cc.carm.lib.configuration.builder.value; import cc.carm.lib.configuration.builder.CommonConfigBuilder; import cc.carm.lib.configuration.function.ConfigDataFunction; import cc.carm.lib.configuration.function.ConfigValueParser; -import cc.carm.lib.configuration.value.standard.ConfiguredSection; import org.jetbrains.annotations.NotNull; import java.util.Map; diff --git a/core/src/test/java/AdaptTest.java b/core/src/test/java/AdaptTest.java index e4cc97c..e1ede3a 100644 --- a/core/src/test/java/AdaptTest.java +++ b/core/src/test/java/AdaptTest.java @@ -1,14 +1,18 @@ import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; -import cc.carm.lib.configuration.adapter.strandard.EnumAdapter; +import cc.carm.lib.configuration.adapter.ValueType; import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapters; import cc.carm.lib.configuration.source.ConfigurationProvider; -import cc.carm.lib.configuration.loader.ConfigurationLoader; -import cc.carm.lib.easyoptions.OptionHolder; +import cc.carm.lib.configuration.source.loader.ConfigurationLoader; +import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder; +import cc.carm.lib.configuration.value.standard.ConfiguredValue; import cc.carm.test.config.TestSource; import org.junit.Test; import java.time.Duration; +import java.time.LocalDate; import java.time.LocalTime; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class AdaptTest { @@ -16,42 +20,29 @@ public class AdaptTest { public void test() throws Exception { ValueAdapterRegistry registry = new ValueAdapterRegistry(); - registry.register(Long.class, PrimitiveAdapters.ofLong()); - registry.register(long.class, PrimitiveAdapters.ofLong()); - registry.register(Integer.class, PrimitiveAdapters.ofInteger()); - registry.register(int.class, PrimitiveAdapters.ofInteger()); - registry.register(Double.class, PrimitiveAdapters.ofDouble()); - registry.register(double.class, PrimitiveAdapters.ofDouble()); - registry.register(Float.class, PrimitiveAdapters.ofFloat()); - registry.register(float.class, PrimitiveAdapters.ofFloat()); - registry.register(Short.class, PrimitiveAdapters.ofShort()); - registry.register(short.class, PrimitiveAdapters.ofShort()); - registry.register(Byte.class, PrimitiveAdapters.ofByte()); - registry.register(byte.class, PrimitiveAdapters.ofByte()); - registry.register(Character.class, PrimitiveAdapters.ofCharacter()); - registry.register(char.class, PrimitiveAdapters.ofCharacter()); - registry.register(Boolean.class, PrimitiveAdapters.ofBoolean()); - registry.register(boolean.class, PrimitiveAdapters.ofBoolean()); - registry.register(String.class, PrimitiveAdapters.ofString()); - registry.register(new EnumAdapter()); + registry.register(PrimitiveAdapters.ADAPTERS); + registry.register(PrimitiveAdapters.ofEnum()); - registry.register(Long.class, Duration.class, Duration::ofSeconds, Duration::getSeconds); + + registry.register(ValueType.of(Long.class), ValueType.of(Duration.class), Duration::ofMillis, Duration::toMillis); registry.register( - Duration.class, LocalTime.class, + ValueType.of(Duration.class), ValueType.of(LocalTime.class), duration -> LocalTime.now().plus(duration), data -> Duration.between(LocalTime.now(), data) ); - ConfigurationProvider provider = new ConfigurationProvider<>(new TestSource(), new ConfigurationLoader(), registry, new OptionHolder()); + ConfigurationProvider provider = new ConfigurationProvider<>( + new TestSource(), new ConfigurationLoader(), + registry, new ConfigurationOptionHolder(), new ConcurrentHashMap<>() + ); - LocalTime v = registry.deserialize(provider, LocalTime.class, "600"); + LocalTime v = registry.deserialize(provider, LocalTime.class, 600000L); Object d = registry.serialize(provider, v); System.out.println(v); System.out.println(d); - System.out.println(registry.deserialize(provider, TestEnum.class, "b")); + System.out.println(registry.deserialize(provider, TestEnum.class, "C")); System.out.println(registry.serialize(provider, TestEnum.C).getClass()); - } enum TestEnum { diff --git a/core/src/test/java/NameTest.java b/core/src/test/java/NameTest.java index d1d09a9..604057c 100644 --- a/core/src/test/java/NameTest.java +++ b/core/src/test/java/NameTest.java @@ -1,4 +1,4 @@ -import cc.carm.lib.configuration.loader.PathGenerator; +import cc.carm.lib.configuration.source.loader.PathGenerator; import org.junit.Test; public class NameTest { diff --git a/core/src/test/java/cc/carm/test/config/LoaderTest.java b/core/src/test/java/cc/carm/test/config/LoaderTest.java index aa3de0a..7210546 100644 --- a/core/src/test/java/cc/carm/test/config/LoaderTest.java +++ b/core/src/test/java/cc/carm/test/config/LoaderTest.java @@ -4,15 +4,17 @@ import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; import cc.carm.lib.configuration.annotation.ConfigPath; import cc.carm.lib.configuration.Configuration; import cc.carm.lib.configuration.source.ConfigurationProvider; -import cc.carm.lib.configuration.loader.ConfigurationLoader; -import cc.carm.lib.easyoptions.OptionHolder; +import cc.carm.lib.configuration.source.loader.ConfigurationLoader; +import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder; import org.junit.Test; +import java.util.concurrent.ConcurrentHashMap; + public class LoaderTest { @Test public void test() throws Exception { - ConfigurationProvider provider = new ConfigurationProvider<>(new TestSource(), new ConfigurationLoader(), new ValueAdapterRegistry(), new OptionHolder()); + ConfigurationProvider provider = new ConfigurationProvider<>(new TestSource(), new ConfigurationLoader(), new ValueAdapterRegistry(), new ConfigurationOptionHolder(), new ConcurrentHashMap<>()); ConfigurationLoader loader = new ConfigurationLoader(); loader.load(provider, ROOT.class); diff --git a/core/src/test/java/cc/carm/test/config/TestSource.java b/core/src/test/java/cc/carm/test/config/TestSource.java index 30247a3..c836e4c 100644 --- a/core/src/test/java/cc/carm/test/config/TestSource.java +++ b/core/src/test/java/cc/carm/test/config/TestSource.java @@ -1,7 +1,7 @@ package cc.carm.test.config; -import cc.carm.lib.configuration.source.ConfigurationSection; -import cc.carm.lib.configuration.source.ConfigurationSource; +import cc.carm.lib.configuration.source.section.ConfigurationSection; +import cc.carm.lib.configuration.source.section.ConfigurationSource; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,7 +16,7 @@ public class TestSource extends ConfigurationSource> HEADER_COMMENTS = ValueMetaType.of(Collections.emptyList()); + PathMetadata> HEADER_COMMENTS = PathMetadata.of(Collections.emptyList()); /** * Configuration's {@link InlineComment} */ - ValueMetaType INLINE_COMMENT_VALUE = ValueMetaType.of(); + PathMetadata INLINE_COMMENT_VALUE = PathMetadata.of(); } diff --git a/features/commentable/src/main/java/cc/carm/lib/configuration/option/CommentableOptions.java b/features/commentable/src/main/java/cc/carm/lib/configuration/option/CommentableOptions.java index 3bc585b..1c8a413 100644 --- a/features/commentable/src/main/java/cc/carm/lib/configuration/option/CommentableOptions.java +++ b/features/commentable/src/main/java/cc/carm/lib/configuration/option/CommentableOptions.java @@ -1,6 +1,6 @@ package cc.carm.lib.configuration.option; -import cc.carm.lib.easyoptions.OptionType; +import cc.carm.lib.configuration.source.option.ConfigurationOption; public interface CommentableOptions { @@ -8,7 +8,7 @@ public interface CommentableOptions { * Whether to keep modified comments in configuration, * that means we only set comments for values that are not exists in configuration. */ - OptionType KEEP_COMMENTS = OptionType.of(true); + ConfigurationOption KEEP_COMMENTS = ConfigurationOption.of(true); /** * Whether to comment values name that are not exists in configuration and no default value offered. @@ -19,6 +19,6 @@ public interface CommentableOptions { * # foo: * */ - OptionType COMMENT_NO_DEFAULT = OptionType.of(true); + ConfigurationOption COMMENT_NO_DEFAULT = ConfigurationOption.of(true); } diff --git a/features/file/src/main/java/cc/carm/lib/configuration/option/FileConfigOptions.java b/features/file/src/main/java/cc/carm/lib/configuration/option/FileConfigOptions.java index 4868651..30741e7 100644 --- a/features/file/src/main/java/cc/carm/lib/configuration/option/FileConfigOptions.java +++ b/features/file/src/main/java/cc/carm/lib/configuration/option/FileConfigOptions.java @@ -1,15 +1,12 @@ package cc.carm.lib.configuration.option; -import cc.carm.lib.easyoptions.OptionType; - -import static cc.carm.lib.easyoptions.OptionType.of; +import cc.carm.lib.configuration.source.option.ConfigurationOption; public class FileConfigOptions { /** * Whether to copy files from resource if exists. */ - OptionType COPY_DEFAULTS = of(true); - + ConfigurationOption COPY_DEFAULTS = ConfigurationOption.of(true); } diff --git a/features/file/src/main/java/cc/carm/lib/configuration/source/FileProvider.java b/features/file/src/main/java/cc/carm/lib/configuration/source/FileProvider.java new file mode 100644 index 0000000..f10b3da --- /dev/null +++ b/features/file/src/main/java/cc/carm/lib/configuration/source/FileProvider.java @@ -0,0 +1,21 @@ +package cc.carm.lib.configuration.source; + +import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; +import cc.carm.lib.configuration.meta.PathMetadata; +import cc.carm.lib.configuration.source.loader.ConfigurationLoader; +import cc.carm.lib.configuration.source.option.ConfigurationOptionHolder; +import cc.carm.lib.configuration.source.section.ConfigurationSource; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; + +public abstract class FileProvider> extends ConfigurationProvider { + + public FileProvider(@NotNull S source, @NotNull ConfigurationLoader loader, + @NotNull ValueAdapterRegistry adapters, @NotNull ConfigurationOptionHolder options, + @NotNull Map, Object>> pathMetadata) { + super(source, loader, adapters, options, pathMetadata); + } + + +} diff --git a/pom.xml b/pom.xml index f2d2d0f..29de05d 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ - + providers/gson diff --git a/providers/gson/pom.xml b/providers/gson/pom.xml index df5abd9..9668214 100644 --- a/providers/gson/pom.xml +++ b/providers/gson/pom.xml @@ -27,6 +27,13 @@ compile + + ${project.parent.groupId} + easyconfiguration-feature-file + ${project.parent.version} + compile + + ${project.parent.groupId} easyconfiguration-demo diff --git a/providers/yaml/src/main/java/cc/carm/lib/configuration/yaml/YAMLConfigSource.java b/providers/yaml/src/main/java/cc/carm/lib/configuration/yaml/YAMLConfigSource.java new file mode 100644 index 0000000..d8e7d8e --- /dev/null +++ b/providers/yaml/src/main/java/cc/carm/lib/configuration/yaml/YAMLConfigSource.java @@ -0,0 +1,4 @@ +package cc.carm.lib.configuration.yaml; + +public class YAMLConfigSource { +}