Skip to content

Commit ab3c51d

Browse files
committed
add support for custom types a classes
1 parent d601fdf commit ab3c51d

53 files changed

Lines changed: 1195 additions & 363 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/main/java/it/aboutbits/springboot/toolbox/autoconfiguration/web/CustomTypeScanner.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import lombok.Getter;
66
import lombok.extern.slf4j.Slf4j;
77

8+
import java.lang.reflect.Modifier;
89
import java.util.ArrayList;
910
import java.util.Arrays;
1011
import java.util.HashSet;
@@ -31,13 +32,17 @@ public void setAdditionalTypePackages(String[] additionalTypePackages) {
3132
log.info("CustomTypeConfiguration enabled. Scanning: {}", Arrays.toString(packageNamesToScan));
3233
var classScanner = ClassScannerUtil.getScannerForPackages(packageNamesToScan);
3334

34-
this.relevantTypes = findAllCustomTypeRecords(classScanner);
35+
this.relevantTypes = findAllCustomTypes(classScanner);
3536
}
3637

3738
@SuppressWarnings("rawtypes")
38-
public static Set<Class<? extends CustomType>> findAllCustomTypeRecords(ClassScannerUtil.ClassScanner classScanner) {
39+
public static Set<Class<? extends CustomType>> findAllCustomTypes(ClassScannerUtil.ClassScanner classScanner) {
3940
return classScanner.getSubTypesOf(CustomType.class).stream()
40-
.filter(Record.class::isAssignableFrom)
41+
.filter(item ->
42+
!item.isInterface()
43+
&& !item.isAnonymousClass()
44+
&& !Modifier.isAbstract(item.getModifiers())
45+
)
4146
.collect(Collectors.toSet());
4247
}
4348
}

src/main/java/it/aboutbits/springboot/toolbox/jackson/CustomTypeDeserializer.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
import java.io.IOException;
1111
import java.lang.reflect.Constructor;
1212
import java.lang.reflect.InvocationTargetException;
13+
import java.lang.reflect.ParameterizedType;
1314
import java.math.BigDecimal;
1415
import java.math.BigInteger;
16+
import java.util.Arrays;
1517
import java.util.function.Function;
1618

1719
public class CustomTypeDeserializer<T extends CustomType<?>> extends JsonDeserializer<T> {
@@ -20,10 +22,33 @@ public class CustomTypeDeserializer<T extends CustomType<?>> extends JsonDeseria
2022
private final Function<JsonParser, Object> typeConverter;
2123

2224
public CustomTypeDeserializer(Class<T> customType) {
25+
Constructor<T> c;
2326
this.customType = customType;
2427

25-
this.constructor = RecordReflectionUtil.getCanonicalConstructor(customType);
28+
if (customType.isRecord()) {
29+
c = RecordReflectionUtil.getCanonicalConstructor(customType);
30+
} else {
31+
try {
32+
var customTypeInterface = Arrays.stream(customType.getGenericInterfaces())
33+
.filter(i ->
34+
i instanceof ParameterizedType
35+
&& CustomType.class.isAssignableFrom((Class<?>) ((ParameterizedType) i).getRawType())
36+
).findFirst()
37+
.map(i -> (ParameterizedType) i)
38+
.orElseThrow();
39+
40+
var parameterType = (Class<?>) customTypeInterface.getActualTypeArguments()[0];
41+
42+
c = customType.getConstructor(parameterType);
43+
} catch (Exception e) {
44+
throw new CustomTypeDeserializerException(
45+
"Unable to find constructor for type: " + customType.getName(),
46+
e
47+
);
48+
}
49+
}
2650

51+
this.constructor = c;
2752
this.typeConverter = getTypeConverter(
2853
constructor.getParameterTypes()[0]
2954
);

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedBigDecimalJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@
1414
import java.sql.Types;
1515

1616
public abstract class WrappedBigDecimalJavaType<T extends CustomType<BigDecimal>> extends AbstractClassJavaType<T> {
17-
private final transient Constructor<T> canonicalConstructor;
17+
private final transient Constructor<T> constructor;
1818

1919
protected WrappedBigDecimalJavaType(Class<T> type) {
2020
super(type);
2121

22-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
22+
Constructor<T> c;
23+
if (type.isRecord()) {
24+
c = RecordReflectionUtil.getCanonicalConstructor(type);
25+
} else {
26+
try {
27+
c = type.getConstructor(BigDecimal.class);
28+
} catch (NoSuchMethodException e) {
29+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
30+
}
31+
}
32+
33+
this.constructor = c;
2334
}
2435

2536
@Override
@@ -60,7 +71,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
6071
return (T) value;
6172
}
6273
if (value instanceof Double doubleValue) {
63-
return canonicalConstructor.newInstance(BigDecimal.valueOf(doubleValue));
74+
return constructor.newInstance(BigDecimal.valueOf(doubleValue));
6475
}
6576

6677
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedBigIntegerJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@
1414
import java.sql.Types;
1515

1616
public abstract class WrappedBigIntegerJavaType<T extends CustomType<BigInteger>> extends AbstractClassJavaType<T> {
17-
private final transient Constructor<T> canonicalConstructor;
17+
private final transient Constructor<T> constructor;
1818

1919
protected WrappedBigIntegerJavaType(Class<T> type) {
2020
super(type);
2121

22-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
22+
Constructor<T> c;
23+
if (type.isRecord()) {
24+
c = RecordReflectionUtil.getCanonicalConstructor(type);
25+
} else {
26+
try {
27+
c = type.getConstructor(BigInteger.class);
28+
} catch (NoSuchMethodException e) {
29+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
30+
}
31+
}
32+
33+
this.constructor = c;
2334
}
2435

2536
@Override
@@ -60,7 +71,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
6071
return (T) value;
6172
}
6273
if (value instanceof Long longValue) {
63-
return canonicalConstructor.newInstance(BigInteger.valueOf(longValue));
74+
return constructor.newInstance(BigInteger.valueOf(longValue));
6475
}
6576

6677
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedDoubleJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
import java.sql.Types;
1414

1515
public abstract class WrappedDoubleJavaType<T extends CustomType<Double>> extends AbstractClassJavaType<T> {
16-
private final transient Constructor<T> canonicalConstructor;
16+
private final transient Constructor<T> constructor;
1717

1818
protected WrappedDoubleJavaType(Class<T> type) {
1919
super(type);
2020

21-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
21+
Constructor<T> c;
22+
if (type.isRecord()) {
23+
c = RecordReflectionUtil.getCanonicalConstructor(type);
24+
} else {
25+
try {
26+
c = type.getConstructor(Double.class);
27+
} catch (NoSuchMethodException e) {
28+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
29+
}
30+
}
31+
32+
this.constructor = c;
2233
}
2334

2435
@Override
@@ -59,7 +70,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
5970
return (T) value;
6071
}
6172
if (value instanceof Double doubleValue) {
62-
return canonicalConstructor.newInstance(doubleValue);
73+
return constructor.newInstance(doubleValue);
6374
}
6475

6576
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedFloatJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
import java.sql.Types;
1414

1515
public abstract class WrappedFloatJavaType<T extends CustomType<Float>> extends AbstractClassJavaType<T> {
16-
private final transient Constructor<T> canonicalConstructor;
16+
private final transient Constructor<T> constructor;
1717

1818
protected WrappedFloatJavaType(Class<T> type) {
1919
super(type);
2020

21-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
21+
Constructor<T> c;
22+
if (type.isRecord()) {
23+
c = RecordReflectionUtil.getCanonicalConstructor(type);
24+
} else {
25+
try {
26+
c = type.getConstructor(Float.class);
27+
} catch (NoSuchMethodException e) {
28+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
29+
}
30+
}
31+
32+
this.constructor = c;
2233
}
2334

2435
@Override
@@ -59,7 +70,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
5970
return (T) value;
6071
}
6172
if (value instanceof Float floatValue) {
62-
return canonicalConstructor.newInstance(floatValue);
73+
return constructor.newInstance(floatValue);
6374
}
6475

6576
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedIntegerJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
import java.sql.Types;
1414

1515
public abstract class WrappedIntegerJavaType<T extends CustomType<Integer>> extends AbstractClassJavaType<T> {
16-
private final transient Constructor<T> canonicalConstructor;
16+
private final transient Constructor<T> constructor;
1717

1818
protected WrappedIntegerJavaType(Class<T> type) {
1919
super(type);
2020

21-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
21+
Constructor<T> c;
22+
if (type.isRecord()) {
23+
c = RecordReflectionUtil.getCanonicalConstructor(type);
24+
} else {
25+
try {
26+
c = type.getConstructor(Integer.class);
27+
} catch (NoSuchMethodException e) {
28+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
29+
}
30+
}
31+
32+
this.constructor = c;
2233
}
2334

2435
@Override
@@ -59,7 +70,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
5970
return (T) value;
6071
}
6172
if (value instanceof Integer integerValue) {
62-
return canonicalConstructor.newInstance(integerValue);
73+
return constructor.newInstance(integerValue);
6374
}
6475

6576
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedLongJavaType.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,24 @@
1313
import java.sql.Types;
1414

1515
public abstract class WrappedLongJavaType<T extends CustomType<Long>> extends AbstractClassJavaType<T> {
16-
private final transient Constructor<T> canonicalConstructor;
16+
private final transient Constructor<T> constructor;
1717

18+
@SneakyThrows
1819
protected WrappedLongJavaType(Class<T> type) {
1920
super(type);
2021

21-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
22+
Constructor<T> c;
23+
if (type.isRecord()) {
24+
c = RecordReflectionUtil.getCanonicalConstructor(type);
25+
} else {
26+
try {
27+
c = type.getConstructor(Long.class);
28+
} catch (NoSuchMethodException e) {
29+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
30+
}
31+
}
32+
33+
this.constructor = c;
2234
}
2335

2436
@Override
@@ -59,7 +71,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
5971
return (T) value;
6072
}
6173
if (value instanceof Long longValue) {
62-
return canonicalConstructor.newInstance(longValue);
74+
return constructor.newInstance(longValue);
6375
}
6476

6577
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedScaledBigDecimalJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,23 @@
1414
import java.sql.Types;
1515

1616
public abstract class WrappedScaledBigDecimalJavaType<T extends CustomType<ScaledBigDecimal>> extends AbstractClassJavaType<T> {
17-
private final transient Constructor<T> canonicalConstructor;
17+
private final transient Constructor<T> constructor;
1818

1919
protected WrappedScaledBigDecimalJavaType(Class<T> type) {
2020
super(type);
2121

22-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
22+
Constructor<T> c;
23+
if (type.isRecord()) {
24+
c = RecordReflectionUtil.getCanonicalConstructor(type);
25+
} else {
26+
try {
27+
c = type.getConstructor(ScaledBigDecimal.class);
28+
} catch (NoSuchMethodException e) {
29+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
30+
}
31+
}
32+
33+
this.constructor = c;
2334
}
2435

2536
@Override
@@ -60,7 +71,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
6071
return (T) value;
6172
}
6273
if (value instanceof Double doubleValue) {
63-
return canonicalConstructor.newInstance(new ScaledBigDecimal(doubleValue));
74+
return constructor.newInstance(new ScaledBigDecimal(doubleValue));
6475
}
6576

6677
throw unknownWrap(value.getClass());

src/main/java/it/aboutbits/springboot/toolbox/persistence/javatype/base/WrappedShortJavaType.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@
1313
import java.sql.Types;
1414

1515
public abstract class WrappedShortJavaType<T extends CustomType<Short>> extends AbstractClassJavaType<T> {
16-
private final transient Constructor<T> canonicalConstructor;
16+
private final transient Constructor<T> constructor;
1717

1818
protected WrappedShortJavaType(Class<T> type) {
1919
super(type);
2020

21-
this.canonicalConstructor = RecordReflectionUtil.getCanonicalConstructor(type);
21+
Constructor<T> c;
22+
if (type.isRecord()) {
23+
c = RecordReflectionUtil.getCanonicalConstructor(type);
24+
} else {
25+
try {
26+
c = type.getConstructor(Short.class);
27+
} catch (NoSuchMethodException e) {
28+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
29+
}
30+
}
31+
32+
this.constructor = c;
2233
}
2334

2435
@Override
@@ -59,7 +70,7 @@ public <X> T wrap(X value, WrapperOptions wrapperOptions) {
5970
return (T) value;
6071
}
6172
if (value instanceof Short shortValue) {
62-
return canonicalConstructor.newInstance(shortValue);
73+
return constructor.newInstance(shortValue);
6374
}
6475

6576
throw unknownWrap(value.getClass());

0 commit comments

Comments
 (0)