Skip to content

Commit b8fab67

Browse files
committed
#194 generics support for annotated helpers
Adds a dependency to `spring-generics`, and uses it to resolve the generics of method parameters in introspected helper classes. With this change, it is also possible to do away with the clunky @blockchain generics handling, where the user had to provide the generic type of the `AtomicReference` class. The Spring tools are able to handle this, and so the annotation parameter has been removed. (BREAKING CHANGE)
1 parent 20c41c2 commit b8fab67

5 files changed

Lines changed: 38 additions & 11 deletions

File tree

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@
210210
<artifactId>codemodel</artifactId>
211211
<version>1.0.2</version>
212212
</dependency>
213+
<dependency>
214+
<groupId>com.unquietcode.tools.spring</groupId>
215+
<artifactId>spring-generics</artifactId>
216+
<version>4.1.4</version>
217+
</dependency>
213218
<dependency>
214219
<groupId>com.google.guava</groupId>
215220
<artifactId>guava</artifactId>

src/main/java/unquietcode/tools/flapi/IntrospectorSupport.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package unquietcode.tools.flapi;
1818

1919
import unquietcode.tools.flapi.annotations.BlockChain;
20+
import unquietcode.tools.spring.generics.MethodParameter;
21+
import unquietcode.tools.spring.generics.ResolvableType;
2022

2123
import java.lang.annotation.Annotation;
2224
import java.lang.reflect.Method;
@@ -89,7 +91,27 @@ else if (parameterType.isArray()) {
8991
typeName = parameterType.getName();
9092
}
9193

92-
signature.append(typeName).append(" p").append(i);
94+
// raw type
95+
signature.append(typeName);
96+
97+
// generics
98+
Class<?>[] generics = ResolvableType.forMethodParameter(MethodParameter.forMethodOrConstructor(method, i)).resolveGenerics();
99+
100+
if (generics != null && generics.length > 0) {
101+
signature.append("<");
102+
103+
for (int p = 0; p < generics.length; ++p) {
104+
if (p != 0) { signature.append(", "); }
105+
106+
Class<?> generic = generics[p];
107+
signature.append(generic.getName());
108+
}
109+
110+
signature.append("> ");
111+
}
112+
113+
// parameter name
114+
signature.append(" p").append(i);
93115
}
94116

95117
signature.append(")");

src/main/java/unquietcode/tools/flapi/annotations/AnnotationIntrospector.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import unquietcode.tools.flapi.outline.DescriptorOutline;
3030
import unquietcode.tools.flapi.outline.MethodOutline;
3131
import unquietcode.tools.flapi.runtime.SpringMethodUtils;
32+
import unquietcode.tools.spring.generics.MethodParameter;
33+
import unquietcode.tools.spring.generics.ResolvableType;
3234

3335
import java.lang.annotation.Annotation;
3436
import java.lang.reflect.AnnotatedElement;
@@ -242,7 +244,11 @@ private void handleMethod(MethodOutline methodOutline, Method method) {
242244
throw new DescriptorBuilderException("@BlockChain parameters must be of type AtomicReference");
243245
}
244246

245-
BlockOutline blockOutline = handleClass(blockChain.value());
247+
// get the generic type of the reference
248+
Class<?> generic = ResolvableType.forMethodParameter(MethodParameter.forMethodOrConstructor(method, i)).resolveGeneric();
249+
250+
// handle the reference type
251+
BlockOutline blockOutline = handleClass(generic);
246252
methodOutline.getBlockChain().add(blockOutline);
247253
methodOutline.getChainParameterPositions().add(i);
248254
}

src/main/java/unquietcode/tools/flapi/annotations/BlockChain.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,12 @@
2424
/**
2525
* Specifies a method parameter that is to be used for building
2626
* a block chain around the method. The parameter must be of
27-
* type {@link java.util.concurrent.atomic.AtomicReference},
28-
* and the provided {@link #value()} class must match the
29-
* generic type of the reference object. A mismatch will not
30-
* be discovered until runtime, at which point you will receive
31-
* a ClassCastException.
27+
* type {@link java.util.concurrent.atomic.AtomicReference}.
3228
*
3329
* @author Ben Fagin
3430
* @version 2014-08-03
3531
*/
3632
@FlapiAnnotation
3733
@Target(ElementType.PARAMETER)
3834
@Retention(RetentionPolicy.RUNTIME)
39-
public @interface BlockChain {
40-
Class<?> value();
41-
}
35+
public @interface BlockChain { }

src/test/java/unquietcode/tools/flapi/examples/calculator/Calculator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@
1919
public interface Calculator {
2020

2121
@Last
22-
void $(int startingValue, @BlockChain(Calculation.class) AtomicReference<Calculation> helper);
22+
void $(int startingValue, @BlockChain AtomicReference<Calculation> helper);
2323
}

0 commit comments

Comments
 (0)