package io.airlift.airship.coordinator; import com.google.common.collect.ImmutableMap; import io.airlift.http.client.Request; import io.airlift.http.client.Response; import io.airlift.http.client.ResponseHandler; import org.apache.bval.jsr303.ApacheValidationProvider; import javax.validation.ConstraintViolation; import javax.validation.Validation; import javax.validation.Validator; import java.util.Map; import static com.google.common.base.Preconditions.checkNotNull; public class ValidatingResponseHandler<T, E extends Exception> implements ResponseHandler<T, E> { private static final Validator VALIDATOR = Validation.byProvider(ApacheValidationProvider.class).configure().buildValidatorFactory().getValidator(); private final ResponseHandler<T, E> handler; public static <T, E extends Exception> ValidatingResponseHandler<T, E> validate(ResponseHandler<T, E> handler) { return new ValidatingResponseHandler<>(handler); } private ValidatingResponseHandler(ResponseHandler<T, E> handler) { this.handler = checkNotNull(handler, "handler is null"); } @Override public T handleException(Request request, Exception exception) throws E { return handler.handleException(request, exception); } @Override public T handle(Request request, Response response) throws E { T result = handler.handle(request, response); Map<String, String> violations = validateObject(result); if (!violations.isEmpty()) { return handler.handleException(request, new IllegalArgumentException("Response result is invalid: " + violations)); } return result; } private static <T> Map<String, String> validateObject(T object) { ImmutableMap.Builder<String, String> map = ImmutableMap.builder(); for (ConstraintViolation<T> violation : VALIDATOR.validate(object)) { map.put(violation.getPropertyPath().toString(), violation.getMessage()); } return map.build(); } }