|
26 | 26 |
|
27 | 27 | import org.apache.commons.lang3.reflect.MethodUtils;
|
28 | 28 |
|
| 29 | +import com.google.common.collect.ArrayListMultimap; |
29 | 30 | import com.google.common.collect.ImmutableList;
|
30 | 31 | import com.google.common.collect.Lists;
|
31 | 32 | import com.google.common.collect.Maps;
|
| 33 | +import com.google.common.collect.Multimap; |
32 | 34 | import com.google.common.collect.Sets;
|
33 | 35 | import com.palantir.code.ts.generator.model.ImmutableServiceEndpointModel;
|
34 | 36 | import com.palantir.code.ts.generator.model.ImmutableServiceEndpointParameterModel;
|
|
46 | 48 | public final class ServiceClassParser {
|
47 | 49 | @SuppressWarnings("unchecked")
|
48 | 50 | private final static List<Class<? extends Annotation>> ANNOTATION_CLASSES = Lists.newArrayList(POST.class, GET.class, DELETE.class, PUT.class, OPTIONS.class);
|
49 |
| - |
| 51 | + |
50 | 52 | public Set<Method> getAllServiceMethods(Class<?> serviceClass) {
|
51 | 53 | Set<Method> serviceMethods = Sets.newHashSet();
|
52 | 54 | for (Class<? extends Annotation> annotation : ANNOTATION_CLASSES) {
|
@@ -74,74 +76,89 @@ public ServiceModel parseServiceClass(Class<?> serviceClass, TypescriptServiceGe
|
74 | 76 | ModelCompiler compiler = new TypeScriptGenerator(settings.getSettings()).getModelCompiler();
|
75 | 77 |
|
76 | 78 | List<ServiceEndpointModel> endpointModels = Lists.newArrayList();
|
77 |
| - for (Method method : serviceMethods) { |
78 |
| - endpointModels.add(computeEndpointModel(method, compiler, settings)); |
79 |
| - } |
| 79 | + endpointModels = computeEndpointModels(serviceMethods, compiler, settings); |
| 80 | + |
80 | 81 | Collections.sort(endpointModels);
|
81 | 82 | serviceModel.endpointModels(endpointModels);
|
82 | 83 | return serviceModel.build();
|
83 | 84 | }
|
84 | 85 |
|
85 |
| - private static ServiceEndpointModel computeEndpointModel(Method endpoint, ModelCompiler compiler, TypescriptServiceGeneratorConfiguration settings) { |
86 |
| - ImmutableServiceEndpointModel.Builder ret = ImmutableServiceEndpointModel.builder(); |
87 |
| - ret.endpointName(endpoint.getName()); |
88 |
| - ret.javaReturnType(endpoint.getGenericReturnType()); |
89 |
| - ret.tsReturnType(compiler.typeFromJavaWithReplacement(endpoint.getGenericReturnType())); |
90 |
| - ret.endpointMethodType(getMethodType(endpoint)); |
91 |
| - |
92 |
| - String annotationValue = ""; |
93 |
| - if (endpoint.getAnnotation(Path.class) != null) { |
94 |
| - annotationValue = endpoint.getAnnotation(Path.class).value(); |
| 86 | + private static List<ServiceEndpointModel> computeEndpointModels(Set<Method> endpoints, ModelCompiler compiler, TypescriptServiceGeneratorConfiguration settings) { |
| 87 | + Multimap<String, Method> endpointNameMap = ArrayListMultimap.create(); |
| 88 | + Map<Method, String> endpointNameGetter = Maps.newHashMap(); |
| 89 | + for (Method endpoint : endpoints) { |
| 90 | + endpointNameMap.put(endpoint.getName(), endpoint); |
| 91 | + endpointNameGetter.put(endpoint, endpoint.getName()); |
95 | 92 | }
|
96 |
| - ret.endpointPath(PathUtils.trimSlashes(annotationValue)); |
97 |
| - Consumes consumes = endpoint.getAnnotation(Consumes.class); |
98 |
| - if (consumes != null) { |
99 |
| - if (consumes.value().length > 1) { |
100 |
| - throw new IllegalArgumentException("Don't know how to handle an endpoint with multiple consume types"); |
| 93 | + for (String endpointName : endpointNameMap.keySet()) { |
| 94 | + List<Method> maybeDuplicates = Lists.newArrayList(endpointNameMap.get(endpointName).iterator()); |
| 95 | + if (maybeDuplicates != null && maybeDuplicates.size() > 1) { |
| 96 | + endpointNameGetter.putAll(settings.duplicateEndpointNameResolver().resolveDuplicateNames(maybeDuplicates)); |
101 | 97 | }
|
102 |
| - ret.endpointMediaType(consumes.value()[0]); |
103 | 98 | }
|
104 |
| - |
105 |
| - List<Map<Class<?>, Annotation>> annotationList = getParamterAnnotationMaps(endpoint); |
106 |
| - List<ServiceEndpointParameterModel> mandatoryParameters = Lists.newArrayList(); |
107 |
| - List<ServiceEndpointParameterModel> optionalParameters = Lists.newArrayList(); |
108 |
| - int annotationListIndex = 0; |
109 |
| - for (Type javaParameterType : endpoint.getGenericParameterTypes()) { |
110 |
| - Map<Class<?>, Annotation> annotations = annotationList.get(annotationListIndex); |
111 |
| - ImmutableServiceEndpointParameterModel.Builder parameterModel = ImmutableServiceEndpointParameterModel.builder(); |
112 |
| - |
113 |
| - // if parameter is annotated with any ignored annotations, skip it entirely |
114 |
| - if (!Collections.disjoint(annotations.keySet(), settings.ignoredAnnotations())) { |
115 |
| - annotationListIndex++; |
116 |
| - continue; |
117 |
| - } |
118 |
| - |
119 |
| - PathParam path = (PathParam) annotations.get(PathParam.class); |
120 |
| - if (path != null) { |
121 |
| - parameterModel.pathParam(path.value()); |
122 |
| - } |
123 |
| - HeaderParam header = (HeaderParam) annotations.get(HeaderParam.class); |
124 |
| - if (header != null) { |
125 |
| - parameterModel.headerParam(header.value()); |
| 99 | + List<ServiceEndpointModel> result = Lists.newArrayList(); |
| 100 | + for (Method endpoint : endpoints) { |
| 101 | + ImmutableServiceEndpointModel.Builder ret = ImmutableServiceEndpointModel.builder(); |
| 102 | + ret.endpointName(endpointNameGetter.get(endpoint)); |
| 103 | + ret.javaReturnType(endpoint.getGenericReturnType()); |
| 104 | + ret.tsReturnType(compiler.typeFromJavaWithReplacement(endpoint.getGenericReturnType())); |
| 105 | + ret.endpointMethodType(getMethodType(endpoint)); |
| 106 | + |
| 107 | + String annotationValue = ""; |
| 108 | + if (endpoint.getAnnotation(Path.class) != null) { |
| 109 | + annotationValue = endpoint.getAnnotation(Path.class).value(); |
126 | 110 | }
|
127 |
| - QueryParam query = (QueryParam) annotations.get(QueryParam.class); |
128 |
| - if (query != null) { |
129 |
| - parameterModel.queryParam(query.value()); |
| 111 | + ret.endpointPath(PathUtils.trimSlashes(annotationValue)); |
| 112 | + Consumes consumes = endpoint.getAnnotation(Consumes.class); |
| 113 | + if (consumes != null) { |
| 114 | + if (consumes.value().length > 1) { |
| 115 | + throw new IllegalArgumentException("Don't know how to handle an endpoint with multiple consume types"); |
| 116 | + } |
| 117 | + ret.endpointMediaType(consumes.value()[0]); |
130 | 118 | }
|
131 | 119 |
|
132 |
| - parameterModel.javaType(javaParameterType); |
133 |
| - TsType tsType = compiler.typeFromJavaWithReplacement(javaParameterType); |
134 |
| - parameterModel.tsType(tsType); |
135 |
| - if (tsType instanceof TsType.OptionalType || query != null) { |
136 |
| - optionalParameters.add(parameterModel.build()); |
137 |
| - } else { |
138 |
| - mandatoryParameters.add(parameterModel.build()); |
| 120 | + List<Map<Class<?>, Annotation>> annotationList = getParamterAnnotationMaps(endpoint); |
| 121 | + List<ServiceEndpointParameterModel> mandatoryParameters = Lists.newArrayList(); |
| 122 | + List<ServiceEndpointParameterModel> optionalParameters = Lists.newArrayList(); |
| 123 | + int annotationListIndex = 0; |
| 124 | + for (Type javaParameterType : endpoint.getGenericParameterTypes()) { |
| 125 | + Map<Class<?>, Annotation> annotations = annotationList.get(annotationListIndex); |
| 126 | + ImmutableServiceEndpointParameterModel.Builder parameterModel = ImmutableServiceEndpointParameterModel.builder(); |
| 127 | + |
| 128 | + // if parameter is annotated with any ignored annotations, skip it entirely |
| 129 | + if (!Collections.disjoint(annotations.keySet(), settings.ignoredAnnotations())) { |
| 130 | + annotationListIndex++; |
| 131 | + continue; |
| 132 | + } |
| 133 | + |
| 134 | + PathParam path = (PathParam) annotations.get(PathParam.class); |
| 135 | + if (path != null) { |
| 136 | + parameterModel.pathParam(path.value()); |
| 137 | + } |
| 138 | + HeaderParam header = (HeaderParam) annotations.get(HeaderParam.class); |
| 139 | + if (header != null) { |
| 140 | + parameterModel.headerParam(header.value()); |
| 141 | + } |
| 142 | + QueryParam query = (QueryParam) annotations.get(QueryParam.class); |
| 143 | + if (query != null) { |
| 144 | + parameterModel.queryParam(query.value()); |
| 145 | + } |
| 146 | + |
| 147 | + parameterModel.javaType(javaParameterType); |
| 148 | + TsType tsType = compiler.typeFromJavaWithReplacement(javaParameterType); |
| 149 | + parameterModel.tsType(tsType); |
| 150 | + if (tsType instanceof TsType.OptionalType || query != null) { |
| 151 | + optionalParameters.add(parameterModel.build()); |
| 152 | + } else { |
| 153 | + mandatoryParameters.add(parameterModel.build()); |
| 154 | + } |
| 155 | + annotationListIndex++; |
139 | 156 | }
|
140 |
| - annotationListIndex++; |
141 |
| - } |
142 | 157 |
|
143 |
| - ret.parameters(ImmutableList.<ServiceEndpointParameterModel> builder().addAll(mandatoryParameters).addAll(optionalParameters).build()); |
144 |
| - return ret.build(); |
| 158 | + ret.parameters(ImmutableList.<ServiceEndpointParameterModel> builder().addAll(mandatoryParameters).addAll(optionalParameters).build()); |
| 159 | + result.add(ret.build()); |
| 160 | + } |
| 161 | + return result; |
145 | 162 | }
|
146 | 163 |
|
147 | 164 | private static String getMethodType(Method endpoint) {
|
|
0 commit comments