class ModelValidator {

    public List<ValidationError> getCreateValidationErrors(Object create, FieldData fieldData) {
        if (create == null) {
            return ImmutableList.of(ValidationError.of("", "create is null"));
        }

        ImmutableList.Builder<ValidationError> errors = ImmutableList.builder();
        Map<String,Object> createMap = mapper.convertValue(create, new TypeReference<Map<String,Object>>() { });
        Set<String> createFields = createMap.keySet();
        for (String fieldName : createFields) {
            Field field = fieldData.getMap().get(fieldName);
            if (field == null) {
                errors.add(ValidationError.of(fieldName, "does not exist"));
            } else if (!field.isCreatable() && !field.isUpdatable()) {
                errors.add(ValidationError.of(fieldName, "is not creatable"));
            }
        }
        for (Field field : fieldData.getMap().values()) {
            Object value = createMap.get(field.getName());
            if (!field.isOptional() && (field.isCreatable() || field.isUpdatable()) && (value == null || "".equals(value))) {
                errors.add(ValidationError.of(field.getName(), "is required"));
            }
        }
        Set<ConstraintViolation<Object>> violations = validator.validate(create, Default.class);
        Set<String> errorFields = new HashSet<>();
        for (ConstraintViolation<?> cv : violations) {
            String field = cv.getPropertyPath().toString();
            if (createFields.contains(field) && !errorFields.contains(field)) {
                errors.add(ValidationError.of(field, cv.getMessage()));
                errorFields.add(field);
            }
        }
        return errors.build();
    }

    public  ModelValidator(Validator validator, ObjectMapper mapper);

}