package org.xpect.state;
import java.lang.annotation.Annotation;
import java.util.List;
import org.eclipse.xtext.util.Pair;
import org.eclipse.xtext.util.Tuples;
import org.xpect.runner.XpectFileRunner;
import org.xpect.runner.XpectRunner;
import org.xpect.runner.XpectTestRunner;
import com.google.common.base.Preconditions;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
/**
* Similar to a Guice Module, bindings (values or factories) are added by {@link XpectRunner}, {@link XpectFileRunner}, and {@link XpectTestRunner}. It is not directly used,
* though. Instead, with this configuration, the {@link StateContainer} is created which is aware of dependencies and is able to resolve them. The state container then injects
* objects. Bindings are added by the Xpect runners, see {@link XpectRunner#createConfiguration()} for example.
*/
public class Configuration {
private final List<Class<?>> factories = Lists.newArrayList();
private final String name;
private final Multimap<Class<? extends Annotation>, Pair<Class<?>, Managed<?>>> values = LinkedHashMultimap.create();
public Configuration(String name) {
this.name = name;
}
public <T> void addDefaultValue(Class<? super T> type, Managed<T> value) {
addValue(Default.class, type, value);
}
public <T> void addDefaultValue(Class<? super T> type, T value) {
addValue(Default.class, type, value);
}
@SuppressWarnings("unchecked")
public <T> void addDefaultValue(T value) {
if (value instanceof Managed<?>)
throw new IllegalStateException("please use addDefaultValue(Class<? super T> type, Managed<T> value)");
addValue(Default.class, (Class<T>) value.getClass(), value);
}
public void addFactory(Class<?> factory) {
Preconditions.checkNotNull(factory);
factories.add(factory);
}
public <T> void addValue(Class<? extends Annotation> annotation, Class<? super T> type, Managed<T> value) {
if (annotation.getAnnotation(XpectStateAnnotation.class) == null)
throw new IllegalStateException("@" + annotation.getName() + " must be annotated with @" + XpectStateAnnotation.class.getSimpleName());
values.put(annotation, Tuples.<Class<?>, Managed<?>> create(type, value));
}
public <T> void addValue(Class<? extends Annotation> annotation, Class<? super T> type, T value) {
addValue(annotation, type, new ManagedImpl<T>(value));
}
@SuppressWarnings("unchecked")
public <T> void addValue(Class<? extends Annotation> annotation, T value) {
if (value instanceof Managed<?>)
throw new IllegalStateException("please use addValue(Class<? extends Annotation> annotation, Class<? super T> type, Managed<T> value)");
addValue(annotation, (Class<T>) value.getClass(), value);
}
public List<Class<?>> getFactories() {
return factories;
}
public String getName() {
return name;
}
public Multimap<Class<? extends Annotation>, Pair<Class<?>, Managed<?>>> getValues() {
return values;
}
}