Skip to content

Commit cb7c9b9

Browse files
committed
add missing primitive types
1 parent 3b86ba1 commit cb7c9b9

23 files changed

Lines changed: 724 additions & 1 deletion

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

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,18 @@ public T deserialize(JsonParser jsonParser, DeserializationContext deserializati
5656
}
5757

5858
private static Function<JsonParser, Object> getTypeConverter(Class<?> wrappedType) {
59+
if (Byte.class.isAssignableFrom(wrappedType)) {
60+
return getByteConverter();
61+
}
62+
if (Boolean.class.isAssignableFrom(wrappedType)) {
63+
return getBooleanConverter();
64+
}
5965
if (String.class.isAssignableFrom(wrappedType)) {
6066
return getStringConverter();
6167
}
68+
if (Character.class.isAssignableFrom(wrappedType)) {
69+
return getCharConverter();
70+
}
6271
if (Short.class.isAssignableFrom(wrappedType)) {
6372
return getShortConverter();
6473
}
@@ -86,6 +95,26 @@ private static Function<JsonParser, Object> getTypeConverter(Class<?> wrappedTyp
8695
throw new CustomTypeDeserializerException("Value type not supported: " + wrappedType.getName());
8796
}
8897

98+
private static Function<JsonParser, Object> getByteConverter() {
99+
return jsonParser -> {
100+
try {
101+
return jsonParser.getByteValue();
102+
} catch (IOException e) {
103+
throw new CustomTypeDeserializerException("Failed to read value as Byte.", e);
104+
}
105+
};
106+
}
107+
108+
private static Function<JsonParser, Object> getBooleanConverter() {
109+
return jsonParser -> {
110+
try {
111+
return jsonParser.getBooleanValue();
112+
} catch (IOException e) {
113+
throw new CustomTypeDeserializerException("Failed to read value as Boolean.", e);
114+
}
115+
};
116+
}
117+
89118
private static Function<JsonParser, Object> getScaledBigDecimalConverter() {
90119
return jsonParser -> {
91120
try {
@@ -176,6 +205,20 @@ private static Function<JsonParser, Object> getStringConverter() {
176205
};
177206
}
178207

208+
private static Function<JsonParser, Object> getCharConverter() {
209+
return jsonParser -> {
210+
try {
211+
var value = jsonParser.getValueAsString();
212+
if (value == null || value.length() != 1) {
213+
throw new IOException();
214+
}
215+
return value.charAt(0);
216+
} catch (IOException e) {
217+
throw new CustomTypeDeserializerException("Failed to read value as Char.", e);
218+
}
219+
};
220+
}
221+
179222
public static final class CustomTypeDeserializerException extends RuntimeException {
180223
public CustomTypeDeserializerException(String message) {
181224
super(message);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package it.aboutbits.springboot.toolbox.persistence.javatype.base;
2+
3+
import it.aboutbits.springboot.toolbox.type.CustomType;
4+
import lombok.SneakyThrows;
5+
import org.hibernate.type.descriptor.WrapperOptions;
6+
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
7+
import org.hibernate.type.descriptor.jdbc.JdbcType;
8+
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
9+
10+
import java.lang.reflect.Constructor;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.sql.Types;
13+
14+
public abstract class WrappedBooleanJavaType<T extends CustomType<Boolean>> extends AbstractClassJavaType<T> {
15+
private final transient Constructor<T> constructor;
16+
17+
protected WrappedBooleanJavaType(Class<T> type) {
18+
super(type);
19+
20+
try {
21+
this.constructor = type.getConstructor(Boolean.class);
22+
} catch (NoSuchMethodException e) {
23+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
24+
}
25+
}
26+
27+
@Override
28+
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
29+
return indicators.getTypeConfiguration()
30+
.getJdbcTypeRegistry()
31+
.getDescriptor(Types.BOOLEAN);
32+
}
33+
34+
@SuppressWarnings("unchecked")
35+
@Override
36+
public <X> X unwrap(T id, Class<X> aClass, WrapperOptions wrapperOptions) {
37+
var javaTypeClass = getJavaTypeClass();
38+
39+
if (id == null) {
40+
return null;
41+
}
42+
if (javaTypeClass.isAssignableFrom(aClass)) {
43+
return (X) id;
44+
}
45+
if (Boolean.class.isAssignableFrom(aClass)) {
46+
return (X) id.value();
47+
}
48+
49+
throw unknownUnwrap(aClass);
50+
}
51+
52+
@SuppressWarnings("unchecked")
53+
@SneakyThrows({InstantiationException.class, IllegalAccessException.class, InvocationTargetException.class})
54+
@Override
55+
public <X> T wrap(X value, WrapperOptions wrapperOptions) {
56+
var clazz = getJavaTypeClass();
57+
58+
if (value == null) {
59+
return null;
60+
}
61+
if (clazz.isInstance(value)) {
62+
return (T) value;
63+
}
64+
if (value instanceof Boolean booleanValue) {
65+
return constructor.newInstance(booleanValue);
66+
}
67+
68+
throw unknownWrap(value.getClass());
69+
}
70+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package it.aboutbits.springboot.toolbox.persistence.javatype.base;
2+
3+
import it.aboutbits.springboot.toolbox.type.CustomType;
4+
import lombok.SneakyThrows;
5+
import org.hibernate.type.descriptor.WrapperOptions;
6+
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
7+
import org.hibernate.type.descriptor.jdbc.JdbcType;
8+
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
9+
10+
import java.lang.reflect.Constructor;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.sql.Types;
13+
14+
public abstract class WrappedByteJavaType<T extends CustomType<Byte>> extends AbstractClassJavaType<T> {
15+
private final transient Constructor<T> constructor;
16+
17+
protected WrappedByteJavaType(Class<T> type) {
18+
super(type);
19+
20+
try {
21+
this.constructor = type.getConstructor(Byte.class);
22+
} catch (NoSuchMethodException e) {
23+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
24+
}
25+
}
26+
27+
@Override
28+
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
29+
return indicators.getTypeConfiguration()
30+
.getJdbcTypeRegistry()
31+
.getDescriptor(Types.TINYINT);
32+
}
33+
34+
@SuppressWarnings("unchecked")
35+
@Override
36+
public <X> X unwrap(T id, Class<X> aClass, WrapperOptions wrapperOptions) {
37+
var javaTypeClass = getJavaTypeClass();
38+
39+
if (id == null) {
40+
return null;
41+
}
42+
if (javaTypeClass.isAssignableFrom(aClass)) {
43+
return (X) id;
44+
}
45+
if (Byte.class.isAssignableFrom(aClass)) {
46+
return (X) id.value();
47+
}
48+
49+
throw unknownUnwrap(aClass);
50+
}
51+
52+
@SuppressWarnings("unchecked")
53+
@SneakyThrows({InstantiationException.class, IllegalAccessException.class, InvocationTargetException.class})
54+
@Override
55+
public <X> T wrap(X value, WrapperOptions wrapperOptions) {
56+
var clazz = getJavaTypeClass();
57+
58+
if (value == null) {
59+
return null;
60+
}
61+
if (clazz.isInstance(value)) {
62+
return (T) value;
63+
}
64+
if (value instanceof Byte byteValue) {
65+
return constructor.newInstance(byteValue);
66+
}
67+
68+
throw unknownWrap(value.getClass());
69+
}
70+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package it.aboutbits.springboot.toolbox.persistence.javatype.base;
2+
3+
import it.aboutbits.springboot.toolbox.type.CustomType;
4+
import lombok.SneakyThrows;
5+
import org.hibernate.type.descriptor.WrapperOptions;
6+
import org.hibernate.type.descriptor.java.AbstractClassJavaType;
7+
import org.hibernate.type.descriptor.jdbc.JdbcType;
8+
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
9+
10+
import java.lang.reflect.Constructor;
11+
import java.lang.reflect.InvocationTargetException;
12+
import java.sql.Types;
13+
14+
public abstract class WrappedCharacterJavaType<T extends CustomType<Character>> extends AbstractClassJavaType<T> {
15+
private final transient Constructor<T> constructor;
16+
17+
protected WrappedCharacterJavaType(Class<T> type) {
18+
super(type);
19+
20+
try {
21+
this.constructor = type.getConstructor(Character.class);
22+
} catch (NoSuchMethodException e) {
23+
throw new IllegalStateException("No constructor found for " + type.getName(), e);
24+
}
25+
}
26+
27+
@Override
28+
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators indicators) {
29+
return indicators.getTypeConfiguration()
30+
.getJdbcTypeRegistry()
31+
.getDescriptor(Types.CHAR);
32+
}
33+
34+
@SuppressWarnings("unchecked")
35+
@Override
36+
public <X> X unwrap(T id, Class<X> aClass, WrapperOptions wrapperOptions) {
37+
var javaTypeClass = getJavaTypeClass();
38+
39+
if (id == null) {
40+
return null;
41+
}
42+
if (javaTypeClass.isAssignableFrom(aClass)) {
43+
return (X) id;
44+
}
45+
if (Character.class.isAssignableFrom(aClass)) {
46+
return (X) id.value();
47+
}
48+
if (String.class.isAssignableFrom(aClass)) {
49+
return (X) String.valueOf(id.value());
50+
}
51+
52+
throw unknownUnwrap(aClass);
53+
}
54+
55+
@SuppressWarnings("unchecked")
56+
@SneakyThrows({InstantiationException.class, IllegalAccessException.class, InvocationTargetException.class})
57+
@Override
58+
public <X> T wrap(X value, WrapperOptions wrapperOptions) {
59+
var clazz = getJavaTypeClass();
60+
61+
if (value == null) {
62+
return null;
63+
}
64+
if (clazz.isInstance(value)) {
65+
return (T) value;
66+
}
67+
if (value instanceof Character charValue) {
68+
return constructor.newInstance(charValue);
69+
}
70+
if (value instanceof String stringValue && stringValue.length() == 1) {
71+
return constructor.newInstance(stringValue.charAt(0));
72+
}
73+
74+
throw unknownWrap(value.getClass());
75+
}
76+
}

src/main/java/it/aboutbits/springboot/toolbox/swagger/type/CustomTypeModelConverter.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ public Schema<?> resolve(
3535
(Class<? extends CustomType<?>>) clazz
3636
);
3737

38+
if (Boolean.class.isAssignableFrom(wrappedType)) {
39+
result = context.resolve(new AnnotatedType(Boolean.TYPE));
40+
}
41+
if (Byte.class.isAssignableFrom(wrappedType)) {
42+
result = context.resolve(new AnnotatedType(Byte.TYPE));
43+
}
3844
if (Short.class.isAssignableFrom(wrappedType)) {
3945
result = context.resolve(new AnnotatedType(Short.TYPE));
4046
}
@@ -62,6 +68,9 @@ public Schema<?> resolve(
6268
if (String.class.isAssignableFrom(wrappedType)) {
6369
result = context.resolve(new AnnotatedType(String.class));
6470
}
71+
if (Character.class.isAssignableFrom(wrappedType)) {
72+
result = context.resolve(new AnnotatedType(Character.TYPE));
73+
}
6574

6675
if (result != null) {
6776
var isIdentity = EntityId.class.isAssignableFrom(clazz);

src/main/java/it/aboutbits/springboot/toolbox/swagger/type/CustomTypePropertyCustomizer.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,22 @@ public Schema<?> customize(Schema property, AnnotatedType annotatedType) {
4242

4343
var description = SwaggerMetaUtil.setIsIdentity(property.getDescription(), isIdentity);
4444

45+
if (Boolean.class.isAssignableFrom(wrappedType)) {
46+
property.type("boolean");
47+
property.format(null);
48+
property.setDescription(description);
49+
property.setProperties(null);
50+
property.set$ref(null);
51+
return property;
52+
}
53+
if (Byte.class.isAssignableFrom(wrappedType)) {
54+
property.type("integer");
55+
property.format("");
56+
property.setDescription(description);
57+
property.setProperties(null);
58+
property.set$ref(null);
59+
return property;
60+
}
4561
if (Short.class.isAssignableFrom(wrappedType)) {
4662
property.type("integer");
4763
property.format("");
@@ -98,7 +114,6 @@ public Schema<?> customize(Schema property, AnnotatedType annotatedType) {
98114
property.set$ref(null);
99115
return property;
100116
}
101-
102117
if (ScaledBigDecimal.class.isAssignableFrom(wrappedType)) {
103118
property.type("number");
104119
property.format("");
@@ -115,6 +130,17 @@ public Schema<?> customize(Schema property, AnnotatedType annotatedType) {
115130
property.set$ref(null);
116131
return property;
117132
}
133+
if (Character.class.isAssignableFrom(wrappedType)) {
134+
property.type("string");
135+
property.format(null);
136+
property.minLength(1);
137+
property.maxLength(1);
138+
property.setDescription(description);
139+
property.setProperties(null);
140+
property.set$ref(null);
141+
return property;
142+
}
143+
118144
log.warn("Property {} of type WrappedValue: Can not resolve parameter type!", property.getName());
119145
}
120146
}

src/main/java/it/aboutbits/springboot/toolbox/web/CustomTypePropertyEditor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,23 @@ public void setAsText(String text) throws IllegalArgumentException {
5959
}
6060

6161
private static Function<String, Object> getTextToTypeConverter(Class<?> wrappedType) {
62+
if (Boolean.class.isAssignableFrom(wrappedType)) {
63+
return Boolean::parseBoolean;
64+
}
6265
if (String.class.isAssignableFrom(wrappedType)) {
6366
return text -> text;
6467
}
68+
if (Character.class.isAssignableFrom(wrappedType)) {
69+
return text -> {
70+
if (text == null || text.length() != 1) {
71+
throw new IllegalArgumentException("Unable to convert text to type: " + wrappedType.getName());
72+
}
73+
return text.charAt(0);
74+
};
75+
}
76+
if (Byte.class.isAssignableFrom(wrappedType)) {
77+
return Byte::parseByte;
78+
}
6579
if (Short.class.isAssignableFrom(wrappedType)) {
6680
return Short::parseShort;
6781
}

0 commit comments

Comments
 (0)