1919import graphql .annotations .annotationTypes .GraphQLType ;
2020import graphql .annotations .annotationTypes .GraphQLUnion ;
2121import graphql .annotations .processor .ProcessingElementsContainer ;
22- import graphql .annotations .processor .util .ReflectionKit ;
2322import graphql .annotations .processor .exceptions .GraphQLAnnotationsException ;
24- import graphql .annotations .processor .typeFunctions .TypeFunction ;
2523import graphql .annotations .processor .retrievers .GraphQLObjectInfoRetriever ;
24+ import graphql .annotations .processor .typeFunctions .TypeFunction ;
2625import graphql .annotations .typeResolvers .UnionTypeResolver ;
2726import graphql .schema .GraphQLObjectType ;
28- import graphql .schema .GraphQLUnionType ;
27+ import graphql .schema .GraphQLUnionType .Builder ;
28+ import graphql .schema .TypeResolver ;
2929
30+ import java .lang .reflect .Constructor ;
3031import java .util .Arrays ;
31- import java .util .function . Function ;
32+ import java .util .Optional ;
3233
34+ import static graphql .annotations .processor .util .ReflectionKit .constructNewInstance ;
35+ import static graphql .annotations .processor .util .ReflectionKit .newInstance ;
3336import static graphql .schema .GraphQLUnionType .newUnionType ;
3437
3538public class UnionBuilder {
@@ -41,18 +44,18 @@ public UnionBuilder(GraphQLObjectInfoRetriever graphQLObjectInfoRetriever) {
4144 }
4245
4346 /**
44- * This will examine the class and return a {@link GraphQLUnionType. Builder} ready for further definition
47+ * This will examine the class and return a {@link Builder} ready for further definition
4548 * @param container a class that hold several members that are required in order to build schema
4649 * @param iface interface to examine
47- * @return a {@link GraphQLUnionType. Builder}
50+ * @return a {@link Builder}
4851 * @throws GraphQLAnnotationsException if the class cannot be examined
4952 */
5053
51- public GraphQLUnionType . Builder getUnionBuilder (Class <?> iface , ProcessingElementsContainer container ) throws GraphQLAnnotationsException , IllegalArgumentException {
54+ public Builder getUnionBuilder (Class <?> iface , ProcessingElementsContainer container ) throws GraphQLAnnotationsException , IllegalArgumentException {
5255 if (!iface .isInterface ()) {
5356 throw new IllegalArgumentException (iface + " is not an interface" );
5457 }
55- GraphQLUnionType . Builder builder = newUnionType ();
58+ Builder builder = newUnionType ();
5659
5760 GraphQLUnion unionAnnotation = iface .getAnnotation (GraphQLUnion .class );
5861 builder .name (graphQLObjectInfoRetriever .getTypeName (iface ));
@@ -65,21 +68,41 @@ public GraphQLUnionType.Builder getUnionBuilder(Class<?> iface, ProcessingElemen
6568 TypeFunction typeFunction = container .getDefaultTypeFunction ();
6669
6770 if (typeAnnotation != null ) {
68- typeFunction = ReflectionKit . newInstance (typeAnnotation .value ());
71+ typeFunction = newInstance (typeAnnotation .value ());
6972 }
7073
7174 TypeFunction finalTypeFunction = typeFunction ;
72- Arrays .asList (unionAnnotation .possibleTypes ()).stream ()
73- .map (new Function <Class <?>, graphql .schema .GraphQLType >() {
74- @ Override
75- public graphql .schema .GraphQLType apply (Class <?> aClass ) {
76- return finalTypeFunction .buildType (aClass , null , container );
77- }
78- })
75+ Arrays .stream (unionAnnotation .possibleTypes ())
76+ .map (aClass -> finalTypeFunction .buildType (aClass , null , container ))
7977 .map (v -> (GraphQLObjectType ) v )
8078 .forEach (builder ::possibleType );
8179
82- builder .typeResolver (new UnionTypeResolver (unionAnnotation .possibleTypes (), container ));
80+ TypeResolver typeResolver = getTypeResolver (container , unionAnnotation );
81+
82+ builder .typeResolver (typeResolver );
8383 return builder ;
8484 }
85+
86+ private TypeResolver getTypeResolver (ProcessingElementsContainer container , GraphQLUnion unionAnnotation ) {
87+ Optional <Constructor <?>> typeResolverConstructorOptional = Arrays .stream (unionAnnotation .typeResolver ().getConstructors ())
88+ .filter (constructor -> constructor .getParameterCount () == 0 || constructorHasPossibleTypesAndContainerAsParameters (container , constructor ))
89+ .findFirst ();
90+
91+ return typeResolverConstructorOptional
92+ .map (constructor -> {
93+ if (constructor .getParameterCount () == 0 ) {
94+ return (TypeResolver ) constructNewInstance (constructor );
95+ }
96+ else {
97+ return (TypeResolver ) constructNewInstance (constructor , unionAnnotation .possibleTypes (), container );
98+ }
99+ })
100+ .orElseGet (() -> new UnionTypeResolver (unionAnnotation .possibleTypes (), container ));
101+ }
102+
103+ private boolean constructorHasPossibleTypesAndContainerAsParameters (ProcessingElementsContainer container , Constructor <?> constructor ) {
104+ return constructor .getParameterCount () == 2 &&
105+ Class [].class .isAssignableFrom (constructor .getParameterTypes ()[0 ]) &&
106+ container .getClass ().isAssignableFrom (constructor .getParameterTypes ()[1 ]);
107+ }
85108}
0 commit comments