I need to find all 'missing' and extra fields for every dto's by their entities using reflection. For example.
I have
public class TestDto {
long id;
String name;
int age;
long personId;
String phone;
}
And Entity
public class TestEntity {
long id;
String name;
int age;
Person person;
String address;
}
person = personId(mapping). We don't need to print it like 'missing' field and 'extra' field.
Output: Missing fields for dto. Please add!: address; Extra fields for dto. Please remove! : phone;
i wrote
private final Map<String, String> fieldMappings = new HashMap<>();
fieldMappings.put("person", "personId");
Field[] dtoFields = auditDtoClass.getDeclaredFields();
Field[] entityFields = entityClass.getDeclaredFields();
List<String> missingFields = Arrays.stream(entityFields)
.filter(field -> !fieldMappings.containsKey(field.getName()) && Stream.of(dtoFields)
.noneMatch(dtoField -> dtoField.getName().equals(field.getName())))
.map(Field::getName)
.filter(field -> Arrays.stream(dtoFields)
.noneMatch(f -> f.getName().equals(field)))
.toList();
List<String> extraFields = Arrays.stream(dtoFields)
.filter(field -> !fieldMappings.containsValue(field.getName()) &&
!fieldMappings.containsKey(field.getName()) && Stream.of(entityFields)
.noneMatch(entityField -> entityField.getName().equals(field.getName())))
.map(Field::getName)
.filter(field -> Arrays.stream(entityFields)
.noneMatch(f -> f.getName().equals(field)))
.toList();
It's wrong.
Because programmer can add (private Person person field) in other entity without adding to dto and it didn't print it in missing fields.
I also think that we can link those fields
fieldMappings.put("person", "personId");
to the entity/dto classes but now I don't understand how.
I'd love to hear ideas on how to do this.
CodePudding user response:
This should do the trick. Please optimize the code to your needs.
{
Map<String, Class<?>> testDtoDeclarationMap = getFieldDeclarationMap(new TestDto());
Map<String, Class<?>> testEntityDeclarationMap = getFieldDeclarationMap(new TestEntity());
testDtoDeclarationMap.forEach(((k, v) -> {
if (!(testEntityDeclarationMap.containsKey(k) && testDtoDeclarationMap.get(k) == testEntityDeclarationMap.get(k))) {
System.out.println("Extra fields for dto. Please remove!: '" k "' with the datatype: " v);
}
}));
testEntityDeclarationMap.forEach(((k, v) -> {
if (!(testDtoDeclarationMap.containsKey(k) && testEntityDeclarationMap.get(k) == testDtoDeclarationMap.get(k))) {
System.out.println("Missing fields for dto. Please add!: '" k "' with the datatype: " v);
}
}));
}
Map<String, Class<?>> getFieldDeclarationMap(Object obj) {
Map<String, Class<?>> map = new HashMap<>();
Field[] declaredFields = obj.getClass().getDeclaredFields();
for (int x=0; x<declaredFields.length; x ) {
Field field = declaredFields[x];
String name = field.getName();
Class<?> type = field.getType();
map.put(name, type);
}
return map;
}
CodePudding user response:
I decided to create 'config' for mappings. For each entity.
private final Map<String, Map<String, String>> entityFieldMappings = new HashMap<>();
Then add some 'mappings'
entityFieldMappings.put("TestEntity", Map.of("person", "personId"));
entityFieldMappings.put("SampleEntity", Map.of(
"customer", "customerId",
"location", "locationId",
"storageCondition", "storageConditionId"
));
Then created method for comparing entity and dto fields
private void compareFields(Class<?> entity, Class<?> dto, String entityName, Map<String, Map<String, String>> fieldMappings) {
final Set<String> entityFieldNames = Arrays.stream(entity.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet());
final Set<String> dtoFieldNames = Arrays.stream(dto.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet());
Map<String, String> entityMappings = fieldMappings.get(entityName);
Set<String> missingFields = entityFieldNames.stream()
.filter(fieldName -> !dtoFieldNames.contains(fieldName) && !entityMappings.containsKey(fieldName))
.collect(Collectors.toSet());
Set<String> extraFields = dtoFieldNames.stream()
.filter(fieldName -> !entityFieldNames.contains(fieldName) && !entityMappings.containsValue(fieldName))
.collect(Collectors.toSet());
if (!missingFields.isEmpty()) {
log.error("Missing fields in Dto: " dto.getName() " for entity: " entity.getName() " are: " missingFields);
}
if (!extraFields.isEmpty()) {
log.error("Extra fields in Dto: " dto.getName() " for entity: " entity.getName() " are: " extraFields);
}
}