11package graphql.kickstart.tools
22
33import graphql.introspection.Introspection
4+ import graphql.introspection.Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION
45import graphql.kickstart.tools.directive.DirectiveWiringHelper
56import graphql.kickstart.tools.util.getDocumentation
67import graphql.kickstart.tools.util.getExtendedFieldDefinitions
@@ -122,28 +123,31 @@ class SchemaParser internal constructor(
122123 .definition(objectDefinition)
123124 .description(getDocumentation(objectDefinition, options))
124125 .withAppliedDirectives(* buildAppliedDirectives(objectDefinition.directives))
125-
126- objectDefinition.implements.forEach { implementsDefinition ->
127- val interfaceName = (implementsDefinition as TypeName ).name
128- builder.withInterface(interfaces.find { it.name == interfaceName }
129- ? : throw SchemaError (" Expected interface type with name '$interfaceName ' but found none!" ))
130- }
131-
132- objectDefinition.getExtendedFieldDefinitions(extensionDefinitions).forEach { fieldDefinition ->
133- builder.field { field ->
134- createField(field, fieldDefinition, inputObjects)
135- codeRegistryBuilder.dataFetcher(
136- FieldCoordinates .coordinates(objectDefinition.name, fieldDefinition.name),
137- fieldResolversByType[objectDefinition]?.get(fieldDefinition)?.createDataFetcher()
138- ? : throw SchemaError (" No resolver method found for object type '${objectDefinition.name} ' and field '${fieldDefinition.name} ', this is most likely a bug with graphql-java-tools" )
139- )
140-
141- val wiredField = field.build()
142- GraphQLFieldDefinition .Builder (wiredField)
143- .clearArguments()
144- .arguments(wiredField.arguments)
126+ .withDirectives(* buildDirectives(objectDefinition.directives, Introspection .DirectiveLocation .OBJECT ))
127+ .apply {
128+ objectDefinition.implements.forEach { implementsDefinition ->
129+ val interfaceName = (implementsDefinition as TypeName ).name
130+ withInterface(interfaces.find { it.name == interfaceName }
131+ ? : throw SchemaError (" Expected interface type with name '$interfaceName ' but found none!" ))
132+ }
133+ }
134+ .apply {
135+ objectDefinition.getExtendedFieldDefinitions(extensionDefinitions).forEach { fieldDefinition ->
136+ field { field ->
137+ createField(field, fieldDefinition, inputObjects)
138+ codeRegistryBuilder.dataFetcher(
139+ FieldCoordinates .coordinates(objectDefinition.name, fieldDefinition.name),
140+ fieldResolversByType[objectDefinition]?.get(fieldDefinition)?.createDataFetcher()
141+ ? : throw SchemaError (" No resolver method found for object type '${objectDefinition.name} ' and field '${fieldDefinition.name} ', this is most likely a bug with graphql-java-tools" )
142+ )
143+
144+ val wiredField = field.build()
145+ GraphQLFieldDefinition .Builder (wiredField)
146+ .clearArguments()
147+ .arguments(wiredField.arguments)
148+ }
149+ }
145150 }
146- }
147151
148152 return directiveWiringHelper.wireObject(builder.build())
149153 }
@@ -152,28 +156,33 @@ class SchemaParser internal constructor(
152156 referencingInputObjects : MutableSet <String >): GraphQLInputObjectType {
153157 val extensionDefinitions = inputExtensionDefinitions.filter { it.name == definition.name }
154158
159+ referencingInputObjects.add(definition.name)
160+
155161 val builder = GraphQLInputObjectType .newInputObject()
156162 .name(definition.name)
157163 .definition(definition)
158164 .extensionDefinitions(extensionDefinitions)
159165 .description(getDocumentation(definition, options))
160166 .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
161-
162- referencingInputObjects.add(definition.name)
163-
164- (extensionDefinitions + definition).forEach {
165- it.inputValueDefinitions.forEach { inputDefinition ->
166- val fieldBuilder = GraphQLInputObjectField .newInputObjectField()
167- .name(inputDefinition.name)
168- .definition(inputDefinition)
169- .description(getDocumentation(inputDefinition, options))
170- .apply { inputDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
171- .apply { getDeprecated(inputDefinition.directives)?.let { deprecate(it) } }
172- .type(determineInputType(inputDefinition.type, inputObjects, referencingInputObjects))
173- .withAppliedDirectives(* buildAppliedDirectives(inputDefinition.directives))
174- builder.field(fieldBuilder.build())
167+ .withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .INPUT_OBJECT ))
168+ .apply {
169+ (extensionDefinitions + definition).forEach { typeDefinition ->
170+ typeDefinition.inputValueDefinitions.forEach { fieldDefinition ->
171+ field(
172+ GraphQLInputObjectField .newInputObjectField()
173+ .name(fieldDefinition.name)
174+ .definition(fieldDefinition)
175+ .description(getDocumentation(fieldDefinition, options))
176+ .apply { fieldDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
177+ .apply { getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
178+ .type(determineInputType(fieldDefinition.type, inputObjects, referencingInputObjects))
179+ .withAppliedDirectives(* buildAppliedDirectives(fieldDefinition.directives))
180+ .withDirectives(* buildDirectives(definition.directives, INPUT_FIELD_DEFINITION ))
181+ .build()
182+ )
183+ }
184+ }
175185 }
176- }
177186
178187 return directiveWiringHelper.wireInputObject(builder.build())
179188 }
@@ -189,57 +198,63 @@ class SchemaParser internal constructor(
189198 .definition(definition)
190199 .description(getDocumentation(definition, options))
191200 .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
192-
193- definition.enumValueDefinitions.forEach { enumDefinition ->
194- val enumName = enumDefinition.name
195- val enumValue = type.unwrap().enumConstants.find { (it as Enum <* >).name == enumName }
196- ? : throw SchemaError (" Expected value for name '$enumName ' in enum '${type.unwrap().simpleName} ' but found none!" )
197-
198- val enumValueAppliedDirectives = buildAppliedDirectives(enumDefinition.directives)
199- val enumValueDefinition = GraphQLEnumValueDefinition .newEnumValueDefinition()
200- .name(enumName)
201- .description(getDocumentation(enumDefinition, options))
202- .value(enumValue)
203- .apply { getDeprecated(enumDefinition.directives)?.let { deprecationReason(it) } }
204- .withAppliedDirectives(* enumValueAppliedDirectives)
205- .definition(enumDefinition)
206- .build()
207-
208- builder.value(enumValueDefinition)
209- }
201+ .withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .ENUM ))
202+ .apply {
203+ definition.enumValueDefinitions.forEach { valueDefinition ->
204+ val enumName = valueDefinition.name
205+ val enumValue = type.unwrap().enumConstants.find { (it as Enum <* >).name == enumName }
206+ ? : throw SchemaError (" Expected value for name '$enumName ' in enum '${type.unwrap().simpleName} ' but found none!" )
207+
208+ value(
209+ GraphQLEnumValueDefinition .newEnumValueDefinition()
210+ .name(enumName)
211+ .description(getDocumentation(valueDefinition, options))
212+ .value(enumValue)
213+ .apply { getDeprecated(valueDefinition.directives)?.let { deprecationReason(it) } }
214+ .withAppliedDirectives(* buildAppliedDirectives(valueDefinition.directives))
215+ .withDirectives(* buildDirectives(valueDefinition.directives, Introspection .DirectiveLocation .ENUM_VALUE ))
216+ .definition(valueDefinition)
217+ .build()
218+ )
219+ }
220+ }
210221
211222 return directiveWiringHelper.wireEnum(builder.build())
212223 }
213224
214225 private fun createInterfaceObject (interfaceDefinition : InterfaceTypeDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLInterfaceType {
215- val name = interfaceDefinition.name
216226 val builder = GraphQLInterfaceType .newInterface()
217- .name(name)
227+ .name(interfaceDefinition. name)
218228 .definition(interfaceDefinition)
219229 .description(getDocumentation(interfaceDefinition, options))
220230 .withAppliedDirectives(* buildAppliedDirectives(interfaceDefinition.directives))
221-
222- interfaceDefinition.fieldDefinitions.forEach { fieldDefinition ->
223- builder.field { field -> createField(field, fieldDefinition, inputObjects) }
224- }
225-
226- interfaceDefinition.implements.forEach { implementsDefinition ->
227- val interfaceName = (implementsDefinition as TypeName ).name
228- builder.withInterface(GraphQLTypeReference (interfaceName))
229- }
231+ .withDirectives(* buildDirectives(interfaceDefinition.directives, Introspection .DirectiveLocation .INTERFACE ))
232+ .apply {
233+ interfaceDefinition.fieldDefinitions.forEach { fieldDefinition ->
234+ field { field -> createField(field, fieldDefinition, inputObjects) }
235+ }
236+ }
237+ .apply {
238+ interfaceDefinition.implements.forEach { implementsDefinition ->
239+ val interfaceName = (implementsDefinition as TypeName ).name
240+ withInterface(GraphQLTypeReference (interfaceName))
241+ }
242+ }
230243
231244 return directiveWiringHelper.wireInterFace(builder.build())
232245 }
233246
234247 private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
235- val name = definition.name
236248 val builder = GraphQLUnionType .newUnionType()
237- .name(name)
249+ .name(definition. name)
238250 .definition(definition)
239251 .description(getDocumentation(definition, options))
240252 .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
253+ .withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .UNION ))
254+ .apply {
255+ getLeafUnionObjects(definition, types).forEach { possibleType(it) }
256+ }
241257
242- getLeafUnionObjects(definition, types).forEach { builder.possibleType(it) }
243258 return directiveWiringHelper.wireUnion(builder.build())
244259 }
245260
@@ -264,56 +279,50 @@ class SchemaParser internal constructor(
264279 }
265280
266281 private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLFieldDefinition .Builder {
267- field
282+ return field
268283 .name(fieldDefinition.name)
269284 .description(getDocumentation(fieldDefinition, options))
270285 .definition(fieldDefinition)
271286 .apply { getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
272287 .type(determineOutputType(fieldDefinition.type, inputObjects))
273288 .withAppliedDirectives(* buildAppliedDirectives(fieldDefinition.directives))
289+ .withDirectives(* buildDirectives(fieldDefinition.directives, Introspection .DirectiveLocation .FIELD_DEFINITION ))
290+ .apply {
291+ fieldDefinition.inputValueDefinitions.forEach { argumentDefinition ->
292+ argument(createArgument(argumentDefinition, inputObjects))
293+ }
294+ }
295+ }
274296
275- fieldDefinition.inputValueDefinitions.forEach { argumentDefinition ->
276- val argumentBuilder = GraphQLArgument .newArgument()
277- .name(argumentDefinition.name)
278- .definition(argumentDefinition)
279- .description(getDocumentation(argumentDefinition, options))
280- .type(determineInputType(argumentDefinition.type, inputObjects, setOf ()))
281- .apply { getDeprecated(argumentDefinition.directives)?.let { deprecate(it) } }
282- .apply { argumentDefinition.defaultValue?.let { defaultValueLiteral(it) } }
283- .withAppliedDirectives(* buildAppliedDirectives(argumentDefinition.directives))
284-
285- field.argument(argumentBuilder.build())
286- }
287-
288- return field
297+ private fun createArgument (definition : InputValueDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLArgument {
298+ return GraphQLArgument .newArgument()
299+ .name(definition.name)
300+ .definition(definition)
301+ .description(getDocumentation(definition, options))
302+ .type(determineInputType(definition.type, inputObjects, setOf ()))
303+ .apply { getDeprecated(definition.directives)?.let { deprecate(it) } }
304+ .apply { definition.defaultValue?.let { defaultValueLiteral(it) } }
305+ .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
306+ .withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .ARGUMENT_DEFINITION ))
307+ .build()
289308 }
290309
291310 private fun createDirective (definition : DirectiveDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLDirective {
292311 val locations = definition.directiveLocations.map { Introspection .DirectiveLocation .valueOf(it.name) }.toTypedArray()
293312
294- val graphQLDirective = GraphQLDirective .newDirective()
313+ return GraphQLDirective .newDirective()
295314 .name(definition.name)
296315 .description(getDocumentation(definition, options))
297316 .definition(definition)
298317 .comparatorRegistry(runtimeWiring.comparatorRegistry)
299318 .validLocations(* locations)
300319 .repeatable(definition.isRepeatable)
301320 .apply {
302- definition.inputValueDefinitions.forEach { arg ->
303- argument(GraphQLArgument .newArgument()
304- .name(arg.name)
305- .definition(arg)
306- .description(getDocumentation(arg, options))
307- .type(determineInputType(arg.type, inputObjects, setOf ()))
308- .apply { getDeprecated(arg.directives)?.let { deprecate(it) } }
309- .apply { arg.defaultValue?.let { defaultValueLiteral(it) } }
310- .withAppliedDirectives(* buildAppliedDirectives(arg.directives))
311- .build())
321+ definition.inputValueDefinitions.forEach { argumentDefinition ->
322+ argument(createArgument(argumentDefinition, inputObjects))
312323 }
313324 }
314325 .build()
315-
316- return graphQLDirective
317326 }
318327
319328 private fun buildAppliedDirectives (directives : List <Directive >): Array <GraphQLAppliedDirective > {
@@ -328,17 +337,31 @@ class SchemaParser internal constructor(
328337 .name(arg.name)
329338 .type(directiveWiringHelper.buildDirectiveInputType(arg.value))
330339 .valueLiteral(arg.value)
331- .build())
340+ .build()
341+ )
332342 }
333343 }
334344 .build()
335345 }.toTypedArray()
336346 }
337347
348+ // TODO remove this once directives are fully replaced with applied directives
349+ private fun buildDirectives (
350+ directives : List <Directive >,
351+ directiveLocation : Introspection .DirectiveLocation
352+ ): Array <GraphQLDirective > {
353+ return directiveWiringHelper.buildDirectives(directives, directiveLocation).toTypedArray()
354+ }
355+
338356 private fun determineOutputType (typeDefinition : Type <* >, inputObjects : List <GraphQLInputObjectType >) =
339357 determineType(GraphQLOutputType ::class , typeDefinition, permittedTypesForObject, inputObjects) as GraphQLOutputType
340358
341- private fun <T : Any > determineType (expectedType : KClass <T >, typeDefinition : Type <* >, allowedTypeReferences : Set <String >, inputObjects : List <GraphQLInputObjectType >): GraphQLType =
359+ private fun <T : Any > determineType (
360+ expectedType : KClass <T >,
361+ typeDefinition : Type <* >,
362+ allowedTypeReferences : Set <String >,
363+ inputObjects : List <GraphQLInputObjectType >
364+ ): GraphQLType =
342365 when (typeDefinition) {
343366 is ListType -> GraphQLList (determineType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects))
344367 is NonNullType -> GraphQLNonNull (determineType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects))
0 commit comments