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();
}
}
}