|
10 | 10 | import java.util.Arrays;
|
11 | 11 | import java.util.List;
|
12 | 12 | import java.util.Map;
|
| 13 | +import java.util.Objects; |
13 | 14 | import java.util.Set;
|
| 15 | +import java.util.function.Supplier; |
14 | 16 |
|
15 | 17 |
|
16 | 18 | public class Swagger {
|
17 | 19 |
|
18 |
| - static SwaggerOperation parseSwaggerAnnotations(Method method) { |
| 20 | + public static SwaggerOperation parseSwaggerAnnotations(Method method) { |
| 21 | + return firstResult( |
| 22 | + () -> parseSwaggerAnnotations3(method), |
| 23 | + () -> parseSwaggerAnnotations1(method), |
| 24 | + new SwaggerOperation()); |
| 25 | + } |
| 26 | + |
| 27 | + private static SwaggerOperation parseSwaggerAnnotations1(Method method) { |
| 28 | + final Annotation apiOperation = Utils.getAnnotation(method, "io.swagger.annotations.ApiOperation"); |
| 29 | + final Annotation[] apiResponses = Utils.getAnnotationElementValue(method, "io.swagger.annotations.ApiResponses", "value", Annotation[].class); |
| 30 | + if (apiOperation == null && apiResponses == null) { |
| 31 | + return null; |
| 32 | + } |
19 | 33 | final SwaggerOperation swaggerOperation = new SwaggerOperation();
|
20 | 34 | // @ApiOperation
|
21 |
| - { |
22 |
| - final Annotation apiOperation = Utils.getAnnotation(method, "io.swagger.annotations.ApiOperation"); |
23 |
| - if (apiOperation != null) { |
24 |
| - final Class<?> response = Utils.getAnnotationElementValue(apiOperation, "response", Class.class); |
25 |
| - final String responseContainer = Utils.getAnnotationElementValue(apiOperation, "responseContainer", String.class); |
26 |
| - if (responseContainer == null || responseContainer.isEmpty()) { |
27 |
| - swaggerOperation.responseType = response; |
28 |
| - } else { |
29 |
| - switch (responseContainer) { |
30 |
| - case "List": |
31 |
| - swaggerOperation.responseType = Utils.createParameterizedType(List.class, response); |
32 |
| - break; |
33 |
| - case "Set": |
34 |
| - swaggerOperation.responseType = Utils.createParameterizedType(Set.class, response); |
35 |
| - break; |
36 |
| - case "Map": |
37 |
| - swaggerOperation.responseType = Utils.createParameterizedType(Map.class, String.class, response); |
38 |
| - break; |
39 |
| - } |
| 35 | + if (apiOperation != null) { |
| 36 | + final Class<?> response = Utils.getAnnotationElementValue(apiOperation, "response", Class.class); |
| 37 | + final String responseContainer = Utils.getAnnotationElementValue(apiOperation, "responseContainer", String.class); |
| 38 | + if (responseContainer == null || responseContainer.isEmpty()) { |
| 39 | + swaggerOperation.responseType = response; |
| 40 | + } else { |
| 41 | + switch (responseContainer) { |
| 42 | + case "List": |
| 43 | + swaggerOperation.responseType = Utils.createParameterizedType(List.class, response); |
| 44 | + break; |
| 45 | + case "Set": |
| 46 | + swaggerOperation.responseType = Utils.createParameterizedType(Set.class, response); |
| 47 | + break; |
| 48 | + case "Map": |
| 49 | + swaggerOperation.responseType = Utils.createParameterizedType(Map.class, String.class, response); |
| 50 | + break; |
40 | 51 | }
|
41 |
| - swaggerOperation.hidden = Utils.getAnnotationElementValue(apiOperation, "hidden", Boolean.class); |
42 |
| - swaggerOperation.comment = Utils.getAnnotationElementValue(apiOperation, "value", String.class); |
43 |
| - swaggerOperation.comment = swaggerOperation.comment.isEmpty() ? null : swaggerOperation.comment; |
44 | 52 | }
|
| 53 | + swaggerOperation.hidden = Utils.getAnnotationElementValue(apiOperation, "hidden", Boolean.class); |
| 54 | + swaggerOperation.comment = Utils.getAnnotationElementValue(apiOperation, "value", String.class); |
| 55 | + swaggerOperation.comment = swaggerOperation.comment.isEmpty() ? null : swaggerOperation.comment; |
45 | 56 | }
|
46 | 57 | // @ApiResponses
|
47 |
| - { |
48 |
| - final Annotation[] apiResponses = Utils.getAnnotationElementValue(method, "io.swagger.annotations.ApiResponses", "value", Annotation[].class); |
49 |
| - if (apiResponses != null) { |
50 |
| - swaggerOperation.possibleResponses = new ArrayList<>(); |
51 |
| - for (Annotation apiResponse : apiResponses) { |
52 |
| - final SwaggerResponse response = new SwaggerResponse(); |
53 |
| - response.code = Utils.getAnnotationElementValue(apiResponse, "code", Integer.class); |
54 |
| - response.comment = Utils.getAnnotationElementValue(apiResponse, "message", String.class); |
55 |
| - response.responseType = Utils.getAnnotationElementValue(apiResponse, "response", Class.class); |
| 58 | + if (apiResponses != null) { |
| 59 | + swaggerOperation.possibleResponses = new ArrayList<>(); |
| 60 | + for (Annotation apiResponse : apiResponses) { |
| 61 | + final SwaggerResponse response = new SwaggerResponse(); |
| 62 | + response.code = String.valueOf(Utils.getAnnotationElementValue(apiResponse, "code", Integer.class)); |
| 63 | + response.comment = Utils.getAnnotationElementValue(apiResponse, "message", String.class); |
| 64 | + response.responseType = Utils.getAnnotationElementValue(apiResponse, "response", Class.class); |
| 65 | + swaggerOperation.possibleResponses.add(response); |
| 66 | + } |
| 67 | + } |
| 68 | + return swaggerOperation; |
| 69 | + } |
| 70 | + |
| 71 | + private static SwaggerOperation parseSwaggerAnnotations3(Method method) { |
| 72 | + final Annotation operationAnnotation = Utils.getAnnotation(method, "io.swagger.v3.oas.annotations.Operation"); |
| 73 | + final Annotation apiResponseAnnotation = Utils.getAnnotation(method, "io.swagger.v3.oas.annotations.responses.ApiResponse"); |
| 74 | + final Annotation apiResponsesAnnotation = Utils.getAnnotation(method, "io.swagger.v3.oas.annotations.responses.ApiResponses"); |
| 75 | + if (operationAnnotation == null && apiResponseAnnotation == null && apiResponsesAnnotation == null) { |
| 76 | + return null; |
| 77 | + } |
| 78 | + final SwaggerOperation swaggerOperation = new SwaggerOperation(); |
| 79 | + // @Operation |
| 80 | + if (operationAnnotation != null) { |
| 81 | + swaggerOperation.hidden = Utils.getAnnotationElementValue(operationAnnotation, "hidden", Boolean.class); |
| 82 | + swaggerOperation.comment = Utils.getAnnotationElementValue(operationAnnotation, "description", String.class); |
| 83 | + swaggerOperation.comment = swaggerOperation.comment.isEmpty() ? null : swaggerOperation.comment; |
| 84 | + } |
| 85 | + // @ApiResponses |
| 86 | + final List<Annotation> responses = firstResult( |
| 87 | + () -> emptyToNull(Utils.getRepeatableAnnotation(apiResponseAnnotation, apiResponsesAnnotation)), |
| 88 | + () -> emptyToNull(Arrays.asList(Utils.getAnnotationElementValue(operationAnnotation, "responses", Annotation[].class))) |
| 89 | + ); |
| 90 | + if (responses != null) { |
| 91 | + swaggerOperation.possibleResponses = new ArrayList<>(); |
| 92 | + for (Annotation apiResponse : responses) { |
| 93 | + final SwaggerResponse response = new SwaggerResponse(); |
| 94 | + final String code = Utils.getAnnotationElementValue(apiResponse, "responseCode", String.class); |
| 95 | + response.code = Objects.equals(code, "default") ? null : code; |
| 96 | + response.comment = Utils.getAnnotationElementValue(apiResponse, "description", String.class); |
| 97 | + final Annotation[] content = Utils.getAnnotationElementValue(apiResponse, "content", Annotation[].class); |
| 98 | + if (content.length > 0) { |
| 99 | + final Annotation schema = Utils.getAnnotationElementValue(content[0], "schema", Annotation.class); |
| 100 | + final Class<?> implementation = Utils.getAnnotationElementValue(schema, "implementation", Class.class); |
| 101 | + if (!Objects.equals(implementation, Void.class)) { |
| 102 | + response.responseType = implementation; |
| 103 | + if (swaggerOperation.responseType == null) { |
| 104 | + if (response.code == null || isSuccessCode(response.code)) { |
| 105 | + swaggerOperation.responseType = implementation; |
| 106 | + } |
| 107 | + } |
| 108 | + } |
| 109 | + } |
| 110 | + if (response.code != null) { |
56 | 111 | swaggerOperation.possibleResponses.add(response);
|
57 | 112 | }
|
58 | 113 | }
|
59 | 114 | }
|
60 | 115 | return swaggerOperation;
|
61 | 116 | }
|
62 | 117 |
|
| 118 | + private static boolean isSuccessCode(String code) { |
| 119 | + return code.startsWith("2"); |
| 120 | + } |
| 121 | + |
63 | 122 | static List<String> getOperationComments(SwaggerOperation operation) {
|
64 | 123 | final List<String> comments = new ArrayList<>();
|
65 | 124 | if (operation.comment != null) {
|
@@ -88,31 +147,80 @@ private static BeanModel enrichBean(BeanModel bean) {
|
88 | 147 | final PropertyModel enrichedProperty = enrichProperty(property);
|
89 | 148 | enrichedProperties.add(enrichedProperty);
|
90 | 149 | }
|
91 |
| - final String comment = Utils.getAnnotationElementValue(bean.getOrigin(), "io.swagger.annotations.ApiModel", "description", String.class); |
| 150 | + final String comment = firstResult( |
| 151 | + () -> Utils.getAnnotationElementValue(bean.getOrigin(), "io.swagger.v3.oas.annotations.media.Schema", "description", String.class), |
| 152 | + () -> Utils.getAnnotationElementValue(bean.getOrigin(), "io.swagger.annotations.ApiModel", "description", String.class)); |
92 | 153 | final List<String> comments = comment != null && !comment.isEmpty() ? Arrays.asList(comment) : null;
|
93 | 154 | return bean.withProperties(enrichedProperties).withComments(Utils.concat(comments, bean.getComments()));
|
94 | 155 | }
|
95 | 156 |
|
96 | 157 | private static PropertyModel enrichProperty(PropertyModel property) {
|
97 | 158 | if (property.getOriginalMember() instanceof AnnotatedElement) {
|
98 | 159 | final AnnotatedElement annotatedElement = (AnnotatedElement) property.getOriginalMember();
|
99 |
| - final String comment = Utils.getAnnotationElementValue(annotatedElement, "io.swagger.annotations.ApiModelProperty", "value", String.class); |
100 |
| - final List<String> comments = comment != null && !comment.isEmpty() ? Arrays.asList(comment) : null; |
101 |
| - final PropertyModel propertyModel = property.withComments(Utils.concat(comments, property.getComments())); |
102 |
| - final String dataTypeString = Utils.getAnnotationElementValue(annotatedElement, "io.swagger.annotations.ApiModelProperty", "dataType", String.class); |
103 |
| - if (dataTypeString == null || dataTypeString.isEmpty()) { |
104 |
| - return propertyModel; |
105 |
| - } |
106 |
| - try { |
107 |
| - final Type type = Class.forName(dataTypeString); |
108 |
| - final boolean required = Utils.getAnnotationElementValue(annotatedElement, "io.swagger.annotations.ApiModelProperty", "required", Boolean.class); |
109 |
| - return propertyModel.withType(type).withOptional(!required); |
110 |
| - } catch (ClassNotFoundException | ClassCastException e) { |
111 |
| - return propertyModel; |
112 |
| - } |
| 160 | + return firstResult( |
| 161 | + () -> enrichProperty3(property, annotatedElement), |
| 162 | + () -> enrichProperty1(property, annotatedElement), |
| 163 | + property); |
113 | 164 | } else {
|
114 | 165 | return property;
|
115 | 166 | }
|
116 | 167 | }
|
117 | 168 |
|
| 169 | + private static PropertyModel enrichProperty1(PropertyModel property, AnnotatedElement annotatedElement) { |
| 170 | + final Annotation apiModelProperty = Utils.getAnnotation(annotatedElement, "io.swagger.annotations.ApiModelProperty"); |
| 171 | + if (apiModelProperty == null) { |
| 172 | + return null; |
| 173 | + } |
| 174 | + final String comment = Utils.getAnnotationElementValue(apiModelProperty, "value", String.class); |
| 175 | + final List<String> comments = comment != null && !comment.isEmpty() ? Arrays.asList(comment) : null; |
| 176 | + final PropertyModel propertyModel = property.withComments(Utils.concat(comments, property.getComments())); |
| 177 | + final String dataTypeString = Utils.getAnnotationElementValue(apiModelProperty, "dataType", String.class); |
| 178 | + if (dataTypeString == null || dataTypeString.isEmpty()) { |
| 179 | + return propertyModel; |
| 180 | + } |
| 181 | + try { |
| 182 | + final Type type = Class.forName(dataTypeString); |
| 183 | + final boolean required = Utils.getAnnotationElementValue(apiModelProperty, "required", Boolean.class); |
| 184 | + return propertyModel.withType(type).withOptional(!required); |
| 185 | + } catch (ClassNotFoundException | ClassCastException e) { |
| 186 | + return propertyModel; |
| 187 | + } |
| 188 | + } |
| 189 | + |
| 190 | + private static PropertyModel enrichProperty3(PropertyModel property, AnnotatedElement annotatedElement) { |
| 191 | + final Annotation schema = Utils.getAnnotation(annotatedElement, "io.swagger.v3.oas.annotations.media.Schema"); |
| 192 | + if (schema == null) { |
| 193 | + return null; |
| 194 | + } |
| 195 | + final String comment = Utils.getAnnotationElementValue(schema, "description", String.class); |
| 196 | + final List<String> comments = comment != null && !comment.isEmpty() ? Arrays.asList(comment) : null; |
| 197 | + final PropertyModel propertyModel = property.withComments(Utils.concat(comments, property.getComments())); |
| 198 | + final Class<?> implementation = Utils.getAnnotationElementValue(schema, "implementation", Class.class); |
| 199 | + if (implementation == null || Objects.equals(implementation, Void.class)) { |
| 200 | + return propertyModel; |
| 201 | + } |
| 202 | + final boolean required = Utils.getAnnotationElementValue(schema, "required", Boolean.class); |
| 203 | + return propertyModel.withType(implementation).withOptional(!required); |
| 204 | + } |
| 205 | + |
| 206 | + private static <T> T firstResult(Supplier<? extends T> supplier1, Supplier<? extends T> supplier2) { |
| 207 | + return firstResult(supplier1, supplier2, null); |
| 208 | + } |
| 209 | + |
| 210 | + private static <T> T firstResult(Supplier<? extends T> supplier1, Supplier<? extends T> supplier2, T defaultResult) { |
| 211 | + final T result1 = supplier1.get(); |
| 212 | + if (result1 != null) { |
| 213 | + return result1; |
| 214 | + } |
| 215 | + final T result2 = supplier2.get(); |
| 216 | + if (result2 != null) { |
| 217 | + return result2; |
| 218 | + } |
| 219 | + return defaultResult; |
| 220 | + } |
| 221 | + |
| 222 | + private static <T> List<T> emptyToNull(List<T> list) { |
| 223 | + return list != null && !list.isEmpty() ? list : null; |
| 224 | + } |
| 225 | + |
118 | 226 | }
|
0 commit comments