private static void testReturnsZeroLengthArray() { for (Class<?> toTest : testData) { tests++; AnnotatedType[] res = toTest.getAnnotatedInterfaces(); if (res == null) { failed++; System.out.println(toTest + ".class.getAnnotatedInterface() returns" + "'null' should zero length array"); } else if (res.length != 0) { failed++; System.out.println(toTest + ".class.getAnnotatedInterfaces() returns: " + Arrays.asList(res) + ", should be a zero length array of AnnotatedType"); } } }
private static void testReturnsEmptyAT() { for (Class<?> toTest : nonNullTestData) { tests++; AnnotatedType res = toTest.getAnnotatedSuperclass(); if (res == null) { failed++; System.out.println(toTest + ".getAnnotatedSuperclass() returns 'null' should be non-null"); } else if (res.getAnnotations().length != 0) { failed++; System.out.println(toTest + ".getAnnotatedSuperclass() returns: " + Arrays.asList(res.getAnnotations()) + ", should be an empty AnnotatedType"); } } }
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; } }
@Override public Object getArgumentValue(Object rawInput, AnnotatedType type, ResolutionEnvironment resolutionEnvironment) { if (GenericTypeReflector.isSuperType(setOfStrings, type.getType())) { return resolutionEnvironment.dataFetchingEnvironment.getSelectionSet().get().keySet(); } Class raw = GenericTypeReflector.erase(type.getType()); if (Field.class.equals(raw)) { return resolutionEnvironment.fields.get(0); } if (GenericTypeReflector.isSuperType(listOfFields, type.getType())) { return resolutionEnvironment.fields; } if (ValueMapper.class.isAssignableFrom(raw)) { return resolutionEnvironment.valueMapper; } if (ResolutionEnvironment.class.isAssignableFrom(raw)) { return resolutionEnvironment; } throw new IllegalArgumentException("Argument of type " + raw.getName() + " can not be injected via @" + GraphQLEnvironment.class.getSimpleName()); }
/** 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 AnnotatedType of(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[] distinctTypes = dedupe(types); Class union; try { union = ClassUtils.forName(Union.class.getName() + distinctTypes.length); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Unions of more than 10 types are not supported"); } Annotation unionAnnotation = stream(ClassUtils.getAllAnnotations(stream(types))) .filter(annotation -> annotation.annotationType().equals(GraphQLUnion.class)) .filter(annotation -> !((GraphQLUnion) annotation).description().isEmpty()) .findFirst().orElse(types[0].getAnnotation(GraphQLUnion.class)); return TypeFactory.parameterizedAnnotatedClass(union, new Annotation[] {unionAnnotation}, distinctTypes); }
private AnnotatedType getInputFieldType(AnnotatedType type, BeanPropertyDefinition propertyDefinition) { AnnotatedParameter ctorParam = propertyDefinition.getConstructorParameter(); if (ctorParam != null) { Constructor<?> constructor = (Constructor<?>) ctorParam.getOwner().getMember(); return ClassUtils.getParameterTypes(constructor, type)[ctorParam.getIndex()]; } if (propertyDefinition.getSetter() != null) { return ClassUtils.getParameterTypes(propertyDefinition.getSetter().getAnnotated(), type)[0]; } if (propertyDefinition.getGetter() != null) { return ClassUtils.getReturnType(propertyDefinition.getGetter().getAnnotated(), type); } if (propertyDefinition.getField() != null) { return ClassUtils.getFieldType(propertyDefinition.getField().getAnnotated(), type); } throw new UnsupportedOperationException("Unknown input field mapping style encountered"); }
protected Set<Type> collectAbstract(AnnotatedType javaType, Set<Type> seen, BuildContext buildContext) { javaType = buildContext.globalEnvironment.converters.getMappableType(javaType); if (Scalars.isScalar(javaType.getType())) { return Collections.emptySet(); } if (GenericTypeReflector.isSuperType(Collection.class, javaType.getType())) { AnnotatedType elementType = GenericTypeReflector.getTypeParameter(javaType, Collection.class.getTypeParameters()[0]); return collectAbstractInner(elementType, seen, buildContext); } if (GenericTypeReflector.isSuperType(Map.class, javaType.getType())) { AnnotatedType keyType = GenericTypeReflector.getTypeParameter(javaType, Map.class.getTypeParameters()[0]); AnnotatedType valueType = GenericTypeReflector.getTypeParameter(javaType, Map.class.getTypeParameters()[1]); Set<Type> abstractTypes = collectAbstractInner(keyType, seen, buildContext); abstractTypes.addAll(collectAbstractInner(valueType, seen, buildContext)); return abstractTypes; } return collectAbstractInner(javaType, seen, buildContext); }
private Set<Type> collectAbstractInner(AnnotatedType javaType, Set<Type> seen, BuildContext buildContext) { if (buildContext.abstractComponentTypes.containsKey(javaType.getType())) { return buildContext.abstractComponentTypes.get(javaType.getType()); } if (seen.contains(javaType.getType())) { return Collections.emptySet(); } seen.add(javaType.getType()); Set<Type> abstractTypes = new HashSet<>(); if (ClassUtils.isAbstract(javaType)) { abstractTypes.add(javaType.getType()); } buildContext.inputFieldStrategy.getInputFields(javaType) .forEach(childQuery -> abstractTypes.addAll(collectAbstract(childQuery.getJavaType(), seen, buildContext))); buildContext.abstractComponentTypes.put(javaType.getType(), abstractTypes); return abstractTypes; }
@Test public void java8TypeAnnotation() throws Exception { Method method = ImmutableHasTypeAnnotation.class.getMethod("str"); AnnotatedType returnType = method.getAnnotatedReturnType(); check(returnType.getAnnotation(TypeA.class)).notNull(); check(returnType.getAnnotation(TypeB.class)).notNull(); }
/** * Check whether the given <code>method</code> return type is annotated with the {@link PropertySetRef} annotation. * @param method Method to inspect * @return Optional {@link PropertySetRef} annotation, if available */ private static Optional<PropertySetRef> getResponsePropertySet(Method method) { final AnnotatedType rt = method.getAnnotatedReturnType(); if (rt != null) { if (rt.isAnnotationPresent(PropertySetRef.class)) { return Optional.of(rt.getAnnotation(PropertySetRef.class)); } // check meta-annotations List<PropertySetRef> annotations = AnnotationUtils.getAnnotations(rt, PropertySetRef.class); if (!annotations.isEmpty()) { return Optional.ofNullable(annotations.get(0)); } } return Optional.empty(); }
/** * Check whether the given <code>method</code> return type is annotated with the {@link ApiPropertySetModel} * annotation. * @param method Method to inspect * @return Optional {@link ApiPropertySetModel} annotation, if available */ private static Optional<ApiPropertySetModel> getResponsePropertySetModel(Method method) { final AnnotatedType rt = method.getAnnotatedReturnType(); if (rt != null) { if (rt.isAnnotationPresent(ApiPropertySetModel.class)) { return Optional.of(rt.getAnnotation(ApiPropertySetModel.class)); } // check meta-annotations List<ApiPropertySetModel> annotations = AnnotationUtils.getAnnotations(rt, ApiPropertySetModel.class); if (!annotations.isEmpty()) { return Optional.ofNullable(annotations.get(0)); } } return Optional.empty(); }
public MinijaxPropertyDescriptor(final Class<?> elementClass, final AnnotatedType annotatedType, final Annotation[] annotations) { super(elementClass, buildConstraintDescriptors(annotatedType, annotations)); if (annotatedType instanceof AnnotatedParameterizedType) { constrainedContainerElementTypes = MinijaxContainerElementTypeDescriptor.build(elementClass, (AnnotatedParameterizedType) annotatedType); } else { constrainedContainerElementTypes = emptySet(); } }
private static Set<ConstraintDescriptor<?>> buildConstraintDescriptors(final AnnotatedType annotatedType, final Annotation[] annotations) { final Set<ConstraintDescriptor<?>> result = new HashSet<>(); for (final Annotation annotation : annotations) { final MinijaxConstraintDescriptor<?> constraintDescriptor = MinijaxConstraintDescriptor.build(annotatedType, annotation); if (constraintDescriptor != null) { result.add(constraintDescriptor); } } return result; }
public static Set<ContainerElementTypeDescriptor> build( final Class<?> elementClass, final AnnotatedParameterizedType annotatedType) { final Set<ContainerElementTypeDescriptor> result = new HashSet<>(); final Class<?> containerClass = ReflectionUtils.getRawType(annotatedType); int argIndex = 0; for (final AnnotatedType typeArg : annotatedType.getAnnotatedActualTypeArguments()) { final Set<ConstraintDescriptor<?>> constraintDescriptors = new HashSet<>(); for (final Annotation annotation : typeArg.getAnnotations()) { final MinijaxConstraintDescriptor<?> constraintDescriptor = MinijaxConstraintDescriptor.build(typeArg, annotation); if (constraintDescriptor != null) { constraintDescriptors.add(constraintDescriptor); } } if (!constraintDescriptors.isEmpty()) { result.add(new MinijaxContainerElementTypeDescriptor(elementClass, containerClass, argIndex, constraintDescriptors)); } argIndex++; } return result; }
public static Class<?> getRawType(final AnnotatedType annotatedType) { final Type containerType = annotatedType.getType(); if (containerType instanceof Class) { return (Class<?>) containerType; } else if (containerType instanceof ParameterizedType) { return (Class<?>) ((ParameterizedType) containerType).getRawType(); } else { throw new ValidationException("Unknown type: " + containerType.getClass()); } }
private static void checkEmptyAT(AnnotatedType a, String msg) { if (a.getAnnotations().length != 0) { failures++; System.err.print(msg); } tests++; }
private void verifyInnerFieldTypeAnnotations(Class c) throws NoSuchFieldException, NoSuchMethodException { AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType(); Annotation anno = at.getAnnotations()[0]; verifyTestAnn(innerTA, anno, "inner"); innerTA = anno; }
private void verifyMapFieldTypeAnnotations(Class c) throws NoSuchFieldException, NoSuchMethodException { Annotation anno; AnnotatedType atBase; AnnotatedType atParameter; atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType(); anno = atBase.getAnnotations()[0]; verifyTestAnn(mapTA[0], anno, "map1"); mapTA[0] = anno; atParameter = ((AnnotatedParameterizedType) atBase). getAnnotatedActualTypeArguments()[0]; anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0]; verifyTestAnn(mapTA[1], anno, "map2"); mapTA[1] = anno; anno = ((AnnotatedWildcardType) atParameter). getAnnotatedUpperBounds()[0].getAnnotations()[0]; verifyTestAnn(mapTA[2], anno, "map3"); mapTA[2] = anno; atParameter = ((AnnotatedParameterizedType) atBase). getAnnotatedActualTypeArguments()[1]; anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0]; verifyTestAnn(mapTA[3], anno, "map4"); mapTA[3] = anno; anno = ((AnnotatedParameterizedType) atParameter). getAnnotatedActualTypeArguments()[0].getAnnotations()[0]; verifyTestAnn(mapTA[4], anno, "map5"); mapTA[4] = anno; }
public void checkAnnotations(AnnotatedType type, String expected) { String actual = Arrays.asList(((AnnotatedParameterizedType) type) .getAnnotations()) .toString() + "," + Arrays.asList(((AnnotatedParameterizedType) type) .getAnnotatedActualTypeArguments()[0].getAnnotations()) .toString(); if (!actual.equals(expected)) throw new AssertionError("Unexpected annotations" + actual); }
private static void checkNull(Executable e, String msg) { AnnotatedType a = e.getAnnotatedReceiverType(); if (a != null) { failures++; System.err.println(msg + ": " + e); } tests++; }
private static void checkEmptyAT(Executable e, String msg) { AnnotatedType a = e.getAnnotatedReceiverType(); if (a.getAnnotations().length != 0) { failures++; System.err.print(msg + ": " + e); } tests++; }
/** * Scans classpath for implementations/subtypes of the given {@link AnnotatedType}. Only the matching classes are loaded. * * @param superType The type whose implementations/subtypes are to be looked for * @return A collection of {@link AnnotatedType}s found on the classpath that are implementations/subtypes of {@code superType} * @throws RuntimeException If a class file could not be parsed or a class could not be loaded */ public static List<AnnotatedType> findImplementations(AnnotatedType superType, String... packages) { Class<?> rawType = getRawType(superType.getType()); return findImplementations(rawType, packages).stream() .map(raw -> GenericTypeReflector.getExactSubType(superType, raw)) .filter(Objects::nonNull) .collect(Collectors.toList()); }
@Override public String name() { AnnotatedType annType = api(); Type type = annType.getType(); if (type instanceof Class) { Class<?> cl = (Class<?>) type; return "anon:" + cl.getSimpleName(); } else { return "anon:" + type; } }
/** * Returns the exact annotated parameter types of the executable declared by the given type, with type variables resolved (if possible) * * @param executable The executable whose parameter types are to be resolved * @param declaringType The declaring annotated type against which to resolve the types of the parameters of the given executable * @return The resolved annotated types of the parameters of the given executable */ public static AnnotatedType[] getParameterTypes(Executable executable, AnnotatedType declaringType) { AnnotatedType exactDeclaringType = GenericTypeReflector.getExactSuperType(capture(declaringType), executable.getDeclaringClass()); if (GenericTypeReflector.isMissingTypeParameters(exactDeclaringType.getType())) { return executable.getAnnotatedParameterTypes(); } return GenericTypeReflector.getParameterTypes(executable, declaringType); }
@Test public <T extends Long, S extends Double> void testBoundedTypeVariables() throws AnnotationFormatException { AnnotatedType t1 = new TypeToken<ArrayList<T>>(){}.getAnnotatedType(); AnnotatedType t2 = new TypeToken<LinkedList<S>>(){}.getAnnotatedType(); AnnotatedType expected = new TypeToken<AbstractList<Number>>(){}.getAnnotatedType(); assertTrue(GenericTypeReflector.equals(expected, ClassUtils.getCommonSuperType(Arrays.asList(t1, t2)))); }
@Override public String generateMutationName(Method mutationMethod, AnnotatedType declaringType, Object instance) { if (mutationMethod.isAnnotationPresent(GraphQLMutation.class)) { return mutationMethod.getAnnotation(GraphQLMutation.class).name(); } Class<?> declaringClass = ClassUtils.getRawType(declaringType.getType()); if (declaringClass.isAnnotationPresent(GraphQLMutation.class)) { return declaringClass.getAnnotation(GraphQLMutation.class).name(); } throw new IllegalArgumentException("Neither the method " + mutationMethod.toString() + " nor the declaring class are annotated with " + GraphQLMutation.class.getSimpleName()); }
@Override @SuppressWarnings("unchecked") public <T> T fromString(String json, AnnotatedType type) { if (STRING_MAPPER.supports(type.getType())) { return STRING_MAPPER.deserialize(json, type.getType()); } throw new IllegalArgumentException(MAPPING_ERROR); }
private AnnotatedType resolveJavaType(List<AnnotatedType> types, String errorPrefix) { errorPrefix = errorPrefix + " Types found: " + Arrays.toString(types.stream().map(type -> type.getType().getTypeName()).toArray()) + ". "; if (!typeInference.inferTypes && !types.stream().map(AnnotatedType::getType).allMatch(type -> type.equals(types.get(0).getType()))) { throw new TypeMappingException(errorPrefix + "If this is intentional, and you wish GraphQL SPQR to infer the most " + "common super type automatically, see https://github.com/leangen/graphql-spqr/wiki/Errors#operation-with-multiple-resolver-methods-of-different-types"); } try { return ClassUtils.getCommonSuperType(types, typeInference.allowObject ? GenericTypeReflector.annotate(Object.class) : null); } catch (TypeMappingException e) { throw new TypeMappingException(errorPrefix, e); } }
private void checkApiRules(Class<?> publicClass) { List<Class<?>> declaredClasses = publicClasses(publicClass.getDeclaredClasses()); if (!declaredClasses.isEmpty()) { throw new IllegalStateException("There are no inner classes in the public API"); } Class<?> componentType = publicClass.getComponentType(); if (componentType != null) { throw new IllegalStateException("There are no array classes in the public API"); } AnnotatedType annotatedSuperclass = publicClass.getAnnotatedSuperclass(); if (annotatedSuperclass != null && annotatedSuperclass.getAnnotations().length > 0) { throw new IllegalStateException("There are no annotated super classes in the public API"); } AnnotatedType[] annotatedInterfaces = publicClass.getAnnotatedInterfaces(); for (AnnotatedType annotatedInterface : annotatedInterfaces) { if (annotatedInterface.getAnnotations().length > 0) { throw new IllegalStateException("There are no annotated interfaces in the public API"); } } List<Constructor<?>> declaredConstructors = publicConstructors(publicClass.getDeclaredConstructors()); if (!declaredConstructors.isEmpty()) { throw new IllegalStateException("There are no constructors in the public API"); } Method[] declaredMethods = publicClass.getDeclaredMethods(); if (existProtectedElements(stream(declaredMethods), Method::getModifiers)) { throw new IllegalStateException("There are no protected methods in the public API"); } Field[] declaredFields = publicClass.getDeclaredFields(); if (existProtectedElements(stream(declaredFields), Field::getModifiers)) { throw new IllegalStateException("There are no protected fields in the public API"); } }
@Override public List<T> convertOutput(Stream<T> original, AnnotatedType type, ResolutionEnvironment resolutionEnvironment) { try (Stream<T> stream = original) { return stream .map(item -> resolutionEnvironment.<T, T>convertOutput(item, getElementType(type))) .collect(Collectors.toList()); } }
@Override public Object getArgumentValue(Object input, AnnotatedType type, ResolutionEnvironment resolutionEnvironment) { if (input == null) { return null; } return convertInput(input.toString(), type, resolutionEnvironment.globalEnvironment, resolutionEnvironment.valueMapper); }
@SuppressWarnings("unchecked") private String generateSimpleName(AnnotatedType type) { Optional<String>[] names = new Optional[]{ Optional.ofNullable(type.getAnnotation(GraphQLUnion.class)) .map(GraphQLUnion::name), Optional.ofNullable(type.getAnnotation(GraphQLInterface.class)) .map(GraphQLInterface::name), Optional.ofNullable(type.getAnnotation(GraphQLType.class)) .map(GraphQLType::name) }; return getFirstNonEmptyOrDefault(names, ClassUtils.getRawType(type.getType()).getSimpleName()); }