package tc.oc.pgm.xml.property; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; import tc.oc.commons.core.inject.KeyedManifest; import tc.oc.commons.core.reflect.ResolvableType; import tc.oc.commons.core.reflect.TypeArgument; import tc.oc.commons.core.reflect.TypeParameter; import tc.oc.commons.core.reflect.Types; import static com.google.common.base.Preconditions.checkNotNull; public class PropertyManifest<T, B extends PropertyBuilder<T, B>> extends KeyedManifest { private final TypeLiteral<T> type; private final TypeArgument<T> typeArg; private final TypeLiteral<B> builderType; private final TypeArgument<B> builderTypeArg; private final boolean defaultForType; public PropertyManifest(Class<T> type) { this(TypeLiteral.get(type)); } public PropertyManifest(Class<T> type, Class<B> builderType) { this(type, builderType, true); } public PropertyManifest(Class<T> type, Class<B> builderType, boolean defaultForType) { this(TypeLiteral.get(type), TypeLiteral.get(builderType), defaultForType); } public PropertyManifest(TypeLiteral<T> type) { this(type, (TypeLiteral<B>) new ResolvableType<PropertyBuilder<T, ?>>(){}.where(new TypeParameter<T>(){}, type)); } public PropertyManifest(TypeLiteral<T> type, TypeLiteral<B> builderType) { this(type, builderType, true); } public PropertyManifest(TypeLiteral<T> type, TypeLiteral<B> builderType, boolean defaultForType) { this.type = Types.assertFullySpecified(checkNotNull(type)); this.builderType = Types.assertFullySpecified(checkNotNull(builderType)); this.typeArg = new TypeArgument<T>(this.type){}; this.builderTypeArg = new TypeArgument<B>(this.builderType){}; this.defaultForType = defaultForType; } @Override protected Object manifestKey() { return type; } @Override protected void configure() { final TypeLiteral<PropertyBuilderFactory<T, B>> factoryType = new ResolvableType<PropertyBuilderFactory<T, B>>(){}.with(typeArg, builderTypeArg); install(new FactoryModuleBuilder().build(factoryType)); if(defaultForType) { final TypeLiteral<PropertyBuilderFactory<T, ?>> baseFactoryType = new ResolvableType<PropertyBuilderFactory<T, ?>>(){}.with(typeArg); bind(baseFactoryType).to(factoryType); } } }