1616import graphql .language .ObjectTypeDefinition ;
1717import graphql .language .ObjectValue ;
1818import graphql .language .OperationTypeDefinition ;
19+ import graphql .language .ResolvedTypeDefinition ;
1920import graphql .language .ScalarTypeDefinition ;
2021import graphql .language .SchemaDefinition ;
2122import graphql .language .StringValue ;
5354import java .util .Optional ;
5455import java .util .Stack ;
5556
57+ import static graphql .Assert .assertNotNull ;
58+
5659/**
5760 * This can generate a working runtime schema from a type registry and runtime wiring
5861 */
@@ -75,6 +78,10 @@ class BuildContext {
7578 this .wiring = wiring ;
7679 }
7780
81+ public TypeDefinitionRegistry getTypeRegistry () {
82+ return typeRegistry ;
83+ }
84+
7885 @ SuppressWarnings ("OptionalGetWithoutIsPresent" )
7986 TypeDefinition getTypeDefinition (Type type ) {
8087 return typeRegistry .getType (type ).get ();
@@ -220,7 +227,7 @@ private <T extends GraphQLOutputType> T buildOutputType(BuildContext buildCtx, T
220227 outputType = buildUnionType (buildCtx , (UnionTypeDefinition ) typeDefinition );
221228 } else if (typeDefinition instanceof EnumTypeDefinition ) {
222229 outputType = buildEnumType ((EnumTypeDefinition ) typeDefinition );
223- } else if (typeDefinition instanceof ScalarTypeDefinition ){
230+ } else if (typeDefinition instanceof ScalarTypeDefinition ) {
224231 outputType = buildScalar (buildCtx , (ScalarTypeDefinition ) typeDefinition );
225232 } else {
226233 // typeDefinition is not a valid output type
@@ -253,7 +260,7 @@ private GraphQLInputType buildInputType(BuildContext buildCtx, Type rawType) {
253260 inputType = buildInputObjectType (buildCtx , (InputObjectTypeDefinition ) typeDefinition );
254261 } else if (typeDefinition instanceof EnumTypeDefinition ) {
255262 inputType = buildEnumType ((EnumTypeDefinition ) typeDefinition );
256- } else if (typeDefinition instanceof ScalarTypeDefinition ){
263+ } else if (typeDefinition instanceof ScalarTypeDefinition ) {
257264 inputType = buildScalar (buildCtx , (ScalarTypeDefinition ) typeDefinition );
258265 } else {
259266 // typeDefinition is not a valid InputType
@@ -331,7 +338,7 @@ private GraphQLInterfaceType buildInterfaceType(BuildContext buildCtx, Interface
331338 builder .name (typeDefinition .getName ());
332339 builder .description (buildDescription (typeDefinition ));
333340
334- builder .typeResolver (getTypeResolver (buildCtx , typeDefinition . getName () ));
341+ builder .typeResolver (getTypeResolver (buildCtx , typeDefinition ));
335342
336343 typeDefinition .getFieldDefinitions ().forEach (fieldDef ->
337344 builder .field (buildField (buildCtx , typeDefinition , fieldDef )));
@@ -342,11 +349,15 @@ private GraphQLUnionType buildUnionType(BuildContext buildCtx, UnionTypeDefiniti
342349 GraphQLUnionType .Builder builder = GraphQLUnionType .newUnionType ();
343350 builder .name (typeDefinition .getName ());
344351 builder .description (buildDescription (typeDefinition ));
345- builder .typeResolver (getTypeResolver (buildCtx , typeDefinition . getName () ));
352+ builder .typeResolver (getTypeResolver (buildCtx , typeDefinition ));
346353
347354 typeDefinition .getMemberTypes ().forEach (mt -> {
348- GraphQLObjectType objectType = buildOutputType (buildCtx , mt );
349- builder .possibleType (objectType );
355+ GraphQLOutputType outputType = buildOutputType (buildCtx , mt );
356+ if (outputType instanceof GraphQLTypeReference ) {
357+ builder .possibleType ((GraphQLTypeReference ) outputType );
358+ } else {
359+ builder .possibleType ((GraphQLObjectType ) outputType );
360+ }
350361 });
351362 return builder .build ();
352363 }
@@ -381,14 +392,23 @@ private GraphQLFieldDefinition buildField(BuildContext buildCtx, TypeDefinition
381392 }
382393
383394 private DataFetcher buildDataFetcher (BuildContext buildCtx , TypeDefinition parentType , FieldDefinition fieldDef ) {
384- RuntimeWiring wiring = buildCtx .getWiring ();
385395 String fieldName = fieldDef .getName ();
386- DataFetcher dataFetcher = wiring .getDataFetcherForType (parentType .getName ()).get (fieldName );
387- if (dataFetcher == null ) {
388- //
389- // in the future we could support FieldDateFetcher but we would need a way to indicate that in the schema spec
390- // perhaps by a directive
391- dataFetcher = new PropertyDataFetcher (fieldName );
396+ TypeDefinitionRegistry typeRegistry = buildCtx .getTypeRegistry ();
397+ RuntimeWiring wiring = buildCtx .getWiring ();
398+ WiringFactory wiringFactory = wiring .getWiringFactory ();
399+
400+ DataFetcher dataFetcher ;
401+ if (wiringFactory .providesDataFetcher (typeRegistry , fieldDef )) {
402+ dataFetcher = wiringFactory .getDataFetcher (typeRegistry , fieldDef );
403+ assertNotNull (dataFetcher , "The WiringFactory indicated it provides a data fetcher but then returned null" );
404+ } else {
405+ dataFetcher = wiring .getDataFetcherForType (parentType .getName ()).get (fieldName );
406+ if (dataFetcher == null ) {
407+ //
408+ // in the future we could support FieldDateFetcher but we would need a way to indicate that in the schema spec
409+ // perhaps by a directive
410+ dataFetcher = new PropertyDataFetcher (fieldName );
411+ }
392412 }
393413 return dataFetcher ;
394414 }
@@ -454,12 +474,24 @@ private Object buildObjectValue(ObjectValue defaultValue) {
454474 return map ;
455475 }
456476
457- private TypeResolver getTypeResolver (BuildContext buildCtx , String name ) {
458- TypeResolver typeResolver = buildCtx .getWiring ().getTypeResolvers ().get (name );
459- if (typeResolver == null ) {
460- // this really should be checked earlier via a pre-flight check
461- typeResolver = new TypeResolverProxy ();
477+ private TypeResolver getTypeResolver (BuildContext buildCtx , ResolvedTypeDefinition typeDefinition ) {
478+ TypeDefinitionRegistry typeRegistry = buildCtx .getTypeRegistry ();
479+ RuntimeWiring wiring = buildCtx .getWiring ();
480+ WiringFactory wiringFactory = wiring .getWiringFactory ();
481+
482+ TypeResolver typeResolver ;
483+ if (wiringFactory .providesTypeResolver (typeRegistry , typeDefinition )) {
484+ typeResolver = wiringFactory .getTypeResolver (typeRegistry , typeDefinition );
485+ assertNotNull (typeResolver , "The WiringFactory indicated it provides a type resolver but then returned null" );
486+
487+ } else {
488+ typeResolver = wiring .getTypeResolvers ().get (typeDefinition .getName ());
489+ if (typeResolver == null ) {
490+ // this really should be checked earlier via a pre-flight check
491+ typeResolver = new TypeResolverProxy ();
492+ }
462493 }
494+
463495 return typeResolver ;
464496 }
465497
0 commit comments