package tc.oc.pgm.features;
import javax.annotation.Nullable;
import com.google.inject.Binder;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.binder.LinkedBindingBuilder;
import tc.oc.commons.core.reflect.ResolvableType;
import tc.oc.commons.core.reflect.TypeArgument;
import tc.oc.pgm.match.MatchModule;
import tc.oc.pgm.match.inject.MatchModuleFeatureManifest;
import tc.oc.pgm.xml.finder.NodeFinder;
/**
* Shortcuts for configuring feature {@link T}
*/
public class FeatureBinder<T extends FeatureDefinition> {
private final Binder binder;
private final TypeLiteral<T> type;
private final TypeArgument<T> typeArg;
private final Key<T> key;
protected FeatureBinder(Binder binder) {
this(binder, (TypeLiteral<T>) null);
}
public FeatureBinder(Binder binder, Class<T> type) {
this(binder, TypeLiteral.get(type));
}
public FeatureBinder(Binder binder, @Nullable TypeLiteral<T> type) {
this.binder = binder;
this.type = type != null ? type : new ResolvableType<T>(){}.in(getClass());
this.typeArg = new TypeArgument<T>(this.type){};
this.key = Key.get(this.type);
binder.install(new FeatureManifest<>(this.type));
}
/**
* Bind a specialized {@link FeatureParser} for {@link T}.
*
* Without this, {@link FeatureParser} itself will be used to parse {@link T}.
*/
public LinkedBindingBuilder<FeatureParser<T>> bindParser() {
return binder.bind(key.ofType(new ResolvableType<FeatureParser<T>>(){}.with(typeArg)));
}
/**
* Bind the {@link FeatureDefinitionParser} for {@link T}.
*
* This binding must exist for {@link T} to be parseable.
*/
public LinkedBindingBuilder<FeatureDefinitionParser<T>> bindDefinitionParser() {
return binder.bind(key.ofType(new ResolvableType<FeatureDefinitionParser<T>>(){}.with(typeArg)));
}
/**
* Configure a List of {@link T} to be parsed from the root of the document automatically,
* using the default element structure.
*
* @see RootFeatureManifest for details
*/
public void installRootParser() {
installRootParser(null);
}
/**
* Configure a List of {@link T} to be parsed from the root of the document automatically,
* using the given {@link NodeFinder}.
*
* @see RootFeatureManifest for details
*/
public void installRootParser(@Nullable NodeFinder nodeFinder) {
binder.install(new RootFeatureManifest<>(type, nodeFinder));
}
/**
* Generate a reflective parser for {@link T}.
*
* @see ReflectiveFeatureManifest
* @see tc.oc.pgm.xml.Parseable
*/
public void installReflectiveParser() {
binder.install(new ReflectiveFeatureManifest<>(type));
}
/**
* Configure the given {@link MatchModule} to load if any instances of {@link T} were parsed
*
* @see MatchModuleFeatureManifest
*/
public void installMatchModule(Class<? extends MatchModule> matchModule) {
binder.install(new MatchModuleFeatureManifest<>(TypeLiteral.get(matchModule), type));
}
}