Browse Source

Use method signatures for factory

master
Paweł Płazieński 5 months ago
parent
commit
0b896633ae
  1. 2
      pom.xml
  2. 27
      src/main/java/org/perfectable/injection/Configuration.java
  3. 34
      src/main/java/org/perfectable/injection/registration/ArgumentsResolution.java
  4. 29
      src/main/java/org/perfectable/injection/registration/Factory.java
  5. 10
      src/main/java/org/perfectable/injection/registration/Injection.java
  6. 114
      src/main/java/org/perfectable/injection/registration/Instantiation.java
  7. 26
      src/main/java/org/perfectable/injection/registration/Registration.java
  8. 49
      src/main/java/org/perfectable/injection/registration/StandardRegistration.java

2
pom.xml

@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
</scm>
<properties>
<version.introspectable>4.1.0</version.introspectable>
<version.introspectable>5.0.0-SNAPSHOT</version.introspectable>
<version.testable>1.7.0</version.testable>
</properties>

27
src/main/java/org/perfectable/injection/Configuration.java

@ -1,14 +1,13 @@ @@ -1,14 +1,13 @@
package org.perfectable.injection;
import org.perfectable.injection.registration.Factory;
import org.perfectable.injection.registration.FunctionalProvider;
import org.perfectable.injection.registration.Registration;
import org.perfectable.injection.registration.Retriever;
import org.perfectable.injection.replacement.Replacement;
import org.perfectable.injection.scope.Scope;
import org.perfectable.introspection.proxy.Signatures;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.inject.Provider;
import org.checkerframework.checker.nullness.qual.NonNull;
@ -41,34 +40,16 @@ public interface Configuration { @@ -41,34 +40,16 @@ public interface Configuration {
register(Registration.external(retriever));
}
default <P extends @NonNull Object, F extends @NonNull Object>
void registerFactory(Factory.Single.Functional<P, F> factory) {
default <P extends @NonNull Object, F1 extends @NonNull Object>
void registerFactory(Signatures.Function1<P, F1, ?> factory) {
register(Registration.factory(factory));
}
default <P extends @NonNull Object, F extends @NonNull Object>
void registerFactory(Class<P> productType, Factory.Single<P, F> factory,
Class<F> factoryArgumentClass, Set<? extends Annotation> argumentQualifiers) {
register(Registration.factory(productType, factory, factoryArgumentClass, argumentQualifiers));
}
default <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
void registerFactory(Factory.Double.Functional<P, F1, F2> factory) {
void registerFactory(Signatures.Function2<P, F1, F2, ?> factory) {
register(Registration.factory(factory));
}
@SuppressWarnings("ParameterNumber")
default <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
void registerFactory(Class<P> productType,
Factory.Double<P, F1, F2> factory,
Class<F1> firstArgumentType,
Set<? extends Annotation> firstArgumentQualifiers,
Class<F2> secondArgumentType,
Set<? extends Annotation> secondArgumentQualifiers) {
register(Registration.factory(productType, factory, firstArgumentType, firstArgumentQualifiers,
secondArgumentType, secondArgumentQualifiers));
}
void addScope(Class<? extends Annotation> annotation, Scope scope);
void addReplacement(Replacement replacement);

34
src/main/java/org/perfectable/injection/registration/ArgumentResolution.java → src/main/java/org/perfectable/injection/registration/ArgumentsResolution.java

@ -8,36 +8,16 @@ import java.lang.annotation.Annotation; @@ -8,36 +8,16 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Executable;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.Iterator;
import java.util.Set;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.Immutable;
import org.checkerframework.checker.nullness.qual.NonNull;
import static com.google.common.base.Preconditions.checkArgument;
@Immutable
final class ArgumentResolution {
static final ArgumentResolution EMPTY = new ArgumentResolution(ImmutableList.of());
static ArgumentResolution of(ImmutableList<Class<? extends @NonNull Object>> argumentClasses,
ImmutableList<? extends Set<? extends Annotation>> argumentQualifiers) {
ImmutableList.Builder<Fetchable<?>> fetchablesBuilder = ImmutableList.builder();
checkArgument(argumentClasses.size() == argumentQualifiers.size());
Iterator<Class<? extends @NonNull Object>> classIterator = argumentClasses.iterator();
Iterator<? extends Set<? extends Annotation>> qualifierIterator = argumentQualifiers.iterator();
while (classIterator.hasNext()) {
Class<? extends @NonNull Object> argumentClass = classIterator.next();
Set<? extends Annotation> qualifiers = qualifierIterator.next();
Fetchable<?> fetchable = Fetchable.createRaw(argumentClass, ImmutableSet.copyOf(qualifiers));
fetchablesBuilder.add(fetchable);
}
return new ArgumentResolution(fetchablesBuilder.build());
}
final class ArgumentsResolution {
static final ArgumentsResolution EMPTY = new ArgumentsResolution(ImmutableList.of());
public static ArgumentResolution of(FunctionalReference reference) {
public static ArgumentsResolution of(FunctionalReference reference) {
FunctionalReference.Introspection introspection = reference.introspect();
ImmutableList.Builder<Fetchable<?>> fetchablesBuilder = ImmutableList.builder();
for (int i = 0; i < introspection.parametersCount(); i++) {
@ -47,11 +27,11 @@ final class ArgumentResolution { @@ -47,11 +27,11 @@ final class ArgumentResolution {
Fetchable<?> fetchable = Fetchable.create(view, qualifiers);
fetchablesBuilder.add(fetchable);
}
return new ArgumentResolution(fetchablesBuilder.build());
return new ArgumentsResolution(fetchablesBuilder.build());
}
static ArgumentResolution of(Class<?> declaringClass, Executable executable) {
static ArgumentsResolution of(Class<?> declaringClass, Executable executable) {
ImmutableList.Builder<Fetchable<?>> fetchablesBuilder = ImmutableList.builder();
for (Parameter parameter : executable.getParameters()) {
ImmutableSet<Annotation> qualifiers = Annotations.extractQualifiers(parameter);
@ -59,12 +39,12 @@ final class ArgumentResolution { @@ -59,12 +39,12 @@ final class ArgumentResolution {
Fetchable<?> fetchable = Fetchable.create(view, qualifiers);
fetchablesBuilder.add(fetchable);
}
return new ArgumentResolution(fetchablesBuilder.build());
return new ArgumentsResolution(fetchablesBuilder.build());
}
private final ImmutableList<Fetchable<?>> fetchables;
private ArgumentResolution(ImmutableList<Fetchable<?>> fetchables) {
private ArgumentsResolution(ImmutableList<Fetchable<?>> fetchables) {
this.fetchables = fetchables;
}

29
src/main/java/org/perfectable/injection/registration/Factory.java

@ -1,29 +0,0 @@ @@ -1,29 +0,0 @@
package org.perfectable.injection.registration;
import org.perfectable.introspection.FunctionalReference;
public final class Factory { // SUPPRESS MissingStaticMethodInNonInstantiatableClass
@FunctionalInterface
public interface Single<P, F> {
P produce(F base);
interface Functional<P, F> extends Single<P, F>, FunctionalReference {
// uses method from Factory
}
}
@SuppressWarnings("JavaLangClash")
@FunctionalInterface
public interface Double<P, F1, F2> {
P produce(F1 first, F2 second);
interface Functional<P, F1, F2> extends Double<P, F1, F2>, FunctionalReference {
// uses method from Factory
}
}
private Factory() {
// container
}
}

10
src/main/java/org/perfectable/injection/registration/Injection.java

@ -134,17 +134,17 @@ abstract class Injection { @@ -134,17 +134,17 @@ abstract class Injection {
}
static OfMethod create(Class<?> declaringClass, Method method) {
ArgumentResolution arguments = ArgumentResolution.of(declaringClass, method);
ArgumentsResolution arguments = ArgumentsResolution.of(declaringClass, method);
return new OfMethod(method, arguments);
}
@SuppressWarnings("Immutable")
private final Method method;
private final ArgumentResolution argumentResolution;
private final ArgumentsResolution argumentsResolution;
private OfMethod(Method method, ArgumentResolution argumentResolution) {
private OfMethod(Method method, ArgumentsResolution argumentsResolution) {
this.method = method;
this.argumentResolution = argumentResolution;
this.argumentsResolution = argumentsResolution;
}
@Override
@ -160,7 +160,7 @@ abstract class Injection { @@ -160,7 +160,7 @@ abstract class Injection {
@SuppressWarnings({"AvoidThrowingRawExceptionTypes", "ThrowSpecificExceptions"})
@Override
public void perform(Object targetObject, Fetchable.Fetcher fetcher) {
Object[] arguments = argumentResolution.prepare(fetcher);
Object[] arguments = argumentsResolution.prepare(fetcher);
try {
method.invoke(targetObject, arguments);
}

114
src/main/java/org/perfectable/injection/registration/Instantiation.java

@ -1,13 +1,14 @@ @@ -1,13 +1,14 @@
package org.perfectable.injection.registration;
import java.lang.annotation.Annotation;
import org.perfectable.introspection.FunctionalReference;
import org.perfectable.introspection.proxy.Invocation;
import org.perfectable.introspection.proxy.Signatures;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
import com.google.common.collect.ImmutableList;
import org.checkerframework.checker.nullness.qual.NonNull;
import static com.google.common.base.Preconditions.checkArgument;
@ -16,60 +17,32 @@ import static org.perfectable.introspection.Introspections.introspect; @@ -16,60 +17,32 @@ import static org.perfectable.introspection.Introspections.introspect;
abstract class Instantiation<T extends @NonNull Object> {
static <T extends @NonNull Object> Instantiation<T> forClass(Class<T> createdClass) {
Constructor<T> constructor = findInjectableConstructor(createdClass);
ArgumentResolution argumentResolution = ArgumentResolution.of(createdClass, constructor);
return new UsingConstructor<>(constructor, argumentResolution);
}
static <P extends @NonNull Object> Instantiation<P> forFactory(Factory.Single.Functional<? extends P, ?> factory) {
ArgumentResolution argumentResolution = ArgumentResolution.of(factory);
return new UsingFactorySingle<>(factory, argumentResolution);
}
static <P extends @NonNull Object, F1 extends @NonNull Object>
Instantiation<P> forFactory(Factory.Single<? extends P, F1> factory,
Class<F1> argumentClass, Set<? extends Annotation> argumentQualifiers) {
ImmutableList<Class<? extends @NonNull Object>> argumentsClasses = ImmutableList.of(argumentClass);
ImmutableList<? extends Set<? extends Annotation>> argumentsQualifiers = ImmutableList.of(argumentQualifiers);
ArgumentResolution argumentResolution = ArgumentResolution.of(argumentsClasses, argumentsQualifiers);
return new UsingFactorySingle<>(factory, argumentResolution);
}
static <P extends @NonNull Object> Instantiation<P> forFactory(
Factory.Double.Functional<? extends P, ?, ?> factory) {
ArgumentResolution argumentResolution = ArgumentResolution.of(factory);
return new UsingFactoryDouble<>(factory, argumentResolution);
ArgumentsResolution argumentsResolution = ArgumentsResolution.of(createdClass, constructor);
return new UsingConstructor<>(constructor, argumentsResolution);
}
static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
Instantiation<P> forFactory(Factory.Double<? extends P, F1, F2> factory,
Class<F1> argument1Class,
Set<? extends Annotation> argument1Qualifiers,
Class<F2> argument2Class,
Set<? extends Annotation> argument2Qualifiers) {
ImmutableList<Class<? extends @NonNull Object>> argumentsClasses =
ImmutableList.of(argument1Class, argument2Class);
ImmutableList<? extends Set<? extends Annotation>> argumentsQualifiers =
ImmutableList.of(argument1Qualifiers, argument2Qualifiers);
ArgumentResolution argumentResolution = ArgumentResolution.of(argumentsClasses, argumentsQualifiers);
return new UsingFactoryDouble<>(factory, argumentResolution);
static <P extends @NonNull Object, F extends Signatures.InvocationConvertible<P, ?> & FunctionalReference>
Instantiation<P> forFactory(F factory) {
ArgumentsResolution argumentsResolution = ArgumentsResolution.of(factory);
return new UsingInvocationConvertible<>(factory, argumentsResolution);
}
static <T extends @NonNull Object> Instantiation<T> forProvider(Provider<? extends T> provider) {
ArgumentResolution argumentResolution = ArgumentResolution.EMPTY;
return new UsingProvider<>(provider, argumentResolution);
ArgumentsResolution argumentsResolution = ArgumentsResolution.EMPTY;
return new UsingProvider<>(provider, argumentsResolution);
}
abstract T construct(Object... arguments);
T instantiate(Fetchable.Fetcher fetcher) {
Object[] arguments = argumentResolution.prepare(fetcher);
Object[] arguments = argumentsResolution.prepare(fetcher);
return construct(arguments);
}
private final ArgumentResolution argumentResolution;
private final ArgumentsResolution argumentsResolution;
private Instantiation(ArgumentResolution argumentResolution) {
this.argumentResolution = argumentResolution;
private Instantiation(ArgumentsResolution argumentsResolution) {
this.argumentsResolution = argumentsResolution;
}
private static <T> Constructor<T> findInjectableConstructor(Class<T> targetClass) {
@ -84,8 +57,8 @@ abstract class Instantiation<T extends @NonNull Object> { @@ -84,8 +57,8 @@ abstract class Instantiation<T extends @NonNull Object> {
private static final class UsingConstructor<T extends @NonNull Object> extends Instantiation<T> {
private final Constructor<? extends T> constructor;
UsingConstructor(Constructor<? extends T> constructor, ArgumentResolution argumentResolution) {
super(argumentResolution);
UsingConstructor(Constructor<? extends T> constructor, ArgumentsResolution argumentsResolution) {
super(argumentsResolution);
this.constructor = constructor;
}
@ -104,8 +77,8 @@ abstract class Instantiation<T extends @NonNull Object> { @@ -104,8 +77,8 @@ abstract class Instantiation<T extends @NonNull Object> {
private static final class UsingProvider<T extends @NonNull Object> extends Instantiation<T> {
private final Provider<? extends T> provider;
UsingProvider(Provider<? extends T> provider, ArgumentResolution argumentResolution) {
super(argumentResolution);
UsingProvider(Provider<? extends T> provider, ArgumentsResolution argumentsResolution) {
super(argumentsResolution);
this.provider = provider;
}
@ -116,42 +89,29 @@ abstract class Instantiation<T extends @NonNull Object> { @@ -116,42 +89,29 @@ abstract class Instantiation<T extends @NonNull Object> {
}
}
private static final class UsingFactorySingle<P extends @NonNull Object, F>
extends Instantiation<P> {
private final Factory.Single<? extends P, ? super F> factory;
private static final class UsingInvocationConvertible<P extends @NonNull Object>
extends Instantiation<P> {
private final Signatures.InvocationConvertible<P, ?> factory;
UsingFactorySingle(Factory.Single<? extends P, ? super F> factory, ArgumentResolution argumentResolution) {
super(argumentResolution);
UsingInvocationConvertible(Signatures.InvocationConvertible<P, ?> factory,
ArgumentsResolution argumentsResolution) {
super(argumentsResolution);
this.factory = factory;
}
@SuppressWarnings("unchecked")
@SuppressWarnings({"unchecked", "IllegalCatch"})
@Override
P construct(Object... arguments) {
checkArgument(arguments.length == 1);
@NonNull F base = (@NonNull F) arguments[0];
return factory.produce(base);
}
}
private static final class UsingFactoryDouble<P extends @NonNull Object, F1, F2> extends Instantiation<P> {
private final Factory.Double<? extends P, ? super F1, ? super F2> factory;
UsingFactoryDouble(Factory.Double<? extends P, ? super F1, ? super F2> factory,
ArgumentResolution argumentResolution) {
super(argumentResolution);
this.factory = factory;
}
@Override
@SuppressWarnings("unchecked")
P construct(Object... arguments) {
checkArgument(arguments.length == 2);
@NonNull F1 first = (@NonNull F1) arguments[0];
@NonNull F2 second = (@NonNull F2) arguments[1];
return factory.produce(first, second);
Invocation<P, ?> invocation = factory.toInvocation(arguments);
try {
return invocation.invoke();
}
catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

26
src/main/java/org/perfectable/injection/registration/Registration.java

@ -4,9 +4,9 @@ import org.perfectable.injection.Registry; @@ -4,9 +4,9 @@ import org.perfectable.injection.Registry;
import org.perfectable.injection.replacement.Replacement;
import org.perfectable.injection.scope.ScopeSelector;
import org.perfectable.introspection.AnnotationBuilder;
import org.perfectable.introspection.proxy.Signatures;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.inject.Named;
import javax.inject.Provider;
@ -37,34 +37,16 @@ public interface Registration { @@ -37,34 +37,16 @@ public interface Registration {
return ExternalRegistration.create(retriever);
}
static <P extends @NonNull Object, F extends @NonNull Object>
Registration factory(Factory.Single.Functional<P, F> factory) {
static <P extends @NonNull Object, F1 extends @NonNull Object>
Registration factory(Signatures.Function1<P, F1, ?> factory) {
return StandardRegistration.forFactory(factory);
}
static <P extends @NonNull Object, F extends @NonNull Object>
Registration factory(Class<P> productType, Factory.Single<P, F> factory,
Class<F> factoryArgumentClass, Set<? extends Annotation> argumentQualifiers) {
return StandardRegistration.forFactory(productType, factory, factoryArgumentClass, argumentQualifiers);
}
static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
Registration factory(Factory.Double.Functional<P, F1, F2> factory) {
Registration factory(Signatures.Function2<P, F1, F2, ?> factory) {
return StandardRegistration.forFactory(factory);
}
@SuppressWarnings("ParameterNumber")
static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
Registration factory(Class<P> productType,
Factory.Double<P, F1, F2> factory,
Class<F1> firstArgumentClass,
Set<? extends Annotation> firstArgumentQualifiers,
Class<F2> secondArgumentClass,
Set<? extends Annotation> secondArgumentQualifiers) {
return StandardRegistration.forFactory(productType, factory, firstArgumentClass, firstArgumentQualifiers,
secondArgumentClass, secondArgumentQualifiers);
}
default Registration with(Annotation annotation) {
if (annotation.annotationType().isAnnotationPresent(javax.inject.Qualifier.class)) {
return QualifiedRegistration.create(this, annotation);

49
src/main/java/org/perfectable/injection/registration/StandardRegistration.java

@ -6,9 +6,9 @@ import org.perfectable.injection.replacement.Replacement; @@ -6,9 +6,9 @@ import org.perfectable.injection.replacement.Replacement;
import org.perfectable.injection.scope.Scope;
import org.perfectable.injection.scope.ScopeSelector;
import org.perfectable.introspection.FunctionalReference;
import org.perfectable.introspection.proxy.Signatures;
import java.lang.annotation.Annotation;
import java.util.Set;
import javax.inject.Provider;
import com.google.common.collect.ImmutableSet;
@ -31,39 +31,28 @@ public final class StandardRegistration<T extends @NonNull Object> implements Re @@ -31,39 +31,28 @@ public final class StandardRegistration<T extends @NonNull Object> implements Re
FunctionalReference.Introspection introspection = provider.introspect();
@SuppressWarnings("unchecked")
Class<T> createdClass = (Class<T>) introspection.resultType();
Instantiation<T> instantiation = Instantiation.forProvider(provider);
return new StandardRegistration<>(createdClass, instantiation);
return forProvider(createdClass, provider);
}
public static <T extends @NonNull Object> StandardRegistration<T> forProvider(Class<T> createdClass,
Provider<T> provider) {
Provider<T> provider) {
Instantiation<T> initializator = Instantiation.forProvider(provider);
return new StandardRegistration<>(createdClass, initializator);
}
public static <P extends @NonNull Object, F extends @NonNull Object>
StandardRegistration<P> forFactory(Factory.Single.Functional<P, F> factory) {
requireNonNull(factory);
FunctionalReference.Introspection introspection = factory.introspect();
@SuppressWarnings("unchecked")
Class<P> createdClass = (Class<P>) introspection.resultType();
Instantiation<P> initializator = Instantiation.forFactory(factory);
return new StandardRegistration<>(createdClass, initializator);
public static <P extends @NonNull Object, F1 extends @NonNull Object>
StandardRegistration<P> forFactory(Signatures.Function1<P, F1, ?> factory) {
return forFactoryInternal(factory);
}
public static <P extends @NonNull Object, F extends @NonNull Object>
StandardRegistration<P> forFactory(Class<P> productType,
Factory.Single<P, F> factory,
Class<F> argumentClass,
Set<? extends Annotation> argumentQualifiers) {
requireNonNull(factory);
Instantiation<P> initializator = Instantiation.forFactory(factory, argumentClass, argumentQualifiers);
return new StandardRegistration<>(productType, initializator);
public static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
StandardRegistration<P> forFactory(Signatures.Function2<P, F1, F2, ?> factory) {
return forFactoryInternal(factory);
}
public static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
StandardRegistration<P> forFactory(Factory.Double.Functional<P, F1, F2> factory) {
@SuppressWarnings("PMD.UnusedPrivateMethod") // false positive
private static <P extends @NonNull Object, F extends Signatures.InvocationConvertible<P, ?> & FunctionalReference>
StandardRegistration<P> forFactoryInternal(F factory) {
requireNonNull(factory);
FunctionalReference.Introspection introspection = factory.introspect();
@SuppressWarnings("unchecked")
@ -72,20 +61,6 @@ public final class StandardRegistration<T extends @NonNull Object> implements Re @@ -72,20 +61,6 @@ public final class StandardRegistration<T extends @NonNull Object> implements Re
return new StandardRegistration<>(createdClass, initializator);
}
@SuppressWarnings("ParameterNumber")
public static <P extends @NonNull Object, F1 extends @NonNull Object, F2 extends @NonNull Object>
StandardRegistration<P> forFactory(Class<P> productType,
Factory.Double<P, F1, F2> factory,
Class<F1> firstArgumentClass,
Set<? extends Annotation> firstArgumentQualifiers,
Class<F2> secondArgumentClass,
Set<? extends Annotation> secondArgumentQualifiers) {
requireNonNull(factory);
Instantiation<P> initializator = Instantiation.forFactory(factory, firstArgumentClass,
firstArgumentQualifiers, secondArgumentClass, secondArgumentQualifiers);
return new StandardRegistration<>(productType, initializator);
}
private StandardRegistration(Class<T> createdClass, Instantiation<T> instantiation) {
this.createdClass = createdClass;
this.instantiation = instantiation;

Loading…
Cancel
Save