I'm rewriting the batch change functionality for a system that takes in a list of Entity objects and a list of changes to apply to all of those objects passing everything by (air quotes)
reference (/air quotes)
, but I'm not quite sure on the best approach.
I have two goals: 1. explicitly return objects and 2. Clean up the function that maps the changes to the object instead of having a giant if-else matching a string to a setter function.
I feel like there has to be a better way to do this that doesn't necessarily require reflection.
My initial idea is to break out the validation into a separate function that would run first, each change would get passed into a validate(entity, change);
function that could return an error description (not throw an error), then if the changes passed they are applied to the Entity object in a single go and then return the altered Entity to be written vs the current pattern of applying field by field.
I don't have any ideas on how to map the BulkEditChange field to the Entity field/setter function besides keeping the giant if-else block in 'setValueForObjectX', I would appreciate any ideas.
Below is a over simplification of the way it is written now:
POJO that contains the change
public class BulkEditChange {
private String field; //name of field to change on Entity Object
private String modifier; // 'append', 'add' or 'subtract' used for integer values
private String value; //String representation of the value
public String getField() {
return field;
}
public String getModifier() {
return modifier;
}
public void setModifier(String modifier) {
this.modifier = modifier;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Then in the service class the changes are applied to the given object
private Entity updateEntityValues(List<Entity> entities, List<BulkEditChange> changes, String batchId) {
List<ValidationError> errors = new ArrayList();
for(Entity entity : entities) {
for (BulkEditChange change : changes) {
if (refreshedEntity instanceof ObjectX) {
setValueForObjectX((ObjectX) refreshedEntity, fieldView, errors);
} else { //instance of another object
setValueForObjectY((ObjectY) refreshedEntity, fieldView, errors);
}
}
}
if(ArrayUtils.isNotEmpty(errors)){
throw new CombinedValidationError("Changes could not be applied because reasons", errors);
}
entityDAO.writeAll(entities);
}
//GOAL 1: Stop attempting to pass the Entity and Errors list by 'reference'
private void setValueForObjectX(ObjectX obj, BulkEditChange change, List<ValidationError> errors){
//GOAL 2: See if I can make this mapping of field name to setter less brute force?
if(change.getField().equals("name")){
if(change.getValue() == null){
ValidationError error = new ValidationError("name cannot be blank");
errors.add(error);
} else {
entity.setName(change.getValue());
}
} else if( change.getField.equals("type")){
//do business logic to check the type, add to errors list if doesn't pass
//if valid set on the entity object
} else if( // Is other field)...
// Goes on and on for each field that can be altered
}
private void setValueForObjectY(ObjectY obj, BulkEditChange change, List<ValidationError> errors){
//Same idea with other object type value setting functions
//Just with different validations
}
Aucun commentaire:
Enregistrer un commentaire