package org.junit.runners.model;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Runner;

/**
 * A RunnerBuilder is a strategy for constructing runners for classes. 
 * 
 * Only writers of custom runners should use <code>RunnerBuilder</code>s.  A custom runner class with a constructor taking
 * a <code>RunnerBuilder</code> parameter will be passed the instance of <code>RunnerBuilder</code> used to build that runner itself.  
 * For example,
 * imagine a custom runner that builds suites based on a list of classes in a text file:
 * 
 * <pre>
 * \@RunWith(TextFileSuite.class)
 * \@SuiteSpecFile("mysuite.txt")
 * class MySuite {}
 * </pre>
 * 
 * The implementation of TextFileSuite might include:
 * 
 * <pre>
 * public TextFileSuite(Class testClass, RunnerBuilder builder) {
 *   // ...
 *   for (String className : readClassNames())
 *     addRunner(builder.runnerForClass(Class.forName(className)));
 *   // ...
 * }
 * </pre>
 * 
 * @see org.junit.runners.Suite
 */
public abstract class RunnerBuilder {
	private final Set<Class<?>> parents= new HashSet<Class<?>>();

	/**
	 * Override to calculate the correct runner for a test class at runtime.
	 * 
	 * @param testClass class to be run
	 * @return a Runner
	 * @throws Throwable if a runner cannot be constructed
	 */
	public abstract Runner runnerForClass(Class<?> testClass) throws Throwable;

	/**
	 * Always returns a runner, even if it is just one that prints an error instead of running tests.
	 * @param testClass class to be run
	 * @return a Runner
	 */
	public Runner safeRunnerForClass(Class<?> testClass) {
		try {
			return runnerForClass(testClass);
		} catch (Throwable e) {
			return new ErrorReportingRunner(testClass, e);
		}
	}

	Class<?> addParent(Class<?> parent) throws InitializationError {
		if (!parents.add(parent))
			throw new InitializationError(String.format("class '%s' (possibly indirectly) contains itself as a SuiteClass", parent.getName()));
		return parent;
	}

	void removeParent(Class<?> klass) {
		parents.remove(klass);
	}

	/**
	 * Constructs and returns a list of Runners, one for each child class in
	 * {@code children}.  Care is taken to avoid infinite recursion:
	 * this builder will throw an exception if it is requested for another
	 * runner for {@code parent} before this call completes.
	 */
	public List<Runner> runners(Class<?> parent, Class<?>[] children)
			throws InitializationError {
		addParent(parent);

		try {
			return runners(children);
		} finally {
			removeParent(parent);
		}
	}
	
	public List<Runner> runners(Class<?> parent, List<Class<?>> children)
			throws InitializationError {
		return runners(parent, children.toArray(new Class<?>[0]));
	}
	
	private List<Runner> runners(Class<?>[] children) {
		ArrayList<Runner> runners= new ArrayList<Runner>();
		for (Class<?> each : children) {
			Runner childRunner= safeRunnerForClass(each);
			if (childRunner != null)
				runners.add(childRunner);
		}
		return runners;
	}
}
