Search code examples
javavalidationenumsannotationshibernate-validator

Custom annotation to validate string against enum type


I am trying to write a custom annotation that would validate a String against a specific Enum. I am using Hibernate Validator API. The desired use-case would look like follows.

@MessageTypeOf(MessageType.NETWORK)
private String message;

The String should be validated against the value given from the toString() method of the enum given as the enum argument (in this case, MessageType.NETWORK).

I have written a validator and looks like this.

public class MessageTypeValidator implements ConstraintValidator<MessageTypeOf, String> {

    private Set<String> values;

    @Override
    public void initialize(MessageTypeOf constraintAnnotation) {
        values = Arrays.asList(MessageType.values())
                .stream()
                .map(v -> v.toString())
                .collect(Collectors.toSet());
    }

    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        if (s == null) return false;

        return values.contains(s);
    }
}

And the annotation.

@Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE, TYPE_USE })
@Retention(RUNTIME)
@Constraint(validatedBy = MessageTypeValidator.class)
@Documented
public @interface MessageTypeOf {

    String message() default "{org.hibernate.validator.referenceguide.chapter06.CheckCase." +
            "message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    MessageType value();

    @Target({ FIELD, METHOD, PARAMETER, ANNOTATION_TYPE })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        MessageType[] value();
    }
}

However, this would validate if a string is part of the enum (any value), where as I need to validate against a specific one. Could someone suggest how to do that?


Solution

  • So, basically, the only valid value of the property would be MessageType.NETWORK.toString(), is that right? That's quite strange (expecting the client to provide a string that can only have one valid value), but anyway, you just need to check that:

    public class MessageTypeValidator implements ConstraintValidator<MessageTypeOf, String> {
    
        private String validValue;
    
        @Override
        public void initialize(MessageTypeOf constraintAnnotation) {
            this.validValue = constraintAnnotation.value().toString();
        }
    
        @Override
        public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
            return this.validValue.equals(s);
        }
    }