diff --git a/core/pom.xml b/core/pom.xml
index 7f1d213..d2d697c 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -5,7 +5,7 @@
configured-parent
cc.carm.lib
- 4.1.0
+ 4.1.1
4.0.0
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 9df8f70..d71d668 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
@@ -15,6 +15,7 @@ public class ValueAdapter
implements ValueSerializer, ValueParser {
protected final @NotNull ValueType type;
+
protected @Nullable ValueSerializer serializer;
protected @Nullable ValueParser deserializer;
@@ -53,13 +54,17 @@ public class ValueAdapter
}
@Override
- public Object serialize(@NotNull ConfigurationHolder> holder, @NotNull ValueType super TYPE> type, @NotNull TYPE value) throws Exception {
+ public @Nullable Object serialize(
+ @NotNull ConfigurationHolder> holder, @NotNull ValueType super TYPE> type,
+ @NotNull TYPE value) throws Exception {
if (serializer == null) throw new UnsupportedOperationException("Serializer is not supported");
return serializer.serialize(holder, type, value);
}
@Override
- public TYPE parse(@NotNull ConfigurationHolder> holder, @NotNull ValueType super TYPE> type, @NotNull Object value) throws Exception {
+ public @Nullable TYPE parse(
+ @NotNull ConfigurationHolder> holder, @NotNull ValueType super TYPE> type,
+ @NotNull Object value) throws Exception {
if (deserializer == null) throw new UnsupportedOperationException("Deserializer is not supported");
return deserializer.parse(holder, type, value);
}
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 f15d6f2..f4823ab 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
@@ -61,7 +61,9 @@ public class ValueAdapterRegistry {
}
}
- public void register(@NotNull ValueType type, @Nullable ValueSerializer serializer, @Nullable ValueParser 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) {
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
index e5162b4..271c00c 100644
--- a/core/src/main/java/cc/carm/lib/configuration/adapter/ValueParser.java
+++ b/core/src/main/java/cc/carm/lib/configuration/adapter/ValueParser.java
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Value deserializer, convert base data to target value.
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface ValueParser {
- TYPE parse(
+ @Nullable TYPE parse(
@NotNull ConfigurationHolder> holder,
@NotNull ValueType super TYPE> 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 37e74e0..5243e7f 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
@@ -2,6 +2,7 @@ package cc.carm.lib.configuration.adapter;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* Value serializer, convert target value to base data.
@@ -11,7 +12,7 @@ import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface ValueSerializer {
- Object serialize(
+ @Nullable Object serialize(
@NotNull ConfigurationHolder> holder,
@NotNull ValueType super TYPE> type, @NotNull TYPE value
) throws Exception;
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
index a0d3435..473e444 100644
--- 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
@@ -5,6 +5,8 @@ import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import org.jetbrains.annotations.NotNull;
+import java.util.UUID;
+
import static cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapter.*;
public interface StandardAdapters {
@@ -17,6 +19,12 @@ public interface StandardAdapters {
@NotNull ValueAdapter> ENUMS = PrimitiveAdapter.ofEnum();
+ @NotNull ValueAdapter UUID = new ValueAdapter<>(
+ ValueType.of(UUID.class),
+ (provider, type, value) -> value.toString(),
+ (provider, type, value) -> java.util.UUID.fromString(value.toString())
+ );
+
@NotNull ValueAdapter SECTIONS = new ValueAdapter<>(
ValueType.of(ConfigureSection.class),
(provider, type, value) -> value,
diff --git a/core/src/main/java/cc/carm/lib/configuration/annotation/Ex.java b/core/src/main/java/cc/carm/lib/configuration/annotation/Ex.java
new file mode 100644
index 0000000..c21ad53
--- /dev/null
+++ b/core/src/main/java/cc/carm/lib/configuration/annotation/Ex.java
@@ -0,0 +1,21 @@
+package cc.carm.lib.configuration.annotation;
+
+import cc.carm.lib.configuration.source.loader.ConfigurationInitializer;
+
+public class Ex {
+
+ static void init(ConfigurationInitializer initializer) {
+ initializer.appendFieldInitializer((holder, path, field, value) -> {
+ ValueRange range = field.getAnnotation(ValueRange.class);
+ if (range == null) return;
+ value.validate((h, v) -> {
+ if (!(v instanceof Number)) return;
+ Number number = (Number) v;
+ if (number.doubleValue() >= range.min() && number.doubleValue() <= range.max()) {
+ throw new IllegalArgumentException(range.message());
+ }
+ });
+ });
+ }
+
+}
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
index 4f87719..e617190 100644
--- a/core/src/main/java/cc/carm/lib/configuration/builder/AbstractConfigBuilder.java
+++ b/core/src/main/java/cc/carm/lib/configuration/builder/AbstractConfigBuilder.java
@@ -1,21 +1,26 @@
package cc.carm.lib.configuration.builder;
import cc.carm.lib.configuration.adapter.ValueType;
+import cc.carm.lib.configuration.function.DataValidator;
+import cc.carm.lib.configuration.function.ValueValidator;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetaHolder;
import cc.carm.lib.configuration.source.meta.ConfigurationMetadata;
import cc.carm.lib.configuration.value.ConfigValue;
import cc.carm.lib.configuration.value.ValueManifest;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.NotNullByDefault;
import org.jetbrains.annotations.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
+import java.util.function.Predicate;
import java.util.function.Supplier;
+@NotNullByDefault
public abstract class AbstractConfigBuilder<
- TYPE, RESULT extends ConfigValue, HOLDER extends ConfigurationHolder>,
- SELF extends AbstractConfigBuilder
+ TYPE, UNIT, RESULT extends ConfigValue, HOLDER extends ConfigurationHolder>,
+ SELF extends AbstractConfigBuilder
> {
protected final Class super HOLDER> providerClass;
@@ -24,6 +29,7 @@ public abstract class AbstractConfigBuilder<
protected @Nullable HOLDER holder;
protected @Nullable String path;
+ protected @NotNull ValueValidator super UNIT> valueValidator = ValueValidator.none();
protected @NotNull Supplier<@Nullable TYPE> defaultValueSupplier = () -> null;
protected @NotNull BiConsumer, String> initializer = (h, p) -> {
};
@@ -37,54 +43,124 @@ public abstract class AbstractConfigBuilder<
return type;
}
- protected abstract @NotNull SELF self();
+ protected abstract SELF self();
public abstract @NotNull RESULT build();
- public @NotNull SELF holder(@Nullable HOLDER holder) {
+ public SELF holder(@Nullable HOLDER holder) {
this.holder = holder;
return self();
}
- public @NotNull SELF path(@Nullable String path) {
+ public SELF path(@Nullable String path) {
this.path = path;
return self();
}
- public @NotNull SELF initializer(@NotNull BiConsumer, String> initializer) {
+ /**
+ * Set the {@link ValueValidator} for the value.
+ *
+ * @param validator The validator to set.
+ * @return this builder
+ */
+ public SELF validator(@NotNull ValueValidator super UNIT> validator) {
+ this.valueValidator = validator;
+ return self();
+ }
+
+ /**
+ * Set the {@link DataValidator} for the value.
+ *
+ * @param validator The validator to set.
+ * @return this builder
+ */
+ public SELF validator(@NotNull DataValidator super UNIT> validator) {
+ return validator((h, value) -> validator.validate(value));
+ }
+
+ /**
+ * Validate the value with the specified condition.
+ *
+ * @param validator The validator to set.
+ * @return this builder
+ */
+ public SELF validate(@NotNull ValueValidator super UNIT> validator) {
+ return validator((h, v) -> {
+ this.valueValidator.validate(h, v);
+ validator.validate(h, v);
+ });
+ }
+
+ /**
+ * Validate the value with the specified condition.
+ *
+ * @param validator The validator to set.
+ * @return this builder
+ */
+ public SELF validate(@NotNull DataValidator super UNIT> validator) {
+ return validate((h, value) -> validator.validate(value));
+ }
+
+ /**
+ * Validate the value with the specified condition.
+ *
+ * @param condition The condition to check, if the condition is false, an exception will be thrown.
+ * @param exception The exception to throw if the condition is false.
+ * @return this builder
+ */
+ public SELF validate(@NotNull Predicate super UNIT> condition, @NotNull Exception exception) {
+ return validate((h, value) -> {
+ if (!condition.test(value)) throw exception;
+ });
+ }
+
+ /**
+ * Validate the value with the specified condition.
+ *
+ * @param condition The condition to check, if the condition is false, an exception will be thrown.
+ * @param msg The message to throw if the condition is false.
+ * @return this builder
+ */
+ public SELF validate(@NotNull Predicate super UNIT> condition, @NotNull String msg) {
+ return validate((h, value) -> {
+ if (!condition.test(value)) throw new IllegalArgumentException(msg);
+ });
+ }
+
+ public SELF initializer(@NotNull BiConsumer, String> initializer) {
this.initializer = initializer;
return self();
}
- public @NotNull SELF append(@NotNull BiConsumer, String> initializer) {
+ public SELF append(@NotNull BiConsumer, String> initializer) {
return initializer(initializer.andThen(initializer));
}
- public @NotNull SELF append(@NotNull Consumer> initializer) {
+ public SELF append(@NotNull Consumer> initializer) {
return append((provider, valuePath) -> initializer.accept(provider));
}
- public @NotNull SELF defaults(@Nullable TYPE defaultValue) {
+ public SELF defaults(@Nullable TYPE defaultValue) {
return defaults(() -> defaultValue);
}
- public @NotNull SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
+ public SELF defaults(@NotNull Supplier<@Nullable TYPE> supplier) {
this.defaultValueSupplier = supplier;
return self();
}
- public @NotNull SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
+ public SELF meta(@NotNull Consumer<@NotNull ConfigurationMetaHolder> metaConsumer) {
return append((h, p) -> metaConsumer.accept(h.metadata(p)));
}
- public @NotNull SELF meta(@NotNull ConfigurationMetadata type, @Nullable M value) {
+ public SELF meta(@NotNull ConfigurationMetadata type, @Nullable M value) {
return meta(h -> h.set(type, value));
}
- protected @NotNull ValueManifest buildManifest() {
+ protected @NotNull ValueManifest buildManifest() {
return new ValueManifest<>(
- type(), this.defaultValueSupplier, this.initializer,
- this.holder, this.path
+ type(), this.defaultValueSupplier, this.valueValidator,
+ this.initializer, this.holder, this.path
);
}
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
index 03dff8d..256334a 100644
--- a/core/src/main/java/cc/carm/lib/configuration/builder/CommonConfigBuilder.java
+++ b/core/src/main/java/cc/carm/lib/configuration/builder/CommonConfigBuilder.java
@@ -4,8 +4,11 @@ import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.source.ConfigurationHolder;
import cc.carm.lib.configuration.value.ConfigValue;
-public abstract class CommonConfigBuilder, SELF extends CommonConfigBuilder>
- extends AbstractConfigBuilder, SELF> {
+public abstract class CommonConfigBuilder<
+ TYPE, UNIT,
+ RESULT extends ConfigValue,
+ SELF extends CommonConfigBuilder
+ > extends AbstractConfigBuilder, SELF> {
protected CommonConfigBuilder(ValueType type) {
super(ConfigurationHolder.class, type);
diff --git a/core/src/main/java/cc/carm/lib/configuration/builder/impl/AbstractSectionBuilder.java b/core/src/main/java/cc/carm/lib/configuration/builder/impl/AbstractSectionBuilder.java
index b695990..93e6897 100644
--- a/core/src/main/java/cc/carm/lib/configuration/builder/impl/AbstractSectionBuilder.java
+++ b/core/src/main/java/cc/carm/lib/configuration/builder/impl/AbstractSectionBuilder.java
@@ -4,7 +4,7 @@ import cc.carm.lib.configuration.adapter.ValueAdapter;
import cc.carm.lib.configuration.adapter.ValueType;
import cc.carm.lib.configuration.builder.CommonConfigBuilder;
import cc.carm.lib.configuration.function.DataFunction;
-import cc.carm.lib.configuration.function.ValueConsumer;
+import cc.carm.lib.configuration.function.ValueComposer;
import cc.carm.lib.configuration.function.ValueHandler;
import cc.carm.lib.configuration.source.section.ConfigureSection;
import cc.carm.lib.configuration.value.ConfigValue;
@@ -14,45 +14,45 @@ import java.util.LinkedHashMap;
import java.util.Map;
public abstract class AbstractSectionBuilder<
- TYPE, PARAM,
- RESULT extends ConfigValue,
- SELF extends AbstractSectionBuilder
- > extends CommonConfigBuilder {
+ TYPE, UNIT,
+ RESULT extends ConfigValue,
+ SELF extends AbstractSectionBuilder
+ > extends CommonConfigBuilder {
- protected final @NotNull ValueType paramType;
+ protected final @NotNull ValueType paramType;
- protected @NotNull ValueHandler parser;
- protected @NotNull ValueHandler> serializer;
+ protected @NotNull ValueHandler parser;
+ protected @NotNull ValueHandler> serializer;
- protected AbstractSectionBuilder(@NotNull ValueType type, @NotNull ValueType paramType,
- @NotNull ValueHandler parser,
- @NotNull ValueHandler> serializer) {
+ protected AbstractSectionBuilder(@NotNull ValueType type, @NotNull ValueType paramType,
+ @NotNull ValueHandler parser,
+ @NotNull ValueHandler> serializer) {
super(type);
this.paramType = paramType;
this.parser = parser;
this.serializer = serializer;
}
- public @NotNull SELF parse(@NotNull DataFunction valueParser) {
+ public @NotNull SELF parse(@NotNull DataFunction valueParser) {
return parse((p, section) -> valueParser.handle(section));
}
- public @NotNull SELF parse(@NotNull ValueHandler valueParser) {
+ public @NotNull SELF parse(@NotNull ValueHandler valueParser) {
this.parser = valueParser;
return self();
}
- public @NotNull SELF serialize(@NotNull ValueHandler> serializer) {
+ public @NotNull SELF serialize(@NotNull ValueHandler> serializer) {
this.serializer = serializer;
return self();
}
- public @NotNull SELF serialize(@NotNull DataFunction> serializer) {
+ public @NotNull SELF serialize(@NotNull DataFunction> serializer) {
return serialize((p, value) -> serializer.handle(value));
}
- public @NotNull SELF serialize(@NotNull ValueConsumer