1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.gbif.ws.client;
15
16 import java.lang.reflect.Method;
17 import java.lang.reflect.Modifier;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.LinkedHashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.commons.lang3.StringUtils;
25 import org.springframework.cloud.openfeign.AnnotatedParameterProcessor;
26 import org.springframework.cloud.openfeign.annotation.PathVariableParameterProcessor;
27 import org.springframework.cloud.openfeign.annotation.QueryMapParameterProcessor;
28 import org.springframework.cloud.openfeign.annotation.RequestHeaderParameterProcessor;
29 import org.springframework.cloud.openfeign.annotation.RequestParamParameterProcessor;
30 import org.springframework.cloud.openfeign.support.SpringMvcContract;
31 import org.springframework.web.bind.annotation.RequestMapping;
32
33 import feign.MethodMetadata;
34 import feign.Util;
35
36 import static feign.Util.checkState;
37 import static feign.Util.emptyToNull;
38 import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
39
40 public class ClientContract extends SpringMvcContract {
41
42 private ClientContract(List<AnnotatedParameterProcessor> annotatedParameterProcessors) {
43 super(annotatedParameterProcessors);
44 }
45
46 public static ClientContract withDefaultProcessors() {
47 return new ClientContract(
48 Arrays.asList(
49 new PartialDateParameterProcessor(),
50 new PathVariableParameterProcessor(),
51 new RequestParamParameterProcessor(),
52 new RequestHeaderParameterProcessor(),
53 new QueryMapParameterProcessor()));
54 }
55
56 public static ClientContract withProcessors(
57 AnnotatedParameterProcessor... annotatedParameterProcessors) {
58 return new ClientContract(Arrays.asList(annotatedParameterProcessors));
59 }
60
61 @Override
62 public List<MethodMetadata> parseAndValidateMetadata(final Class<?> targetType) {
63 checkState(
64 targetType.getTypeParameters().length == 0,
65 "Parameterized types unsupported: %s",
66 targetType.getSimpleName());
67 final Map<String, MethodMetadata> result = new LinkedHashMap<>();
68
69 for (final Method method : targetType.getMethods()) {
70 if (method.getDeclaringClass() == Object.class
71 || (method.getModifiers() & Modifier.STATIC) != 0
72 || Util.isDefault(method)
73
74
75 || method.toString().startsWith("public default")
76
77 || method.getAnnotations().length == 0) {
78 continue;
79 }
80 final MethodMetadata metadata = this.parseAndValidateMetadata(targetType, method);
81 checkState(
82 !result.containsKey(metadata.configKey()),
83 "Overrides unsupported: %s",
84 metadata.configKey());
85 result.put(metadata.configKey(), metadata);
86 }
87
88 return new ArrayList<>(result.values());
89 }
90
91 @Override
92 protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
93 RequestMapping classAnnotation = findMergedAnnotation(clz, RequestMapping.class);
94 if (classAnnotation != null) {
95
96 if (classAnnotation.value().length > 0) {
97 String pathValue = emptyToNull(classAnnotation.value()[0]);
98 data.template().uri(StringUtils.prependIfMissing(pathValue, "/"));
99 }
100 }
101 }
102 }