package com.github.dakusui.jcunit8.exceptions;

import com.github.dakusui.jcunit.core.tuples.Tuple;
import com.github.dakusui.jcunit8.factorspace.Constraint;

import java.util.List;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static java.lang.String.format;

/**
 * Indicates user's artifact (Typically test classes, annotated with
 * {@literal @}{@code Runwith(JCUnit.class)}), is invalid.
 */
public class TestDefinitionException extends BaseException {
  private TestDefinitionException(String message) {
    super(message);
  }

  private TestDefinitionException(String message, Throwable e) {
    super(message, e);
  }

  public static TestDefinitionException wrap(Throwable t) {
    throw new TestDefinitionException(format("Test definition is not valid: %s", t.getMessage()), t);
  }

  public static TestDefinitionException impossibleConstraint(List<Constraint> constraints) {
    throw new TestDefinitionException(format("Constraints '%s' did not become true.", constraints));
  }

  public static TestDefinitionException fsmDoesNotHaveRouteToSpecifiedState(Object destinationState, String fsmName, Object fsmModel) {
    throw new TestDefinitionException(format("No route to '%s' was found on FSM:'%s'(%s)", destinationState, fsmName, fsmModel));
  }

  public static TestDefinitionException failedToCover(String factorName, List<Object> factorLevels, Tuple tuple) {
    throw new TestDefinitionException(format("Factor '%s' doesn't have any valid level '%s' for tuple '%s'", factorName, factorLevels, tuple));
  }

  public static <T> T checkValue(T value, Predicate<T> check) {
    return checkValue(value, check, "'%s' is not valid", value);
  }

  public static <T> T checkValue(T value, Predicate<T> check, Supplier<String> messageComposer) {
    if (check.test(value))
      return value;
    throw new TestDefinitionException(messageComposer.get());
  }

  public static <T> T checkValue(T value, Predicate<T> check, String fmt, Object... args) {
    return checkValue(value, check, () -> format(fmt, args));
  }

  public static Supplier<TestDefinitionException> sutDoesNotHaveSpecifiedMethod(Class<?> klass, String name, List args) {
    return () -> {
      throw new TestDefinitionException(format("SUT '%s' does not have a method %s/%d (%s)", klass.getCanonicalName(), name, args.size(), args));
    };
  }

  public static TestDefinitionException parameterWithoutAnnotation(String methodName) {
    throw new TestDefinitionException(String.format("Method parameter not annotated with @From is found at '%s'", methodName));
  }

  public static  TestDefinitionException noParameterFound() {
    throw new TestDefinitionException("No parameter is found.");
  }
}

@@ -178,81 +178,8 @@
 ist;
-%0Aimport java.util.function.Predicate;%0Aimport java.util.function.Supplier;
 %0A%0Aim
@@ -314,17 +314,17 @@
 code Run
-w
+W
 ith(JCUn
@@ -994,1299 +994,224 @@
 on f
-smDoesNotHaveRouteToSpecifiedState(Object destinationState, String fsmName, Object fsmModel) %7B%0A    throw new TestDefinitionException(format(%22No route to '%25s' was found on FSM:'%25s'(%25s)%22, destinationState, fsmName, fsmModel));%0A  %7D%0A%0A  public static TestDefinitionException failedToCover(String factorName, List%3CObject%3E factorLevels, Tuple tuple) %7B%0A    throw new TestDefinitionException(format(%22Factor '%25s' doesn't have any valid level '%25s' for tuple '%25s'%22, factorName, factorLevels, tuple));%0A  %7D%0A%0A  public static %3CT%3E T checkValue(T value, Predicate%3CT%3E check) %7B%0A    return checkValue(value, check, %22'%25s' is not valid%22, value);%0A  %7D%0A%0A  public static %3CT%3E T checkValue(T value, Predicate%3CT%3E check, Supplier%3CString%3E messageComposer) %7B%0A    if (check.test(value))%0A      return value;%0A    throw new TestDefinitionException(messageComposer.get());%0A  %7D%0A%0A  public static %3CT%3E T checkValue(T value, Predicate%3CT%3E check, String fmt, Object... args) %7B%0A    return checkValue(value, check, () -%3E format(fmt, args));%0A  %7D%0A%0A  public static Supplier%3CTestDefinitionException%3E sutDoesNotHaveSpecifiedMethod(Class%3C?%3E klass, String name, List args) %7B%0A    return () -%3E %7B%0A      throw new TestDefinitionException(format(%22SUT '%25s' does not have a method %25s/%25d (%25s)%22, klass.getCanonicalName(), name, args.size(), args));%0A    %7D
+ailedToCover(String factorName, List%3CObject%3E factorLevels, Tuple tuple) %7B%0A    throw new TestDefinitionException(format(%22Factor '%25s' doesn't have any valid level '%25s' for tuple '%25s'%22, factorName, factorLevels, tuple))
 ;%0A  

Address warnings in TestDefinitionException.java