Skip to content

Commit

Permalink
Merge DependencyDescription#type and DependencyDescription#genericType
Browse files Browse the repository at this point in the history
- The Type as returned by Field#getGenericType or similar has all the information given by Field#getType (and then some)
  • Loading branch information
ljacqu committed Jun 10, 2017
1 parent 53df99d commit fa2fd87
Show file tree
Hide file tree
Showing 16 changed files with 66 additions and 51 deletions.
6 changes: 3 additions & 3 deletions src/main/java/ch/jalu/injector/InjectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,10 @@ private Object[] resolveDependencies(ResolvedInstantiationContext<?> resolvedCon
Object object = resolveDependency(resolvedContext, dependency);
if (object == null) {
if (REQUEST_SCOPED_IF_HAS_DEPENDENCIES == resolvedContext.getResolutionType()
&& objects.get(dependency.getType()) == null) {
&& objects.get(dependency.getTypeAsClass()) == null) {
return null;
}
object = get(dependency.getType(), traversedClasses);
object = get(dependency.getTypeAsClass(), traversedClasses);
}
values[i] = object;
}
Expand Down Expand Up @@ -286,7 +286,7 @@ private Object resolveDependency(ResolvedInstantiationContext<?> resolvedContext
private static void validateInjectionHasNoCircularDependencies(List<? extends DependencyDescription> dependencies,
Set<Class<?>> traversedClasses) {
for (DependencyDescription dependency : dependencies) {
Class<?> clazz = dependency.getType();
Class<?> clazz = dependency.getTypeAsClass();
if (traversedClasses.contains(clazz)) {
throw new InjectorException("Found cyclic dependency - already traversed '" + clazz
+ "' (full traversal list: " + traversedClasses + ")");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ public Class<AllInstances> getAnnotationType() {
public Object resolveValueSafely(ResolvedInstantiationContext<?> context, AllInstances annotation,
DependencyDescription dependencyDescription) {
// The raw type, e.g. List or array
final Class<?> rawType = dependencyDescription.getType();
final Class<?> rawType = dependencyDescription.getTypeAsClass();
// The type of the collection, e.g. String for List<String> or String[]
final Class<?> genericType = ReflectionUtils.getCollectionType(rawType, dependencyDescription.getGenericType());
final Class<?> genericType = ReflectionUtils.getCollectionType(rawType, dependencyDescription.getType());

if (genericType == null) {
throw new InjectorException("Unsupported dependency of type '" + rawType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public Object resolveValueSafely(ResolvedInstantiationContext<?> context, AllTyp
InjectorUtils.checkNotNull(annotation.value(), "Annotation value may not be null");
Set<?> subTypes = reflections.getSubTypesOf(annotation.value());

Class<?> rawType = dependencyDescription.getType();
Class<?> rawType = dependencyDescription.getTypeAsClass();
return ReflectionUtils.toSuitableCollectionType(rawType, subTypes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class FactoryDependencyHandler implements DependencyHandler {

@Override
public Object resolveValue(ResolvedInstantiationContext<?> context, DependencyDescription dependencyDescription) {
if (dependencyDescription.getType() == Factory.class) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getGenericType());
if (Factory.class.equals(dependencyDescription.getTypeAsClass())) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getType());
if (genericType == null) {
throw new InjectorException("Factory fields must have concrete generic type. "
+ "Cannot get generic type for field in '" + context.getMappedClass() + "'");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public class SingletonStoreDependencyHandler implements DependencyHandler {

@Override
public Object resolveValue(ResolvedInstantiationContext<?> context, DependencyDescription dependencyDescription) {
if (dependencyDescription.getType() == SingletonStore.class) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getGenericType());
if (SingletonStore.class.equals(dependencyDescription.getTypeAsClass())) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getType());
if (genericType == null) {
throw new InjectorException("Singleton store fields must have concrete generic type. "
+ "Cannot get generic type for field in '" + context.getMappedClass() + "'");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,41 +1,59 @@
package ch.jalu.injector.handlers.instantiation;

import javax.annotation.Nullable;
import ch.jalu.injector.exceptions.InjectorException;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
* Describes a dependency.
*/
public class DependencyDescription {

private final Class<?> type;
private final Type genericType;
private final Type type;
private final Annotation[] annotations;

public DependencyDescription(Class<?> type, @Nullable Type genericType, Annotation... annotations) {
public DependencyDescription(Type type, Annotation... annotations) {
this.type = type;
this.genericType = genericType;
this.annotations = annotations;
}

/**
* Returns the dependency's type.
* Returns the dependency's type. In general this is the type as returned by
* {@link java.lang.reflect.Field#getGenericType()} or similar: it is a {@code Type}, which may be a
* {@link Class} for simple types or types where no generic information is provided, or it may be a
* {@link ParameterizedType} for types with generic information.
*
* Other extensions of Type are currently not supported.
* <p>
* Use {@link #getTypeAsClass()} to get the type as a Class safely.
* See {@link ch.jalu.injector.utils.ReflectionUtils} for performing further queries on the type.
*
* @return the type (class)
* @return the type
*/
public Class<?> getType() {
public Type getType() {
return type;
}

/**
* Returns the dependency's generic type if applicable.
* Returns the dependency's type as a class.
*
* @return the generic type or {@code null} if not applicable
* @return the type (as Class)
*/
@Nullable
public Type getGenericType() {
return genericType;
public Class<?> getTypeAsClass() {
if (type instanceof Class<?>) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
Type rawType = ((ParameterizedType) type).getRawType();
if (rawType instanceof Class<?>) {
return (Class<?>) rawType;
} else {
throw new InjectorException("Parameterized type '" + type + "' does not have a Class as its raw type");
}
}
throw new InjectorException("Unknown Type '" + type + "' (" + type.getClass()
+ ") cannot be converted to Class");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
* The injector's default instantiation method; injects constructor and fields.
Expand Down Expand Up @@ -69,23 +70,19 @@ public T instantiateWith(Object... values) {
}

private List<DependencyDescription> buildConstructorDependencies() {
final Class<?>[] parameters = constructor.getParameterTypes();
final Type[] genericTypes = constructor.getGenericParameterTypes();
final Type[] parameters = constructor.getGenericParameterTypes();
final Annotation[][] annotations = constructor.getParameterAnnotations();

List<DependencyDescription> dependencies = new ArrayList<>(parameters.length);
for (int i = 0; i < parameters.length; ++i) {
dependencies.add(new DependencyDescription(parameters[i], genericTypes[i], annotations[i]));
dependencies.add(new DependencyDescription(parameters[i], annotations[i]));
}
return dependencies;
}

private List<DependencyDescription> buildFieldDependencies() {
List<DependencyDescription> dependencies = new ArrayList<>(fields.size());
for (Field field : fields) {
dependencies.add(new DependencyDescription(
field.getType(), field.getGenericType(), field.getAnnotations()));
}
return dependencies;
return fields.stream()
.map(f -> new DependencyDescription(f.getGenericType(), f.getAnnotations()))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public <T> Instantiation<T> get(UnresolvedInstantiationContext<T> context) {

@Override
public Object resolveValue(ResolvedInstantiationContext<?> context, DependencyDescription dependencyDescription) {
if (dependencyDescription.getType() == Provider.class) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getGenericType());
if (Provider.class.equals(dependencyDescription.getTypeAsClass())) {
Class<?> genericType = ReflectionUtils.getGenericType(dependencyDescription.getType());
if (genericType == null) {
throw new InjectorException("Injection of a provider was requested but no generic type was given");
}
Expand Down Expand Up @@ -129,8 +129,7 @@ private final class UninitializedProviderInstantiation<T> implements ProviderWra

@Override
public List<DependencyDescription> getDependencies() {
return Collections.singletonList(
new DependencyDescription(providerClass, clazz));
return Collections.singletonList(new DependencyDescription(providerClass));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public AnnotationResolver(TestClass testClass, Object target, Class<? extends An
public Object resolveValue(ResolvedInstantiationContext<?> context,
DependencyDescription dependencyDescription) throws Exception {
for (Annotation annotation : dependencyDescription.getAnnotations()) {
Object o = resolveByAnnotation(annotation.annotationType(), dependencyDescription.getType());
Object o = resolveByAnnotation(annotation.annotationType(), dependencyDescription.getTypeAsClass());
if (o != null) {
return o;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public Object resolveValue(ResolvedInstantiationContext<?> context,
areMocksRegistered = true;
}

Class<?> type = dependencyDescription.getType();
Class<?> type = dependencyDescription.getTypeAsClass();
Object object = injector.getIfAvailable(type);
if (object != null) {
return object;
Expand Down
3 changes: 2 additions & 1 deletion src/test/java/ch/jalu/injector/TestUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.function.Predicate;

Expand Down Expand Up @@ -45,7 +46,7 @@ public void describeTo(Description description) {
};
}

public static Matcher<? super Class<?>> isClass(Class clazz) {
public static Matcher<? super Type> isClass(Class clazz) {
return equalTo(clazz);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public void shouldThrowForUnspecifiedGenerics() {
// given
ResolvedInstantiationContext<Object> context = new ResolvedInstantiationContext<>(
injector, StandardResolutionType.SINGLETON, Object.class, Object.class, null);
DependencyDescription description = new DependencyDescription(Factory.class, null, null);
DependencyDescription description = new DependencyDescription(Factory.class, null);

// expect
exceptionCatcher.expect("Factory fields must have concrete generic type.");
Expand All @@ -114,7 +114,7 @@ public void shouldReturnNullForNonFactoryType() {
// given
ResolvedInstantiationContext<Object> context = new ResolvedInstantiationContext<>(
injector, StandardResolutionType.SINGLETON, Object.class, Object.class, null);
DependencyDescription description = new DependencyDescription(Parent.class, null, null);
DependencyDescription description = new DependencyDescription(Parent.class, null);

// when
Object result = getFactoryHandler().resolveValue(context, description);
Expand All @@ -129,7 +129,7 @@ private <T> Factory<T> getFactoryForClass(Class<T> clazz) {
return (Factory<T>) factoryHandler.resolveValue(
new ResolvedInstantiationContext<>(injector, StandardResolutionType.SINGLETON,
Object.class, Object.class, null),
new DependencyDescription(Factory.class, createParameterizedType(Factory.class, clazz), null)
new DependencyDescription(createParameterizedType(Factory.class, clazz), null)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void shouldReturnRegisteredValue() {
Annotation[] annotations = {
newSizeAnnotation("value"), newDurationAnnotation()
};
DependencyDescription dependencyDescription = new DependencyDescription(null, null, annotations);
DependencyDescription dependencyDescription = new DependencyDescription( null, annotations);

// when
// Injector param not needed -> null
Expand All @@ -43,7 +43,7 @@ public void shouldReturnNullForUnregisteredAnnotation() {
Annotation[] annotations = {
newSizeAnnotation("value"), newDurationAnnotation()
};
DependencyDescription dependencyDescription = new DependencyDescription(null, null, annotations);
DependencyDescription dependencyDescription = new DependencyDescription(null, annotations);
// register some object under another annotation for the heck of it
savedAnnotationsHandler.processProvided(Test.class, new Object());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public void shouldThrowForUnspecifiedGenerics() {
// given
ResolvedInstantiationContext<BetaManager> context = new ResolvedInstantiationContext<>(
injector, StandardResolutionType.SINGLETON, BetaManager.class, BetaManager.class, null);
DependencyDescription description = new DependencyDescription(SingletonStore.class, null, null);
DependencyDescription description = new DependencyDescription(SingletonStore.class, null);

// expect
exceptionCatcher.expect("Singleton store fields must have concrete generic type.");
Expand All @@ -147,7 +147,7 @@ public void shouldReturnNullForOtherType() {
// given
ResolvedInstantiationContext<Object> context = new ResolvedInstantiationContext<>(
injector, StandardResolutionType.SINGLETON, Object.class, Object.class, null);
DependencyDescription description = new DependencyDescription(Parent.class, null, null);
DependencyDescription description = new DependencyDescription(Parent.class, null);

// when
Object result = getSingletonStoreHandler().resolveValue(context, description);
Expand All @@ -162,7 +162,7 @@ private <T> SingletonStore<T> getSingletonStoreForClass(Class<T> clazz) {
return (SingletonStore<T>) singletonStoreHandler.resolveValue(
new ResolvedInstantiationContext<>(injector, StandardResolutionType.SINGLETON,
Object.class, Object.class, null),
new DependencyDescription(SingletonStore.class, createParameterizedType(SingletonStore.class, clazz), null)
new DependencyDescription(createParameterizedType(SingletonStore.class, clazz), null)
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public void shouldInjectProviderAndCustomProviderClass() {
public void shouldThrowForMissingGeneric() {
// given
ProviderHandlerImpl providerHandler = new ProviderHandlerImpl();
DependencyDescription dependency = new DependencyDescription(Provider.class, null);
DependencyDescription dependency = new DependencyDescription(Provider.class);
Injector injector = mock(Injector.class);
ResolvedInstantiationContext context = new ResolvedInstantiationContext<>(
injector, null, Object.class, null, null);
Expand All @@ -238,7 +238,7 @@ public void shouldThrowForMissingGeneric() {
public void shouldIgnoreNonProviderDependency() {
// given
ProviderHandlerImpl providerHandler = new ProviderHandlerImpl();
DependencyDescription dependency = new DependencyDescription(Bravo.class, null);
DependencyDescription dependency = new DependencyDescription(Bravo.class);
Injector injector = mock(Injector.class);
ResolvedInstantiationContext context = new ResolvedInstantiationContext<>(
injector, null, Object.class, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void shouldProvideMock() throws Exception {
MockitoAnnotations.initMocks(runnerTest);
TestClass testClass = new TestClass(runnerTest.getClass());
MockDependencyHandler mockDependencyHandler = new MockDependencyHandler(testClass, runnerTest);
DependencyDescription dependencyDescription = new DependencyDescription(AlphaService.class, null, null);
DependencyDescription dependencyDescription = new DependencyDescription(AlphaService.class, null);
AlphaService alphaService = mock(AlphaService.class);
given(injector.getIfAvailable(AlphaService.class)).willReturn(alphaService);

Expand All @@ -62,7 +62,7 @@ public void shouldThrowForUnavailableMock() {
MockitoAnnotations.initMocks(runnerTest);
TestClass testClass = new TestClass(runnerTest.getClass());
MockDependencyHandler mockDependencyHandler = new MockDependencyHandler(testClass, runnerTest);
DependencyDescription dependencyDescription = new DependencyDescription(AlphaService.class, null, null);
DependencyDescription dependencyDescription = new DependencyDescription(AlphaService.class, null);
given(injector.getIfAvailable(AlphaService.class)).willReturn(null);

// when
Expand Down

0 comments on commit fa2fd87

Please sign in to comment.