Skip to content

Commit 4823d7b

Browse files
committed
feat(docservice): Support Jackson polymorphism annotations (#6370)
1 parent e2a8648 commit 4823d7b

File tree

17 files changed

+1478
-584
lines changed

17 files changed

+1478
-584
lines changed

core/src/main/java/com/linecorp/armeria/internal/server/annotation/AnnotatedDocServicePlugin.java

Lines changed: 1 addition & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -16,37 +16,28 @@
1616

1717
package com.linecorp.armeria.internal.server.annotation;
1818

19-
import static com.google.common.collect.ImmutableList.toImmutableList;
2019
import static com.google.common.collect.ImmutableSet.toImmutableSet;
2120
import static com.linecorp.armeria.internal.server.annotation.KotlinUtil.isKFunction;
2221
import static com.linecorp.armeria.internal.server.annotation.KotlinUtil.isReturnTypeNothing;
2322
import static com.linecorp.armeria.internal.server.annotation.KotlinUtil.kFunctionGenericReturnType;
2423
import static com.linecorp.armeria.internal.server.annotation.KotlinUtil.kFunctionReturnType;
24+
import static com.linecorp.armeria.internal.server.docs.DocServiceTypeUtil.toTypeSignature;
2525
import static com.linecorp.armeria.server.docs.FieldLocation.HEADER;
2626
import static com.linecorp.armeria.server.docs.FieldLocation.PATH;
2727
import static com.linecorp.armeria.server.docs.FieldLocation.QUERY;
2828
import static com.linecorp.armeria.server.docs.FieldLocation.UNSPECIFIED;
2929
import static java.util.Objects.requireNonNull;
3030

3131
import java.lang.annotation.Annotation;
32-
import java.lang.reflect.GenericArrayType;
3332
import java.lang.reflect.Method;
34-
import java.lang.reflect.ParameterizedType;
35-
import java.lang.reflect.Type;
36-
import java.lang.reflect.TypeVariable;
37-
import java.lang.reflect.WildcardType;
38-
import java.nio.ByteBuffer;
3933
import java.util.HashMap;
4034
import java.util.HashSet;
4135
import java.util.List;
4236
import java.util.Map;
43-
import java.util.Optional;
4437
import java.util.Set;
45-
import java.util.stream.Stream;
4638

4739
import com.fasterxml.jackson.core.JsonProcessingException;
4840
import com.fasterxml.jackson.core.TreeNode;
49-
import com.fasterxml.jackson.databind.JavaType;
5041
import com.fasterxml.jackson.databind.ObjectWriter;
5142
import com.google.common.annotations.VisibleForTesting;
5243
import com.google.common.collect.ImmutableList;
@@ -84,36 +75,11 @@
8475
import com.linecorp.armeria.server.docs.TypeSignature;
8576
import com.linecorp.armeria.server.docs.TypeSignatureType;
8677

87-
import io.netty.buffer.ByteBuf;
88-
8978
/**
9079
* A {@link DocServicePlugin} implementation that supports the {@link AnnotatedService}.
9180
*/
9281
public final class AnnotatedDocServicePlugin implements DocServicePlugin {
9382

94-
@VisibleForTesting
95-
static final TypeSignature VOID = TypeSignature.ofBase("void");
96-
@VisibleForTesting
97-
static final TypeSignature BOOLEAN = TypeSignature.ofBase("boolean");
98-
@VisibleForTesting
99-
static final TypeSignature BYTE = TypeSignature.ofBase("byte");
100-
@VisibleForTesting
101-
static final TypeSignature SHORT = TypeSignature.ofBase("short");
102-
@VisibleForTesting
103-
static final TypeSignature INT = TypeSignature.ofBase("int");
104-
@VisibleForTesting
105-
static final TypeSignature LONG = TypeSignature.ofBase("long");
106-
@VisibleForTesting
107-
static final TypeSignature FLOAT = TypeSignature.ofBase("float");
108-
@VisibleForTesting
109-
static final TypeSignature DOUBLE = TypeSignature.ofBase("double");
110-
@VisibleForTesting
111-
static final TypeSignature CHAR = TypeSignature.ofBase("char");
112-
@VisibleForTesting
113-
static final TypeSignature STRING = TypeSignature.ofBase("string");
114-
@VisibleForTesting
115-
static final TypeSignature BINARY = TypeSignature.ofBase("binary");
116-
11783
private static final ObjectWriter objectWriter = JacksonUtil.newDefaultObjectMapper()
11884
.writerWithDefaultPrettyPrinter();
11985

@@ -311,121 +277,6 @@ private static FieldInfo fieldInfo(AnnotatedValueResolver resolver) {
311277
.build();
312278
}
313279

314-
static TypeSignature toTypeSignature(Type type) {
315-
requireNonNull(type, "type");
316-
317-
if (type instanceof JavaType) {
318-
return toTypeSignature((JavaType) type);
319-
}
320-
321-
// The data types defined by the OpenAPI Specification:
322-
323-
if (type == Void.class || type == void.class) {
324-
return VOID;
325-
}
326-
if (type == Boolean.class || type == boolean.class) {
327-
return BOOLEAN;
328-
}
329-
if (type == Byte.class || type == byte.class) {
330-
return BYTE;
331-
}
332-
if (type == Short.class || type == short.class) {
333-
return SHORT;
334-
}
335-
if (type == Integer.class || type == int.class) {
336-
return INT;
337-
}
338-
if (type == Long.class || type == long.class) {
339-
return LONG;
340-
}
341-
if (type == Float.class || type == float.class) {
342-
return FLOAT;
343-
}
344-
if (type == Double.class || type == double.class) {
345-
return DOUBLE;
346-
}
347-
if (type == Character.class || type == char.class) {
348-
return CHAR;
349-
}
350-
if (type == String.class) {
351-
return STRING;
352-
}
353-
if (type == byte[].class || type == Byte[].class ||
354-
type == ByteBuffer.class || type == ByteBuf.class) {
355-
return BINARY;
356-
}
357-
// End of data types defined by the OpenAPI Specification.
358-
359-
if (type instanceof ParameterizedType) {
360-
final ParameterizedType parameterizedType = (ParameterizedType) type;
361-
final Class<?> rawType = (Class<?>) parameterizedType.getRawType();
362-
if (List.class.isAssignableFrom(rawType)) {
363-
return TypeSignature.ofList(toTypeSignature(parameterizedType.getActualTypeArguments()[0]));
364-
}
365-
if (Set.class.isAssignableFrom(rawType)) {
366-
return TypeSignature.ofSet(toTypeSignature(parameterizedType.getActualTypeArguments()[0]));
367-
}
368-
369-
if (Map.class.isAssignableFrom(rawType)) {
370-
final TypeSignature key = toTypeSignature(parameterizedType.getActualTypeArguments()[0]);
371-
final TypeSignature value = toTypeSignature(parameterizedType.getActualTypeArguments()[1]);
372-
return TypeSignature.ofMap(key, value);
373-
}
374-
375-
if (Optional.class.isAssignableFrom(rawType) || "scala.Option".equals(rawType.getName())) {
376-
return TypeSignature.ofOptional(toTypeSignature(parameterizedType.getActualTypeArguments()[0]));
377-
}
378-
379-
final List<TypeSignature> actualTypes = Stream.of(parameterizedType.getActualTypeArguments())
380-
.map(AnnotatedDocServicePlugin::toTypeSignature)
381-
.collect(toImmutableList());
382-
return TypeSignature.ofContainer(rawType.getSimpleName(), actualTypes);
383-
}
384-
385-
if (type instanceof WildcardType) {
386-
// Create an unresolved type with an empty string so that the type name will be '?'.
387-
return TypeSignature.ofUnresolved("");
388-
}
389-
if (type instanceof TypeVariable) {
390-
return TypeSignature.ofBase(type.getTypeName());
391-
}
392-
if (type instanceof GenericArrayType) {
393-
return TypeSignature.ofList(toTypeSignature(((GenericArrayType) type).getGenericComponentType()));
394-
}
395-
396-
if (!(type instanceof Class)) {
397-
return TypeSignature.ofBase(type.getTypeName());
398-
}
399-
400-
final Class<?> clazz = (Class<?>) type;
401-
if (clazz.isArray()) {
402-
// If it's an array, return it as a list.
403-
return TypeSignature.ofList(toTypeSignature(clazz.getComponentType()));
404-
}
405-
406-
return TypeSignature.ofStruct(clazz);
407-
}
408-
409-
static TypeSignature toTypeSignature(JavaType type) {
410-
if (type.isArrayType() || type.isCollectionLikeType()) {
411-
return TypeSignature.ofList(toTypeSignature(type.getContentType()));
412-
}
413-
414-
if (type.isMapLikeType()) {
415-
final TypeSignature key = toTypeSignature(type.getKeyType());
416-
final TypeSignature value = toTypeSignature(type.getContentType());
417-
return TypeSignature.ofMap(key, value);
418-
}
419-
420-
if (Optional.class.isAssignableFrom(type.getRawClass()) ||
421-
"scala.Option".equals(type.getRawClass().getName())) {
422-
return TypeSignature.ofOptional(
423-
toTypeSignature(type.getBindings().getBoundType(0)));
424-
}
425-
426-
return toTypeSignature(type.getRawClass());
427-
}
428-
429280
private static FieldLocation location(AnnotatedValueResolver resolver) {
430281
if (resolver.isPathVariable()) {
431282
return PATH;

core/src/main/java/com/linecorp/armeria/internal/server/annotation/DefaultDescriptiveTypeInfoProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
import static com.google.common.base.MoreObjects.firstNonNull;
2020
import static com.google.common.collect.ImmutableList.toImmutableList;
21-
import static com.linecorp.armeria.internal.server.annotation.AnnotatedDocServicePlugin.toTypeSignature;
2221
import static com.linecorp.armeria.internal.server.annotation.AnnotatedValueResolver.isAnnotatedNullable;
22+
import static com.linecorp.armeria.internal.server.docs.DocServiceTypeUtil.toTypeSignature;
2323
import static java.util.Objects.requireNonNull;
2424

2525
import java.lang.reflect.AnnotatedElement;

core/src/main/java/com/linecorp/armeria/internal/server/annotation/ReflectiveDescriptiveTypeInfoProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
package com.linecorp.armeria.internal.server.annotation;
1818

1919
import static com.google.common.collect.ImmutableList.toImmutableList;
20-
import static com.linecorp.armeria.internal.server.annotation.AnnotatedDocServicePlugin.toTypeSignature;
2120
import static com.linecorp.armeria.internal.server.annotation.DefaultDescriptiveTypeInfoProvider.isNullable;
21+
import static com.linecorp.armeria.internal.server.docs.DocServiceTypeUtil.toTypeSignature;
2222

2323
import java.lang.reflect.AnnotatedElement;
2424
import java.lang.reflect.Field;

0 commit comments

Comments
 (0)