class ModelValidator {

    public List<ValidationError> getUpdateValidationErrors(Update<?> update, FieldData fieldData) {
        if (update == null) {
            return ImmutableList.of(ValidationError.of("", "update is null"));
        }
        ImmutableList.Builder<ValidationError> errors = ImmutableList.builder();
        Set<String> updateFields = update.getUpdateFields();

        // ensure we are only touching @Updatable fields
        for (String fieldName : updateFields) {
            Field field = fieldData.getMap().get(fieldName);
            if (field == null) {
                errors.add(ValidationError.of(fieldName, "does not exist"));
            } else if (!field.isUpdatable()) {
                errors.add(ValidationError.of(fieldName, "is not updatable"));
            } else if (!field.isOptional() && update.getRemoveFields().contains(fieldName)) {
                errors.add(ValidationError.of(fieldName, "is required"));
            }
        }

        // validate the model -- but ignore fields that aren't being touched
        Set<ConstraintViolation<Object>> violations = validator.validate(update.getPartial(), Default.class);
        Set<String> errorFields = new HashSet<>();
        for (ConstraintViolation<?> cv : violations) {
            String field = cv.getPropertyPath().toString();
            if (updateFields.contains(field) && !errorFields.contains(field)) {
                errors.add(ValidationError.of(field, cv.getMessage()));
                errorFields.add(field);
            }
        }

        return errors.build();
    }

    public  ModelValidator(Validator validator, ObjectMapper mapper);

}