package scotch.test; import static java.util.Collections.emptyList; import static lombok.AccessLevel.PRIVATE; import static org.apache.commons.lang.StringEscapeUtils.escapeJava; import static scotch.runtime.RuntimeSupport.applicable; import static scotch.runtime.RuntimeSupport.callable; import static scotch.symbol.type.TypeDescriptors.fn; import static scotch.symbol.type.TypeDescriptors.sum; import java.util.List; import java.util.Objects; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import scotch.data.string.String_; import scotch.runtime.Applicable; import scotch.runtime.Callable; import scotch.symbol.DataConstructor; import scotch.symbol.DataType; import scotch.symbol.TypeParameters; import scotch.symbol.Value; import scotch.symbol.ValueType; import scotch.symbol.type.TypeDescriptor; @DataType(memberName = "ExpectationResult") public abstract class ExpectationResult { public static final TypeDescriptor TYPE = sum("scotch.test.ExpectationResult"); private static final Callable<SuccessfulExpectation> SUCCESS = callable(SuccessfulExpectation::new); @Value(memberName = "FailedExpectation") public static Applicable<String, FailedExpectation> failedExpectation() { return applicable(message -> callable(() -> new FailedExpectation(message))); } @ValueType(forMember = "FailedExpectation") public static TypeDescriptor failedExpectation$type() { return fn(String_.TYPE, TYPE); } @TypeParameters public static List<TypeDescriptor> parameters() { return emptyList(); } @Value(memberName = "SuccessfulExpectation") public static Callable<SuccessfulExpectation> successfulExpectation() { return SUCCESS; } @ValueType(forMember = "SuccessfulExpectation") public static TypeDescriptor successfulExpectation$type() { return TYPE; } private ExpectationResult() { // intentionally empty } public abstract <T> Callable<T> accept(Visitor<T> visitor); @Override public abstract boolean equals(Object o); @Override public abstract int hashCode(); @Override public abstract String toString(); public interface Visitor<T> { Callable<T> visit(SuccessfulExpectation successfulExpectation); Callable<T> visit(FailedExpectation failedExpectation); } @DataConstructor(memberName = "FailedExpectation", dataType = "ExpectationResult", ordinal = 1) @AllArgsConstructor(access = PRIVATE) public static class FailedExpectation extends ExpectationResult { @Getter private final Callable<String> message; @Override public <T> Callable<T> accept(Visitor<T> visitor) { return visitor.visit(this); } @Override public boolean equals(Object o) { return o == this || o instanceof FailedExpectation && Objects.equals(message.call(), ((FailedExpectation) o).message.call()); } @Override public int hashCode() { return Objects.hash(message.call()); } @Override public String toString() { return getClass().getSimpleName() + " { message = \"" + escapeJava(message.call()) + "\" }"; } } @DataConstructor(memberName = "SuccessfulExpectation", dataType = "ExpectationResult", ordinal = 0) @EqualsAndHashCode(callSuper = false) public static class SuccessfulExpectation extends ExpectationResult { private SuccessfulExpectation() { // intentionally empty } @Override public <T> Callable<T> accept(Visitor<T> visitor) { return visitor.visit(this); } @Override public String toString() { return getClass().getSimpleName(); } } }