package com.forter.contracts.validation; import com.google.common.base.Optional; import com.google.common.base.Throwables; import com.google.common.collect.Sets; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import javax.validation.ConstraintViolation; import javax.validation.ValidationException; import java.util.Set; /** * A set of {@link ConstraintViolation}s that has a proper {@link #toString} method. * Also supports {@link javax.validation.ValidationException} */ public class ValidatedContract<T> { private final Set<ConstraintViolation<T>> violations; private final Optional<ValidationException> exception; private final T contract; public ValidatedContract(T contract, Set<ConstraintViolation<T>> violations) { this(contract, violations, Optional.<ValidationException>absent()); } public ValidatedContract(T contract, ValidationException e) { this(contract, Sets.<ConstraintViolation<T>>newHashSet(), Optional.of(e)); } private ValidatedContract(T contract, Set<ConstraintViolation<T>> violations, Optional<ValidationException> exception) { this.contract = contract; this.violations = violations; /** TODO: Remove when https://github.com/forter/storm-data-contracts/issues/6 is resolved * and the null check is removed from {@link OptionalUnwrapperhandleValidatedValue} */ this.exception = exception; } public String toString() { if (isValid()) { return "valid contract"; } final StringBuffer sb = new StringBuffer(); if (!violations.isEmpty()) { sb.append(violations.size()).append(" contract violations: "); for (final ConstraintViolation violation : violations) { sb.append(violation.getPropertyPath()).append(" is ").append(violation.getInvalidValue()) .append(" but ").append(violation.getMessage()) .append(". "); } } if (exception.isPresent()) { Throwable rootCause = Throwables.getRootCause(exception.get()); sb.append(rootCause.getMessage()); } if (contract == null) { sb.append(" Contract: null"); } else { sb.append(" Contract:").append(ToStringBuilder.reflectionToString(contract, ToStringStyle.SHORT_PREFIX_STYLE)); } final String message = sb.toString(); return message; } public boolean isValid() { return violations.isEmpty() && !exception.isPresent(); } public T getContract() { return contract; } }