1
0

test code coverage improved and more JSon/field types

This commit is contained in:
Michael Hoennig
2019-04-25 18:53:16 +02:00
parent 070f321a06
commit a6fd210de5
11 changed files with 466 additions and 149 deletions

View File

@ -28,10 +28,6 @@ abstract class JSonAccessFilter<T> {
this.parentIdField = determineFieldWithAnnotation(dto.getClass(), ParentId.class);
}
boolean isParentIdField(final Field field) {
return field.equals(parentIdField);
}
Long getId() {
if (selfIdField == null) {
return null;
@ -95,7 +91,7 @@ abstract class JSonAccessFilter<T> {
@SuppressWarnings("unchecked")
protected Object loadDto(final Class<? extends IdToDtoResolver> resolverClass, final Long id) {
verify(id != null, "id must not be null");
verify(id != null, "id must not be null for " + resolverClass.getSimpleName());
final AutowireCapableBeanFactory beanFactory = ctx.getAutowireCapableBeanFactory();
verify(beanFactory != null, "no bean factory found, probably missing mock configuration for ApplicationContext, e.g. given(...)");

View File

@ -11,6 +11,7 @@ import org.hostsharing.hsadminng.web.rest.errors.BadRequestAlertException;
import org.springframework.context.ApplicationContext;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Set;
@ -40,8 +41,8 @@ public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
treeNode.fieldNames().forEachRemaining(fieldName -> {
try {
final Field field = dto.getClass().getDeclaredField(fieldName);
final Object newValue = readValue(treeNode, field);
writeValue(dto, field, newValue);
final Object newValue = readValueFromJSon(treeNode, field);
writeValueToDto(dto, field, newValue);
} catch (NoSuchFieldException e) {
throw new RuntimeException("setting field " + fieldName + " failed", e);
}
@ -69,12 +70,12 @@ public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
}
}
private Object readValue(final TreeNode treeNode, final Field field) {
return readValue(treeNode, field.getName(), field.getType());
private Object readValueFromJSon(final TreeNode treeNode, final Field field) {
return readValueFromJSon(treeNode, field.getName(), field.getType());
}
private Object readValue(final TreeNode treeNode, final String fieldName, final Class<?> fieldClass) {
private Object readValueFromJSon(final TreeNode treeNode, final String fieldName, final Class<?> fieldClass) {
final TreeNode fieldNode = treeNode.get(fieldName);
if (fieldNode instanceof NullNode) {
return null;
@ -88,23 +89,29 @@ public class JSonDeserializerWithAccessFilter<T> extends JSonAccessFilter<T> {
if (fieldNode instanceof LongNode) {
return ((LongNode) fieldNode).asLong();
}
if (fieldNode instanceof DoubleNode) {
// TODO: we need to figure out, why DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS does not work
return ((DoubleNode) fieldNode).asDouble();
}
if (fieldNode instanceof ArrayNode && LocalDate.class.isAssignableFrom(fieldClass)) {
return LocalDate.of(((ArrayNode) fieldNode).get(0).asInt(), ((ArrayNode) fieldNode).get(1).asInt(), ((ArrayNode) fieldNode).get(2).asInt());
}
{
throw new NotImplementedException("property type not yet implemented: " + fieldNode + " -> " + fieldName + ": " + fieldClass);
}
throw new NotImplementedException("JSon node type not implemented: " + fieldNode.getClass() + " -> " + fieldName + ": " + fieldClass);
}
private void writeValue(final T dto, final Field field, final Object value) {
private void writeValueToDto(final T dto, final Field field, final Object value) {
if (value == null) {
ReflectionUtil.setValue(dto, field, null);
} else if (field.getType().isAssignableFrom(value.getClass())) {
ReflectionUtil.setValue(dto, field, value);
} else if (Integer.class.isAssignableFrom(field.getType()) || int.class.isAssignableFrom(field.getType())) {
} else if (int.class.isAssignableFrom(field.getType())) {
ReflectionUtil.setValue(dto, field, ((Number) value).intValue());
} else if (Long.class.isAssignableFrom(field.getType()) || long.class.isAssignableFrom(field.getType())) {
ReflectionUtil.setValue(dto, field, ((Number) value).longValue());
} else if (BigDecimal.class.isAssignableFrom(field.getType())) {
ReflectionUtil.setValue(dto, field, new BigDecimal(value.toString()));
} else if (Boolean.class.isAssignableFrom(field.getType()) || boolean.class.isAssignableFrom(field.getType())) {
ReflectionUtil.setValue(dto, field, Boolean.valueOf(value.toString()));
} else if (field.getType().isEnum()) {
ReflectionUtil.setValue(dto, field, Enum.valueOf((Class<Enum>) field.getType(), value.toString()));
} else if (LocalDate.class.isAssignableFrom(field.getType())) {

View File

@ -4,10 +4,12 @@ package org.hostsharing.hsadminng.service.accessfilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.lang3.NotImplementedException;
import org.hostsharing.hsadminng.service.util.ReflectionUtil;
import org.springframework.context.ApplicationContext;
import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.time.LocalDate;
public class JSonSerializerWithAccessFilter<T> extends JSonAccessFilter<T> {
@ -41,32 +43,27 @@ public class JSonSerializerWithAccessFilter<T> extends JSonAccessFilter<T> {
// Alternatively extract the supported types to subclasses of some abstract class and
// here as well as in the deserializer just access the matching implementation through a map.
// Or even completely switch from Jackson to GSON?
final Object fieldValue = get(dto, field);
final Object fieldValue = ReflectionUtil.getValue(dto, field);
if (fieldValue == null) {
jsonGenerator.writeNullField(fieldName);
} else if (String.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeStringField(fieldName, (String) fieldValue);
} else if (Integer.class.isAssignableFrom(field.getType()) || int.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeNumberField(fieldName, (int) fieldValue);
} else if (Long.class.isAssignableFrom(field.getType()) || long.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeNumberField(fieldName, (long) fieldValue);
} else if (LocalDate.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeStringField(fieldName, fieldValue.toString()); // TODO proper format
jsonGenerator.writeStringField(fieldName, fieldValue.toString());
} else if (Enum.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeStringField(fieldName, fieldValue.toString()); // TODO proper representation
} else if (String.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeStringField(fieldName, (String) fieldValue);
jsonGenerator.writeStringField(fieldName, ((Enum) fieldValue).name());
} else if (Boolean.class.isAssignableFrom(field.getType()) || boolean.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeBooleanField(fieldName, (Boolean) fieldValue);
} else if (BigDecimal.class.isAssignableFrom(field.getType())) {
jsonGenerator.writeNumberField(fieldName, (BigDecimal) fieldValue);
} else {
throw new NotImplementedException("property type not yet implemented: " + field);
}
}
}
private Object get(final Object dto, final Field field) {
try {
field.setAccessible(true);
return field.get(dto);
} catch (IllegalAccessException e) {
throw new RuntimeException("getting field " + field + " failed", e);
}
}
}