Skip to content
Snippets Groups Projects
Commit 812ce762 authored by Karsch Lukas's avatar Karsch Lukas
Browse files

#42 entity mapper

parent 7fa1c96d
No related branches found
No related tags found
1 merge request!27Resolve "plants controller: require admin role & add delete endpoint"
package hdm.mi.growbros.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@Component
public class EntityMapper {
private final static Logger log = LoggerFactory.getLogger(EntityMapper.class);
/**
* Updates fields of an existing entity based on non-null values from an update request.
* This method is designed for use in PATCH operations within a Spring Boot application.
*
* <p>
* The {@code map} method facilitates the partial update of an existing entity by mapping non-null
* fields from an update request object to the corresponding fields in the existing entity.
* Fields in the update request with null values are excluded from the update.
* </p>
*
* <p>
* Usage example:
* <pre>{@code
* // Create an instance of the class containing the map method
* EntityMapper entityMapper = new EntityMapper();
*
* // Create an instance of the existing entity and update request
* ExistingEntity existingEntity = // ... (initialize existing entity)
* UpdateRequest updateRequest = // ... (initialize update request)
*
* // Perform the partial update
* entityMapper.map(updateRequest, existingEntity);
* }</pre>
* </p>
*
* <p>
* Note: This class assumes proper usage in a Spring Boot application, particularly for PATCH
* operations, where only specified fields need to be updated without affecting the entire entity.
* </p>
*
* @param updateRequest The object containing fields with non-null values to be used for updating.
* @param existingEntity The entity object to be updated with non-null values from the update request.
*/
public void map(Object updateRequest, Object existingEntity) {
if (updateRequest == null) {
log.warn("Update request was null, no mapping will take place");
return;
}
if (existingEntity == null) {
log.warn("Existing entity was null, no mapping will take place");
return;
}
final Field[] allUpdaterFields = updateRequest.getClass().getDeclaredFields();
final List<Field> toUpdate = new ArrayList<>();
for (Field updaterField : allUpdaterFields) {
updaterField.setAccessible(true);
try {
if (updaterField.get(updateRequest) != null && !"this$0".equals(updaterField.getName())) {
toUpdate.add(updaterField);
}
} catch (IllegalAccessException e) {
log.error("Illegal access exception while mapping object", e);
}
}
updateFields(toUpdate, updateRequest, existingEntity);
}
private Field getFieldForName(String name, Object o) {
var fields = o.getClass().getDeclaredFields();
for (Field f : fields) {
if (name.equals(f.getName())) return f;
}
throw new IllegalArgumentException("No field with declared name '" + name + "' is present on this object");
}
private void updateFields(List<Field> toUpdate, Object updateRequest, Object existingEntity) {
for (Field updateField : toUpdate) {
try {
updateField.setAccessible(true);
Field entityField = getFieldForName(updateField.getName(), existingEntity);
entityField.setAccessible(true);
final Object newValue = updateField.get(updateRequest);
entityField.set(existingEntity, newValue);
} catch (IllegalAccessException e) {
log.error("Illegal access exception while mapping object", e);
}
}
}
}
package hdm.mi.growbros.util;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class EntityMapperTest {
private EntityMapper entityMapper;
@BeforeEach
void setup() {
entityMapper = new EntityMapper();
}
@Test
void shouldIgnore_whenEitherArgument_isNull() {
//arrange
final Entity entity = getBaseEntity();
final UpdaterObject updater = new UpdaterObject();
//act and assert
assertAll(
() -> assertDoesNotThrow(() -> entityMapper.map(null, entity)),
() -> assertDoesNotThrow(() -> entityMapper.map(updater, null))
);
}
@Test
void shouldUpdate_toNewValues() {
//arrange
final Entity entity = getBaseEntity();
final UpdaterObject updater = new UpdaterObject();
final String expected = "UPDATED value 1";
updater.value1 = expected;
//act
entityMapper.map(updater, entity);
//assert
assertAll(
() -> assertEquals(1, entity.id),
() -> assertEquals(expected, entity.value1),
() -> assertEquals("Value 2", entity.value2)
);
}
private class UpdaterObject {
private String value1;
private String value2;
}
private class Entity {
private int id;
private String value1;
private String value2;
}
private Entity getBaseEntity() {
final Entity entity = new Entity();
entity.id = 1;
entity.value1 = "Value 1";
entity.value2 = "Value 2";
return entity;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment