From 2df33e34589ca3e756aba3d6ad95aa550e1a934a Mon Sep 17 00:00:00 2001 From: carm Date: Tue, 16 Jan 2024 03:50:08 +0800 Subject: [PATCH] feat(adapter): Finished adapters registry --- .../configuration/adapter/ValueAdapter.java | 31 +++++--- .../adapter/ValueAdapterRegistry.java | 28 +++++--- .../adapter/primitive/PrimitiveAdapter.java | 30 -------- .../adapter/strandard/EnumAdapter.java | 24 +++++++ .../adapter/strandard/PrimitiveAdapters.java | 70 +++++++++++++++++++ core/src/test/java/AdaptTest.java | 31 ++++++-- 6 files changed, 163 insertions(+), 51 deletions(-) delete mode 100644 core/src/main/java/cc/carm/lib/configuration/adapter/primitive/PrimitiveAdapter.java create mode 100644 core/src/main/java/cc/carm/lib/configuration/adapter/strandard/EnumAdapter.java create mode 100644 core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java 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 738dc27..c0782fa 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 @@ -3,27 +3,34 @@ package cc.carm.lib.configuration.adapter; import cc.carm.lib.configuration.source.ConfigurationProvider; import org.jetbrains.annotations.NotNull; +/** + * Value adapter, used to convert the value of the configuration file into the objects. + * + * @param

The type of the configuration provider. + * @param The type of the base data + * @param The type of the target value + */ public abstract class ValueAdapter

{ - protected final Class baseType; - protected final Class valueType; + protected final Class baseType; + protected final Class valueType; - protected ValueAdapter(Class baseType, Class valueType) { + protected ValueAdapter(Class baseType, Class valueType) { this.baseType = baseType; this.valueType = valueType; } - public Class getBaseType() { + public Class getBaseClass() { return baseType; } - public Class getValueType() { + public Class getValueClass() { return valueType; } public abstract B serialize(@NotNull P provider, @NotNull V value) throws Exception; - public abstract V deserialize(@NotNull P provider, @NotNull B data) throws Exception; + public abstract V deserialize(@NotNull P provider, @NotNull Class clazz, @NotNull B data) throws Exception; public boolean isAdaptedFrom(Class clazz) { return clazz.isAssignableFrom(valueType); @@ -33,12 +40,18 @@ public abstract class ValueAdapter

{ return isAdaptedFrom(object.getClass()); } - protected final V deserializeObject(P provider, Object data) throws Exception { - return deserialize(provider, this.baseType.cast(data)); + public boolean isAdapterOf(Class clazz) { + return valueType.isAssignableFrom(clazz); } + @SuppressWarnings("unchecked") + protected final V deserializeObject(P provider, Class valueClass, Object data) throws Exception { + return deserialize(provider, (Class) valueClass, (B) data); + } + + @SuppressWarnings("unchecked") protected final B serializeObject(P provider, Object value) throws Exception { - return serialize(provider, this.valueType.cast(value)); + return serialize(provider, (V) 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 5540d19..607aa0b 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,6 +1,6 @@ package cc.carm.lib.configuration.adapter; -import cc.carm.lib.configuration.adapter.primitive.PrimitiveAdapter; +import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapters; import cc.carm.lib.configuration.core.function.ConfigDataFunction; import cc.carm.lib.configuration.source.ConfigurationProvider; import org.jetbrains.annotations.NotNull; @@ -18,7 +18,11 @@ public class ValueAdapterRegistry

{ } public void register(@NotNull ValueAdapter adapter) { - adapters.put(adapter.valueType, adapter); + adapters.put(adapter.getValueClass(), adapter); + } + + public void register(Class clazz, @NotNull ValueAdapter adapter) { + adapters.put(clazz, adapter); } public void register(Class baseClass, Class valueClass, @@ -31,7 +35,7 @@ public class ValueAdapterRegistry

{ } @Override - public V deserialize(@NotNull P provider, @NotNull B data) throws Exception { + public V deserialize(@NotNull P provider, @NotNull Class clazz, @NotNull B data) throws Exception { return parser.parse(data); } }); @@ -46,17 +50,19 @@ public class ValueAdapterRegistry

{ if (value == null) return null; if (type == Object.class) return type.cast(value); - ValueAdapter adapter = adapters.get(type); + 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(value)) return (T) adapter.deserializeObject(provider, value); + if (adapter.isAdaptedFrom(value)) { + return (T) adapter.deserializeObject(provider, type, value); + } // OTHERWISE, WE NEED TO DESERIALIZE ONE BY ONE - Object baseValue = deserialize(adapter.getBaseType(), value); + Object baseValue = deserialize(adapter.getBaseClass(), value); if (baseValue == null) return null; // Null check - return (T) adapter.deserializeObject(provider, baseValue); + return (T) adapter.deserializeObject(provider, type, baseValue); } public Object serialize(T value) throws Exception { @@ -66,7 +72,7 @@ public class ValueAdapterRegistry

{ ValueAdapter adapter = adapters.get(valueClass); if (adapter == null) return value; // No adapters, try to return the original value - if (adapter instanceof PrimitiveAdapter) { + 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); @@ -76,5 +82,11 @@ public class ValueAdapterRegistry

{ return serialize(adapter.serializeObject(provider, value)); } + public ValueAdapter getAdapter(Class clazz) { + ValueAdapter byClass = adapters.get(clazz); + if (byClass != null) return byClass; + return adapters.values().stream().filter(adapter -> adapter.isAdapterOf(clazz)).findFirst().orElse(null); + } + } diff --git a/core/src/main/java/cc/carm/lib/configuration/adapter/primitive/PrimitiveAdapter.java b/core/src/main/java/cc/carm/lib/configuration/adapter/primitive/PrimitiveAdapter.java deleted file mode 100644 index 4c484dd..0000000 --- a/core/src/main/java/cc/carm/lib/configuration/adapter/primitive/PrimitiveAdapter.java +++ /dev/null @@ -1,30 +0,0 @@ -package cc.carm.lib.configuration.adapter.primitive; - -import cc.carm.lib.configuration.adapter.ValueAdapter; -import cc.carm.lib.configuration.core.function.ConfigDataFunction; -import cc.carm.lib.configuration.source.ConfigurationProvider; -import org.jetbrains.annotations.NotNull; - -public abstract class PrimitiveAdapter

extends ValueAdapter { - - public static

PrimitiveAdapter of(@NotNull Class clazz, - @NotNull ConfigDataFunction function) { - return new PrimitiveAdapter(clazz) { - @Override - public T deserialize(@NotNull P provider, @NotNull Object data) throws Exception { - return function.parse(data); - } - }; - } - - - protected PrimitiveAdapter(Class valueType) { - super(Object.class, valueType); - } - - @Override - public Object serialize(@NotNull P provider, @NotNull T value) throws Exception { - return value; - } - -} 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 new file mode 100644 index 0000000..40bd3c4 --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/EnumAdapter.java @@ -0,0 +1,24 @@ +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 P provider, @NotNull Enum value) throws Exception { + return value.name(); + } + + @Override + public Enum deserialize(@NotNull P provider, @NotNull Class clazz, @NotNull String data) throws Exception { + return Enum.valueOf(clazz, data); + } + +} 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 new file mode 100644 index 0000000..6062b7b --- /dev/null +++ b/core/src/main/java/cc/carm/lib/configuration/adapter/strandard/PrimitiveAdapters.java @@ -0,0 +1,70 @@ +package cc.carm.lib.configuration.adapter.strandard; + +import cc.carm.lib.configuration.adapter.ValueAdapter; +import cc.carm.lib.configuration.core.function.ConfigDataFunction; +import cc.carm.lib.configuration.source.ConfigurationProvider; +import org.jetbrains.annotations.NotNull; + +public abstract class PrimitiveAdapters

extends ValueAdapter { + + public static

PrimitiveAdapters ofString() { + return of(String.class, o -> o instanceof String ? (String) o : o.toString()); + } + + public static

PrimitiveAdapters ofBoolean() { + 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 ofInteger() { + return ofNumber(Integer.class, Number::intValue, Integer::parseInt); + } + + public static

PrimitiveAdapters ofLong() { + return ofNumber(Long.class, Number::longValue, Long::parseLong); + } + + public static

PrimitiveAdapters ofDouble() { + return ofNumber(Double.class, Number::doubleValue, Double::parseDouble); + } + + public static

PrimitiveAdapters ofFloat() { + return ofNumber(Float.class, Number::floatValue, Float::parseFloat); + } + + public static

PrimitiveAdapters ofShort() { + 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 P provider, @NotNull T value) throws Exception { + return value; + } + + public static

PrimitiveAdapters of(@NotNull Class clazz, + @NotNull ConfigDataFunction function) { + return new PrimitiveAdapters(clazz) { + @Override + public T deserialize(@NotNull P provider, @NotNull Class clazz, @NotNull Object data) throws Exception { + return function.parse(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())); + } +} diff --git a/core/src/test/java/AdaptTest.java b/core/src/test/java/AdaptTest.java index 077dc9d..35be94b 100644 --- a/core/src/test/java/AdaptTest.java +++ b/core/src/test/java/AdaptTest.java @@ -1,5 +1,6 @@ import cc.carm.lib.configuration.adapter.ValueAdapterRegistry; -import cc.carm.lib.configuration.adapter.primitive.PrimitiveAdapter; +import cc.carm.lib.configuration.adapter.strandard.EnumAdapter; +import cc.carm.lib.configuration.adapter.strandard.PrimitiveAdapters; import cc.carm.lib.configuration.source.ConfigurationProvider; import org.junit.Test; @@ -12,9 +13,25 @@ public class AdaptTest { public void test() throws Exception { ValueAdapterRegistry registry = new ValueAdapterRegistry<>(new ConfigurationProvider()); - registry.register(PrimitiveAdapter.of(Long.class, data -> Long.parseLong(data.toString()))); - registry.register(PrimitiveAdapter.of(Integer.class, data -> Integer.parseInt(data.toString()))); - registry.register(PrimitiveAdapter.of(long.class, data -> Long.parseLong(data.toString()))); + 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(Long.class, Duration.class, Duration::ofSeconds, Duration::getSeconds); registry.register( Duration.class, LocalTime.class, @@ -25,8 +42,14 @@ public class AdaptTest { LocalTime v = registry.deserialize(LocalTime.class, "600"); Object d = registry.serialize(v); + System.out.println(v); System.out.println(d); + System.out.println(registry.deserialize(TestEnum.class, "b")); + } + + enum TestEnum { + A, b, C } }