private void verifyArrayFieldTypeAnnotations(Class c) throws NoSuchFieldException, NoSuchMethodException { Annotation anno; AnnotatedType at; at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType(); anno = at.getAnnotations()[0]; verifyTestAnn(arrayTA[0], anno, "array1"); arrayTA[0] = anno; for (int i = 1; i <= 3; i++) { at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType(); anno = at.getAnnotations()[0]; verifyTestAnn(arrayTA[i], anno, "array" + (i + 1)); arrayTA[i] = anno; } }
/** Create {@link JavaType} based on {@link AnnotatedType} instance. */ public static JavaType of(AnnotatedType annotatedType) { if (annotatedType instanceof AnnotatedArrayType) { return JavaTypes.of((AnnotatedArrayType) annotatedType); } if (annotatedType instanceof AnnotatedParameterizedType) { return JavaTypes.of((AnnotatedParameterizedType) annotatedType); } if (annotatedType instanceof AnnotatedTypeVariable) { return JavaTypes.of((AnnotatedTypeVariable) annotatedType); } if (annotatedType instanceof AnnotatedWildcardType) { return JavaTypes.of((AnnotatedWildcardType) annotatedType); } // default case: use underlying raw type JavaType result = of(annotatedType.getType()); result.getAnnotations().addAll(Annotation.of(annotatedType.getAnnotations())); return result; }
public static boolean containsTypeAnnotation(AnnotatedType type, Class<? extends Annotation> annotation) { if (type.isAnnotationPresent(annotation)) { return true; } if (type instanceof AnnotatedParameterizedType) { AnnotatedParameterizedType parameterizedType = ((AnnotatedParameterizedType) type); return Arrays.stream(parameterizedType.getAnnotatedActualTypeArguments()) .anyMatch(param -> containsTypeAnnotation(param, annotation)); } if (type instanceof AnnotatedTypeVariable) { AnnotatedTypeVariable variable = ((AnnotatedTypeVariable) type); return Arrays.stream(variable.getAnnotatedBounds()) .anyMatch(bound -> containsTypeAnnotation(bound, annotation)); } if (type instanceof AnnotatedWildcardType) { AnnotatedWildcardType wildcard = ((AnnotatedWildcardType) type); return Stream.concat( Arrays.stream(wildcard.getAnnotatedLowerBounds()), Arrays.stream(wildcard.getAnnotatedUpperBounds())) .anyMatch(param -> containsTypeAnnotation(param, annotation)); } if (type instanceof AnnotatedArrayType) { return containsTypeAnnotation(((AnnotatedArrayType) type).getAnnotatedGenericComponentType(), annotation); } return false; }
/** Create {@link JavaType} based on {@link AnnotatedArrayType} instance. */ static JavaType of(AnnotatedArrayType annotatedType) { List<ArrayDimension> dimensions = new ArrayList<>(); AnnotatedType component = annotatedType; while (component instanceof AnnotatedArrayType) { ArrayDimension dimension = new ArrayDimension(); stream(component.getAnnotations()).forEach(a -> dimension.addAnnotation(a)); dimensions.add(dimension); component = ((AnnotatedArrayType) component).getAnnotatedGenericComponentType(); } return ArrayType.of(JavaType.of(component), dimensions); }
@Override public AnnotatedType getSubstituteType(AnnotatedType original) { return TypeFactory.parameterizedAnnotatedClass(List.class, original.getAnnotations(), ((AnnotatedArrayType) original).getAnnotatedGenericComponentType()); }
@Override public boolean supports(AnnotatedType type) { return type instanceof AnnotatedArrayType; }
public static AnnotatedType unionize(AnnotatedType[] types) { Objects.requireNonNull(types); if (types.length < 2) { if (types.length == 1 && GenericTypeReflector.isSuperType(Union.class, types[0].getType())) { return types[0]; } throw new IllegalArgumentException(SINGLE_TYPE_UNION_ERROR); } AnnotatedType t1 = types[0]; if (stream(types).anyMatch(t -> t.isAnnotationPresent(GraphQLUnion.class))) { if (stream(types).allMatch(t -> t.isAnnotationPresent(GraphQLUnion.class) && t.getAnnotation(GraphQLUnion.class).name().equals(t1.getAnnotation(GraphQLUnion.class).name()))) { return of(types); } else { throw new IllegalArgumentException("All union members must be explicitly annotated: " + Arrays.toString(types)); } } if (stream(types).allMatch(t -> t instanceof AnnotatedParameterizedType)) { AnnotatedParameterizedType p1 = (AnnotatedParameterizedType) t1; AnnotatedParameterizedType[] pTypes = stream(types) .map(t -> (AnnotatedParameterizedType) t) .toArray(AnnotatedParameterizedType[]::new); AnnotatedType[] params = new AnnotatedType[p1.getAnnotatedActualTypeArguments().length]; for (int i = 0; i < p1.getAnnotatedActualTypeArguments().length; i++) { final int j = i; params[i] = unionize(stream(pTypes) .map(p -> p.getAnnotatedActualTypeArguments()[j]) .toArray(AnnotatedType[]::new)); } Class<?> rawType = ((Class<?>) ((ParameterizedType) p1.getType()).getRawType()); return TypeFactory.parameterizedAnnotatedClass(rawType, ClassUtils.getAllAnnotations(stream(types)), params); } if (stream(types).allMatch(t -> t instanceof AnnotatedArrayType)) { AnnotatedType[] components = stream(types) .map(type -> ((AnnotatedArrayType) type).getAnnotatedGenericComponentType()) .toArray(AnnotatedType[]::new); return TypeFactory.arrayOf(unionize(components), ClassUtils.getAllAnnotations(stream(types))); } if (stream(types).allMatch(t -> types[0].getType().equals(t.getType()))) { return types[0]; } throw new IllegalArgumentException("Types are incompatible and can not be unionized: "); }
private static AnnotatedType getCommonSuperType(List<AnnotatedType> types, Set<String> seenTypeCombos, AnnotatedType fallback) { if (types == null || types.isEmpty()) { throw new IllegalArgumentException("At least one type must be provided"); } if (types.size() == 1) { return types.get(0); } Annotation[] mergedAnnotations = getMergedAnnotations(types.toArray(new AnnotatedType[types.size()])); if (types.stream().map(AnnotatedType::getType).allMatch(type -> type.equals(types.get(0).getType()))) { return GenericTypeReflector.replaceAnnotations(types.get(0), mergedAnnotations); } List<Class<?>> classes = types.stream().map(AnnotatedType::getType).map(ClassUtils::getRawType).collect(Collectors.toList()); String typeNames = types.stream().map(type -> type.getType().getTypeName()).sorted().collect(Collectors.joining(",")); if (seenTypeCombos.contains(typeNames)) { return fallbackOrException(fallback); } seenTypeCombos.add(typeNames); //deal with arrays first as they are special if (types.stream().allMatch(type -> type instanceof AnnotatedArrayType)) { List<AnnotatedType> componentTypes = types.stream() .map(type -> ((AnnotatedArrayType) type).getAnnotatedGenericComponentType()) .collect(Collectors.toList()); AnnotatedType componentType = getCommonSuperType(componentTypes, seenTypeCombos, fallback); return TypeFactory.arrayOf(componentType, mergedAnnotations); } Class<?> commonRawSuperType = getCommonSuperTypes(classes).get(0); if (classes.stream().noneMatch(ROOT_TYPES::contains) && ROOT_TYPES.contains(commonRawSuperType)) { return fallbackOrException(fallback); } List<AnnotatedType> normalizedTypes = types.stream() .map(type -> GenericTypeReflector.getExactSuperType(type, commonRawSuperType)) .collect(Collectors.toList()); if (normalizedTypes.stream().anyMatch(type -> GenericTypeReflector.isMissingTypeParameters(type.getType()))) { throw new TypeMappingException("Automatic type inference failed because some of the types are missing generic type parameter(s)."); } if (normalizedTypes.stream().allMatch(type -> type.getType() instanceof Class)) { return annotate(commonRawSuperType, mergedAnnotations); } if (normalizedTypes.stream().allMatch(type -> type instanceof AnnotatedParameterizedType)) { AnnotatedType[] parameters = Arrays.stream(commonRawSuperType.getTypeParameters()) .map(param -> normalizedTypes.stream().map(type -> GenericTypeReflector.getTypeParameter(type, param)).collect(Collectors.toList())) .map(paramTypes -> getCommonSuperType(paramTypes, seenTypeCombos, fallback)) .toArray(AnnotatedType[]::new); return TypeFactory.parameterizedAnnotatedClass(commonRawSuperType, mergedAnnotations, parameters); } return fallbackOrException(fallback); }
public static <T> TypedClass<T> wrap(AnnotatedType ant) { if (ant instanceof AnnotatedParameterizedType) { AnnotatedParameterizedType pant = (AnnotatedParameterizedType) ant; ParameterizedType pt = (ParameterizedType) ant.getType(); return (TypedClass<T>) wrap(wrapSimple(pt.getRawType()), pant.getAnnotatedActualTypeArguments(), pt, ant.getAnnotations()); } else if (ant instanceof AnnotatedArrayType) { AnnotatedArrayType aant = (AnnotatedArrayType) ant; TypedClass<?> ctype = wrap(aant.getAnnotatedGenericComponentType()); return new TypedArrayClass<>(ctype, ant.getAnnotations()); } return wrap(ant.getType(), ant.getDeclaredAnnotations()); }