Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8ac8995

Browse files
committed
Mostly working stuff except for generic controllers with base classes
1 parent 3f35d74 commit 8ac8995

17 files changed

Lines changed: 114 additions & 247 deletions

File tree

springfox-spring-web/src/main/java/springfox/documentation/spring/web/HandlerMethodReturnTypes.java

Lines changed: 0 additions & 51 deletions
This file was deleted.

springfox-spring-web/src/main/java/springfox/documentation/spring/web/readers/operation/HandlerMethodResolver.java

Lines changed: 65 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -21,206 +21,151 @@
2121

2222
import com.fasterxml.classmate.MemberResolver;
2323
import com.fasterxml.classmate.ResolvedType;
24-
import com.fasterxml.classmate.ResolvedTypeWithMembers;
2524
import com.fasterxml.classmate.TypeResolver;
2625
import com.fasterxml.classmate.members.ResolvedMethod;
2726
import com.google.common.annotations.VisibleForTesting;
27+
import com.google.common.base.Function;
28+
import com.google.common.base.Optional;
2829
import com.google.common.base.Predicate;
29-
import com.google.common.collect.Iterables;
30+
import com.google.common.collect.Lists;
3031
import com.google.common.collect.Ordering;
3132
import com.google.common.primitives.Ints;
32-
import org.slf4j.Logger;
33-
import org.slf4j.LoggerFactory;
34-
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
3533
import org.springframework.core.MethodParameter;
3634
import org.springframework.web.method.HandlerMethod;
3735
import springfox.documentation.service.ResolvedMethodParameter;
38-
import springfox.documentation.spring.web.HandlerMethodReturnTypes;
3936

4037
import java.lang.reflect.Method;
4138
import java.lang.reflect.ParameterizedType;
39+
import java.lang.reflect.Proxy;
4240
import java.lang.reflect.Type;
4341
import java.util.Comparator;
4442
import java.util.List;
4543

46-
import static com.google.common.collect.Iterables.*;
44+
import static com.google.common.base.Optional.*;
45+
import static com.google.common.collect.FluentIterable.*;
4746
import static com.google.common.collect.Lists.*;
4847

4948
public class HandlerMethodResolver {
5049

51-
private static final Logger log = LoggerFactory.getLogger(HandlerMethodResolver.class);
5250
private final TypeResolver typeResolver;
5351

5452
public HandlerMethodResolver(TypeResolver typeResolver) {
5553
this.typeResolver = typeResolver;
5654
}
5755

58-
public List<ResolvedMethodParameter> methodParameters(final HandlerMethod methodToResolve) {
59-
Class hostClass = HandlerMethodReturnTypes.useType(methodToResolve.getBeanType())
60-
.or(methodToResolve.getMethod().getDeclaringClass());
61-
ResolvedMethod resolvedMethod = getResolvedMethod(methodToResolve.getMethod(), hostClass);
62-
List<ResolvedMethodParameter> parameters = newArrayList();
63-
MethodParameter[] methodParameters = methodToResolve.getMethodParameters();
64-
if (resolvedMethod != null) {
65-
if (methodParameters.length == resolvedMethod.getArgumentCount()) {
66-
for (int index = 0; index < resolvedMethod.getArgumentCount(); index++) {
67-
MethodParameter methodParameter = methodParameters[index];
68-
methodParameter.initParameterNameDiscovery(new LocalVariableTableParameterNameDiscoverer());
69-
parameters.add(new ResolvedMethodParameter(methodParameter, resolvedMethod.getArgumentType(index)));
70-
}
71-
} else {
72-
log.warn(String.format("Problem trying to resolve a method named %s", methodToResolve.getMethod().getName()));
73-
log.warn(String.format("Method parameter count %s does not match resolved method argument count %s",
74-
methodParameters.length, resolvedMethod.getArgumentCount()));
75-
}
76-
}
77-
return parameters;
56+
public ResolvedType methodReturnType(HandlerMethod handlerMethod) {
57+
return resolvedMethod(handlerMethod).transform(toReturnType(typeResolver)).or(typeResolver.resolve(Void.TYPE));
7858
}
7959

80-
/**
81-
* Resolves the return type of the given method in the class.
82-
*
83-
* @param methodToResolve a method which is declared in the implementing class or one of its subclasses
84-
* @param actualClass the actual class. Used to resolve generic types if needed.
85-
* @return
86-
*/
87-
public ResolvedType methodReturnType(final Method methodToResolve, Class<?> actualClass) {
88-
ResolvedMethod resolvedMethod = getResolvedMethod(methodToResolve, actualClass);
89-
if (resolvedMethod != null) {
90-
return returnTypeOrVoid(resolvedMethod);
60+
public Optional<ResolvedMethod> resolvedMethod(HandlerMethod handlerMethod) {
61+
if (handlerMethod == null) {
62+
return Optional.absent();
9163
}
92-
return typeResolver.resolve(methodToResolve.getReturnType());
64+
Class hostClass = useType(handlerMethod.getBeanType())
65+
.or(handlerMethod.getMethod().getDeclaringClass());
66+
ResolvedType beanType = typeResolver.resolve(hostClass);
67+
ResolvedMethod[] memberMethods = new MemberResolver(typeResolver).resolve(beanType, null, null).getMemberMethods();
68+
return from(newArrayList(memberMethods))
69+
.filter(methodsMatches(handlerMethod.getMethod()))
70+
.first();
9371
}
9472

95-
private static Predicate<ResolvedMethod> methodNamesAreSame(final Method methodToResolve) {
96-
return new Predicate<ResolvedMethod>() {
73+
private static Function<ResolvedMethod, ResolvedType> toReturnType(final TypeResolver resolver) {
74+
return new Function<ResolvedMethod, ResolvedType>() {
9775
@Override
98-
public boolean apply(ResolvedMethod input) {
99-
return input.getRawMember().getName().equals(methodToResolve.getName());
76+
public ResolvedType apply(ResolvedMethod input) {
77+
return fromNullable(input.getReturnType()).or(resolver.resolve(Void.TYPE));
10078
}
10179
};
10280
}
10381

104-
@VisibleForTesting
105-
static Ordering<ResolvedMethod> byArgumentCount() {
106-
return Ordering.from(new Comparator<ResolvedMethod>() {
107-
@Override
108-
public int compare(ResolvedMethod first, ResolvedMethod second) {
109-
return Ints.compare(first.getArgumentCount(), second.getArgumentCount());
110-
}
111-
});
112-
}
113-
114-
private static Iterable<ResolvedMethod> methodsWithSameNumberOfParams(Iterable<ResolvedMethod> filtered,
115-
final Method methodToResolve) {
116-
117-
return filter(filtered, new Predicate<ResolvedMethod>() {
82+
private static Predicate<ResolvedMethod> methodsMatches(final Method method) {
83+
return new Predicate<ResolvedMethod>() {
11884
@Override
11985
public boolean apply(ResolvedMethod input) {
120-
return input.getArgumentCount() == methodToResolve.getParameterTypes().length;
86+
return input.getRawMember().equals(method);
12187
}
122-
});
88+
};
12389
}
12490

125-
@VisibleForTesting
126-
ResolvedMethod getResolvedMethod(final Method methodToResolve, Class<?> beanType) {
127-
ResolvedType enclosingType = typeResolver.resolve(beanType);
128-
MemberResolver resolver = new MemberResolver(typeResolver);
129-
resolver.setIncludeLangObject(false);
130-
ResolvedTypeWithMembers typeWithMembers = resolver.resolve(enclosingType, null, null);
131-
Iterable<ResolvedMethod> filtered = filter(newArrayList(typeWithMembers.getMemberMethods()),
132-
methodNamesAreSame(methodToResolve));
133-
return resolveToMethodWithMaxResolvedTypes(filtered, methodToResolve);
134-
}
13591

136-
private ResolvedMethod resolveToMethodWithMaxResolvedTypes(Iterable<ResolvedMethod> filtered,
137-
Method methodToResolve) {
138-
139-
if (Iterables.size(filtered) > 1) {
140-
Iterable<ResolvedMethod> covariantMethods = covariantMethods(filtered, methodToResolve);
141-
if (Iterables.size(covariantMethods) == 0) {
142-
return byArgumentCount().max(filtered);
143-
} else if (Iterables.size(covariantMethods) == 1) {
144-
return Iterables.getFirst(covariantMethods, null);
145-
} else {
146-
return byArgumentCount().max(covariantMethods);
147-
}
92+
public static Optional<Class> useType(Class beanType) {
93+
if (Proxy.class.isAssignableFrom(beanType)) {
94+
return Optional.absent();
95+
}
96+
if (Class.class.getName().equals(beanType.getName())) {
97+
return Optional.absent();
14898
}
149-
return Iterables.getFirst(filtered, null);
99+
return fromNullable(beanType);
150100
}
151101

152-
private Iterable<ResolvedMethod> covariantMethods(Iterable<ResolvedMethod> filtered,
153-
final Method methodToResolve) {
154-
155-
return filter(methodsWithSameNumberOfParams(filtered, methodToResolve), onlyCovariantMethods(methodToResolve));
102+
public List<ResolvedMethodParameter> methodParameters(final HandlerMethod methodToResolve) {
103+
return resolvedMethod(methodToResolve)
104+
.transform(toParameters(methodToResolve))
105+
.or(Lists.<ResolvedMethodParameter>newArrayList());
156106
}
157107

158-
private Predicate<ResolvedMethod> onlyCovariantMethods(final Method methodToResolve) {
159-
return new Predicate<ResolvedMethod>() {
108+
private Function<ResolvedMethod, List<ResolvedMethodParameter>> toParameters(final HandlerMethod methodToResolve) {
109+
return new Function<ResolvedMethod, List<ResolvedMethodParameter>>() {
160110
@Override
161-
public boolean apply(ResolvedMethod input) {
162-
for (int index = 0; index < input.getArgumentCount(); index++) {
163-
if (!covariant(input.getArgumentType(index), methodToResolve.getGenericParameterTypes()[index])) {
164-
return false;
165-
}
111+
public List<ResolvedMethodParameter> apply(ResolvedMethod input) {
112+
List<ResolvedMethodParameter> parameters = newArrayList();
113+
MethodParameter[] methodParameters = methodToResolve.getMethodParameters();
114+
for (int i = 0; i < input.getArgumentCount(); i++) {
115+
parameters.add(new ResolvedMethodParameter(methodParameters[i], input.getArgumentType(i)));
166116
}
167-
ResolvedType candidateMethodReturnValue = returnTypeOrVoid(input);
168-
return bothAreVoids(candidateMethodReturnValue, methodToResolve.getGenericReturnType())
169-
|| contravariant(candidateMethodReturnValue, methodToResolve.getGenericReturnType());
117+
return parameters;
170118
}
171119
};
172120
}
173121

174122
@VisibleForTesting
175-
boolean bothAreVoids(ResolvedType candidateMethodReturnValue, Type returnType) {
176-
return (Void.class == candidateMethodReturnValue.getErasedType()
177-
|| Void.TYPE == candidateMethodReturnValue.getErasedType())
178-
&& (Void.TYPE == returnType
179-
|| Void.class == returnType);
180-
}
181-
182-
private ResolvedType returnTypeOrVoid(ResolvedMethod input) {
183-
ResolvedType returnType = input.getReturnType();
184-
if (returnType == null) {
185-
returnType = typeResolver.resolve(Void.class);
186-
}
187-
return returnType;
123+
static Ordering<ResolvedMethod> byArgumentCount() {
124+
return Ordering.from(new Comparator<ResolvedMethod>() {
125+
@Override
126+
public int compare(ResolvedMethod first, ResolvedMethod second) {
127+
return Ints.compare(first.getArgumentCount(), second.getArgumentCount());
128+
}
129+
});
188130
}
189131

190-
boolean contravariant(ResolvedType candidateMethodReturnValue, Type returnValueOnMethod) {
191-
return isSubClass(candidateMethodReturnValue, returnValueOnMethod)
192-
|| isGenericTypeSubclass(candidateMethodReturnValue, returnValueOnMethod);
132+
@VisibleForTesting
133+
boolean bothAreVoids(ResolvedType candidateMethodReturnValue, Type returnType) {
134+
return (Void.class == candidateMethodReturnValue.getErasedType()
135+
|| Void.TYPE == candidateMethodReturnValue.getErasedType())
136+
&& (Void.TYPE == returnType
137+
|| Void.class == returnType);
193138
}
194139

195140
@VisibleForTesting
196141
boolean isGenericTypeSubclass(ResolvedType candidateMethodReturnValue, Type returnValueOnMethod) {
197142
return returnValueOnMethod instanceof ParameterizedType &&
198-
candidateMethodReturnValue.getErasedType()
199-
.isAssignableFrom((Class<?>) ((ParameterizedType) returnValueOnMethod).getRawType());
143+
candidateMethodReturnValue.getErasedType()
144+
.isAssignableFrom((Class<?>) ((ParameterizedType) returnValueOnMethod).getRawType());
200145
}
201146

202147
@VisibleForTesting
203148
boolean isSubClass(ResolvedType candidateMethodReturnValue, Type returnValueOnMethod) {
204149
return returnValueOnMethod instanceof Class
205-
&& candidateMethodReturnValue.getErasedType().isAssignableFrom((Class<?>) returnValueOnMethod);
150+
&& candidateMethodReturnValue.getErasedType().isAssignableFrom((Class<?>) returnValueOnMethod);
206151
}
207152

208153
@VisibleForTesting
209154
boolean covariant(ResolvedType candidateMethodArgument, Type argumentOnMethod) {
210155
return isSuperClass(candidateMethodArgument, argumentOnMethod)
211-
|| isGenericTypeSuperClass(candidateMethodArgument, argumentOnMethod);
156+
|| isGenericTypeSuperClass(candidateMethodArgument, argumentOnMethod);
212157
}
213158

214159
@VisibleForTesting
215160
boolean isGenericTypeSuperClass(ResolvedType candidateMethodArgument, Type argumentOnMethod) {
216161
return argumentOnMethod instanceof ParameterizedType &&
217-
((Class<?>) ((ParameterizedType) argumentOnMethod).getRawType())
218-
.isAssignableFrom(candidateMethodArgument.getErasedType());
162+
((Class<?>) ((ParameterizedType) argumentOnMethod).getRawType())
163+
.isAssignableFrom(candidateMethodArgument.getErasedType());
219164
}
220165

221166
@VisibleForTesting
222167
boolean isSuperClass(ResolvedType candidateMethodArgument, Type argumentOnMethod) {
223168
return argumentOnMethod instanceof Class
224-
&& ((Class<?>) argumentOnMethod).isAssignableFrom(candidateMethodArgument.getErasedType());
169+
&& ((Class<?>) argumentOnMethod).isAssignableFrom(candidateMethodArgument.getErasedType());
225170
}
226171
}

springfox-spring-web/src/main/java/springfox/documentation/spring/web/readers/operation/OperationModelsProvider.java

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,7 @@
3939
import java.lang.reflect.Method;
4040
import java.util.List;
4141

42-
import static springfox.documentation.schema.ResolvedTypes.resolvedTypeSignature;
43-
import static springfox.documentation.spring.web.HandlerMethodReturnTypes.*;
42+
import static springfox.documentation.schema.ResolvedTypes.*;
4443

4544
@Component
4645
@Order(Ordered.HIGHEST_PRECEDENCE)
@@ -66,7 +65,7 @@ public boolean supports(DocumentationType delimiter) {
6665
}
6766

6867
private void collectFromReturnType(RequestMappingContext context) {
69-
ResolvedType modelType = handlerReturnType(typeResolver, context.getHandlerMethod());
68+
ResolvedType modelType = new HandlerMethodResolver(typeResolver).methodReturnType(context.getHandlerMethod());
7069
modelType = context.alternateFor(modelType);
7170
LOG.debug("Adding return parameter of type {}", resolvedTypeSignature(modelType).or("<null>"));
7271
context.operationModelsBuilder().addReturn(modelType);
@@ -81,14 +80,11 @@ private void collectParameters(RequestMappingContext context) {
8180

8281
HandlerMethodResolver handlerMethodResolver = new HandlerMethodResolver(typeResolver);
8382
List<ResolvedMethodParameter> parameterTypes = handlerMethodResolver.methodParameters(handlerMethod);
84-
Annotation[][] annotations = method.getParameterAnnotations();
85-
86-
for (int i = 0; i < annotations.length; i++) {
87-
Annotation[] pAnnotations = annotations[i];
88-
for (Annotation annotation : pAnnotations) {
83+
for (ResolvedMethodParameter parameterType : parameterTypes) {
84+
Annotation[] parameterAnnotations = parameterType.getMethodParameter().getParameterAnnotations();
85+
for (Annotation annotation : parameterAnnotations) {
8986
if (annotation instanceof RequestBody || annotation instanceof RequestPart) {
90-
ResolvedMethodParameter pType = parameterTypes.get(i);
91-
ResolvedType modelType = context.alternateFor(pType.getResolvedParameterType());
87+
ResolvedType modelType = context.alternateFor(parameterType.getResolvedParameterType());
9288
LOG.debug("Adding input parameter of type {}", resolvedTypeSignature(modelType).or("<null>"));
9389
context.operationModelsBuilder().addInputParam(modelType);
9490
}

springfox-spring-web/src/main/java/springfox/documentation/spring/web/readers/operation/OperationResponseClassReader.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import springfox.documentation.spi.schema.contexts.ModelContext;
3434
import springfox.documentation.spi.service.OperationBuilderPlugin;
3535
import springfox.documentation.spi.service.contexts.OperationContext;
36-
import springfox.documentation.spring.web.HandlerMethodReturnTypes;
3736

3837
@Component
3938
@Order(Ordered.HIGHEST_PRECEDENCE)
@@ -52,7 +51,7 @@ public OperationResponseClassReader(TypeResolver typeResolver,
5251
@Override
5352
public void apply(OperationContext context) {
5453
HandlerMethod handlerMethod = context.getHandlerMethod();
55-
ResolvedType returnType = HandlerMethodReturnTypes.handlerReturnType(typeResolver, handlerMethod);
54+
ResolvedType returnType = new HandlerMethodResolver(typeResolver).methodReturnType(handlerMethod);
5655
returnType = context.alternateFor(returnType);
5756
ModelContext modelContext = ModelContext.returnValue(returnType, context.getDocumentationType(),
5857
context.getAlternateTypeProvider(), context.getDocumentationContext().getGenericsNamingStrategy());

springfox-spring-web/src/main/java/springfox/documentation/spring/web/readers/operation/ResponseMessagesReader.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
import springfox.documentation.spi.schema.contexts.ModelContext;
4040
import springfox.documentation.spi.service.OperationBuilderPlugin;
4141
import springfox.documentation.spi.service.contexts.OperationContext;
42-
import springfox.documentation.spring.web.HandlerMethodReturnTypes;
4342

4443
import java.util.List;
4544

@@ -76,7 +75,7 @@ public boolean supports(DocumentationType delimiter) {
7675

7776
private void applyReturnTypeOverride(OperationContext context) {
7877

79-
ResolvedType returnType = HandlerMethodReturnTypes.handlerReturnType(typeResolver, context.getHandlerMethod());
78+
ResolvedType returnType = new HandlerMethodResolver(typeResolver).methodReturnType(context.getHandlerMethod());
8079
returnType = context.alternateFor(returnType);
8180
int httpStatusCode = httpStatusCode(context.getHandlerMethod());
8281
String message = message(context.getHandlerMethod());

0 commit comments

Comments
 (0)