Skip to content

Instantly share code, notes, and snippets.

@cemo
Created October 8, 2012 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cemo/3854759 to your computer and use it in GitHub Desktop.
Save cemo/3854759 to your computer and use it in GitHub Desktop.
package com.yammer.dropwizard.validation;
import com.google.common.base.Joiner;
import com.google.common.collect.*;
import org.hibernate.validator.internal.engine.ConstraintValidatorFactoryImpl;
import javax.validation.*;
import javax.validation.groups.Default;
import java.util.Set;
import static java.lang.String.format;
/**
* A simple façade for Hibernate Validator.
*/
public class Validator {
private Configuration<?> configuration = Validation.byDefaultProvider().configure();
private ClassToInstanceMap<ConstraintValidator> instances = MutableClassToInstanceMap.create();
private InstanceAwareConstraintValidatorFactory instanceAwareConstraintValidatorFactory = new InstanceAwareConstraintValidatorFactory();
private final javax.validation.Validator validator = configuration
.constraintValidatorFactory(instanceAwareConstraintValidatorFactory)
.buildValidatorFactory().getValidator();
/**
* Validates the given object, and returns a list of error messages, if any. If the returned
* list is empty, the object is valid.
*
* @param o a potentially-valid object
* @param <T> the type of object to validate
* @return a list of error messages, if any, regarding {@code o}'s validity
*/
public <T> ImmutableList<String> validate(T o) {
return validate(o, Default.class);
}
/**
* Validates the given object, and returns a list of error messages, if any. If the returned
* list is empty, the object is valid.
* @param o a potentially-valid object
* @param groups group or list of groups targeted for validation (default to {@link javax.validation.groups.Default})
* @param <T> the type of object to validate
* @return a list of error messages, if any, regarding {@code o}'s validity
*/
public <T> ImmutableList<String> validate(T o, Class<?>... groups) {
final Set<String> errors = Sets.newHashSet();
final Set<ConstraintViolation<T>> violations = validator.validate(o, groups);
for (ConstraintViolation<T> v : violations) {
if (v.getConstraintDescriptor().getAnnotation() instanceof ValidationMethod) {
final ImmutableList<Path.Node> nodes = ImmutableList.copyOf(v.getPropertyPath());
final ImmutableList<Path.Node> usefulNodes = nodes.subList(0, nodes.size() - 1);
final String msg = v.getMessage().startsWith(".") ? "%s%s" : "%s %s";
errors.add(format(msg, Joiner.on('.').join(usefulNodes), v.getMessage()).trim());
} else {
errors.add(format("%s %s (was %s)",
v.getPropertyPath(),
v.getMessage(),
v.getInvalidValue()));
}
}
return ImmutableList.copyOf(Ordering.natural().sortedCopy(errors));
}
public void addContraintValidation(ConstraintValidator constraintValidator) {
instances.put(constraintValidator.getClass(), constraintValidator);
}
public void addContraintValidations(Set<ConstraintValidator<?, ?>> constraintValidators) {
for (ConstraintValidator constraintValidator : constraintValidators) {
instances.put(constraintValidator.getClass(), constraintValidator);
}
}
private class InstanceAwareConstraintValidatorFactory implements ConstraintValidatorFactory {
private ConstraintValidatorFactoryImpl defaultFactory = new ConstraintValidatorFactoryImpl();
/**
* Trying to return from instance map. In the absence of instance,
* it delegates to default contraint validator factory.
*
* @param key The class of the constraint validator to instantiate.
* @return A constraint validator instance of the specified class.
* @see org.hibernate.validator.internal.engine.ConstraintValidatorFactoryImpl
*/
@Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
if (instances.containsKey(key)) {
return instances.getInstance(key);
}
return defaultFactory.getInstance(key);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment