11package graphql.kickstart.tools
22
3- import graphql.Scalars
43import graphql.introspection.Introspection
5- import graphql.kickstart.tools.directive.SchemaGeneratorDirectiveHelper
4+ import graphql.kickstart.tools.directive.DirectiveWiringHelper
65import graphql.kickstart.tools.util.getDocumentation
76import graphql.kickstart.tools.util.getExtendedFieldDefinitions
87import graphql.kickstart.tools.util.unwrap
@@ -57,9 +56,7 @@ class SchemaParser internal constructor(
5756 (inputObjectDefinitions.map { it.name } + enumDefinitions.map { it.name }).toSet()
5857
5958 private val codeRegistryBuilder = GraphQLCodeRegistry .newCodeRegistry()
60-
61- private val schemaGeneratorDirectiveHelper = SchemaGeneratorDirectiveHelper ()
62- private val schemaDirectiveParameters = SchemaGeneratorDirectiveHelper .Parameters (null , runtimeWiring, null , codeRegistryBuilder)
59+ private val directiveWiringHelper = DirectiveWiringHelper (options, runtimeWiring, codeRegistryBuilder, directiveDefinitions)
6360
6461 /* *
6562 * Parses the given schema with respect to the given dictionary and returns GraphQL objects.
@@ -124,9 +121,7 @@ class SchemaParser internal constructor(
124121 .name(name)
125122 .definition(objectDefinition)
126123 .description(getDocumentation(objectDefinition, options))
127-
128- builder.withDirectives(* buildDirectives(objectDefinition.directives, Introspection .DirectiveLocation .OBJECT ))
129- builder.withAppliedDirectives(* buildAppliedDirectives(objectDefinition.directives))
124+ .withAppliedDirectives(* buildAppliedDirectives(objectDefinition.directives))
130125
131126 objectDefinition.implements.forEach { implementsDefinition ->
132127 val interfaceName = (implementsDefinition as TypeName ).name
@@ -150,10 +145,7 @@ class SchemaParser internal constructor(
150145 }
151146 }
152147
153- val objectType = builder.build()
154- val directiveHelperParameters = SchemaGeneratorDirectiveHelper .Parameters (null , runtimeWiring, null , codeRegistryBuilder)
155-
156- return schemaGeneratorDirectiveHelper.onObject(objectType, directiveHelperParameters)
148+ return directiveWiringHelper.wireObject(builder.build())
157149 }
158150
159151 private fun createInputObject (definition : InputObjectTypeDefinition , inputObjects : List <GraphQLInputObjectType >,
@@ -165,9 +157,7 @@ class SchemaParser internal constructor(
165157 .definition(definition)
166158 .extensionDefinitions(extensionDefinitions)
167159 .description(getDocumentation(definition, options))
168-
169- builder.withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .INPUT_OBJECT ))
170- builder.withAppliedDirectives(* buildAppliedDirectives(definition.directives))
160+ .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
171161
172162 referencingInputObjects.add(definition.name)
173163
@@ -179,13 +169,12 @@ class SchemaParser internal constructor(
179169 .description(getDocumentation(inputDefinition, options))
180170 .apply { inputDefinition.defaultValue?.let { v -> defaultValueLiteral(v) } }
181171 .type(determineInputType(inputDefinition.type, inputObjects, referencingInputObjects))
182- .withDirectives(* buildDirectives(inputDefinition.directives, Introspection .DirectiveLocation .INPUT_FIELD_DEFINITION ))
183172 .withAppliedDirectives(* buildAppliedDirectives(inputDefinition.directives))
184173 builder.field(fieldBuilder.build())
185174 }
186175 }
187176
188- return schemaGeneratorDirectiveHelper.onInputObjectType (builder.build(), schemaDirectiveParameters )
177+ return directiveWiringHelper.wireInputObject (builder.build())
189178 }
190179
191180 private fun createEnumObject (definition : EnumTypeDefinition ): GraphQLEnumType {
@@ -198,24 +187,20 @@ class SchemaParser internal constructor(
198187 .name(name)
199188 .definition(definition)
200189 .description(getDocumentation(definition, options))
201-
202- builder.withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .ENUM ))
203- builder.withAppliedDirectives(* buildAppliedDirectives(definition.directives))
190+ .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
204191
205192 definition.enumValueDefinitions.forEach { enumDefinition ->
206193 val enumName = enumDefinition.name
207194 val enumValue = type.unwrap().enumConstants.find { (it as Enum <* >).name == enumName }
208195 ? : throw SchemaError (" Expected value for name '$enumName ' in enum '${type.unwrap().simpleName} ' but found none!" )
209196
210- val enumValueDirectives = buildDirectives(enumDefinition.directives, Introspection .DirectiveLocation .ENUM_VALUE )
211197 val enumValueAppliedDirectives = buildAppliedDirectives(enumDefinition.directives)
212198 getDeprecated(enumDefinition.directives).let {
213199 val enumValueDefinition = GraphQLEnumValueDefinition .newEnumValueDefinition()
214200 .name(enumName)
215201 .description(getDocumentation(enumDefinition, options))
216202 .value(enumValue)
217203 .deprecationReason(it)
218- .withDirectives(* enumValueDirectives)
219204 .withAppliedDirectives(* enumValueAppliedDirectives)
220205 .definition(enumDefinition)
221206 .build()
@@ -224,7 +209,7 @@ class SchemaParser internal constructor(
224209 }
225210 }
226211
227- return schemaGeneratorDirectiveHelper.onEnum (builder.build(), schemaDirectiveParameters )
212+ return directiveWiringHelper.wireEnum (builder.build())
228213 }
229214
230215 private fun createInterfaceObject (interfaceDefinition : InterfaceTypeDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLInterfaceType {
@@ -233,9 +218,7 @@ class SchemaParser internal constructor(
233218 .name(name)
234219 .definition(interfaceDefinition)
235220 .description(getDocumentation(interfaceDefinition, options))
236-
237- builder.withDirectives(* buildDirectives(interfaceDefinition.directives, Introspection .DirectiveLocation .INTERFACE ))
238- builder.withAppliedDirectives(* buildAppliedDirectives(interfaceDefinition.directives))
221+ .withAppliedDirectives(* buildAppliedDirectives(interfaceDefinition.directives))
239222
240223 interfaceDefinition.fieldDefinitions.forEach { fieldDefinition ->
241224 builder.field { field -> createField(field, fieldDefinition, inputObjects) }
@@ -246,7 +229,7 @@ class SchemaParser internal constructor(
246229 builder.withInterface(GraphQLTypeReference (interfaceName))
247230 }
248231
249- return schemaGeneratorDirectiveHelper.onInterface (builder.build(), schemaDirectiveParameters )
232+ return directiveWiringHelper.wireInterFace (builder.build())
250233 }
251234
252235 private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
@@ -255,12 +238,10 @@ class SchemaParser internal constructor(
255238 .name(name)
256239 .definition(definition)
257240 .description(getDocumentation(definition, options))
258-
259- builder.withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .UNION ))
260- builder.withAppliedDirectives(* buildAppliedDirectives(definition.directives))
241+ .withAppliedDirectives(* buildAppliedDirectives(definition.directives))
261242
262243 getLeafUnionObjects(definition, types).forEach { builder.possibleType(it) }
263- return schemaGeneratorDirectiveHelper.onUnion (builder.build(), schemaDirectiveParameters )
244+ return directiveWiringHelper.wireUnion (builder.build())
264245 }
265246
266247 private fun getLeafUnionObjects (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): List <GraphQLObjectType > {
@@ -290,6 +271,7 @@ class SchemaParser internal constructor(
290271 .definition(fieldDefinition)
291272 .apply { getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
292273 .type(determineOutputType(fieldDefinition.type, inputObjects))
274+ .withAppliedDirectives(* buildAppliedDirectives(fieldDefinition.directives))
293275
294276 fieldDefinition.inputValueDefinitions.forEach { argumentDefinition ->
295277 val argumentBuilder = GraphQLArgument .newArgument()
@@ -298,13 +280,10 @@ class SchemaParser internal constructor(
298280 .description(getDocumentation(argumentDefinition, options))
299281 .type(determineInputType(argumentDefinition.type, inputObjects, setOf ()))
300282 .apply { argumentDefinition.defaultValue?.let { defaultValueLiteral(it) } }
301- .withDirectives(* buildDirectives(argumentDefinition.directives, Introspection .DirectiveLocation .ARGUMENT_DEFINITION ))
302283 .withAppliedDirectives(* buildAppliedDirectives(argumentDefinition.directives))
303284
304285 field.argument(argumentBuilder.build())
305286 }
306- field.withDirectives(* buildDirectives(fieldDefinition.directives, Introspection .DirectiveLocation .FIELD_DEFINITION ))
307- field.withAppliedDirectives(* buildAppliedDirectives(fieldDefinition.directives))
308287
309288 return field
310289 }
@@ -327,7 +306,6 @@ class SchemaParser internal constructor(
327306 .description(getDocumentation(arg, options))
328307 .type(determineInputType(arg.type, inputObjects, setOf ()))
329308 .apply { arg.defaultValue?.let { defaultValueLiteral(it) } }
330- .withDirectives(* buildDirectives(arg.directives, Introspection .DirectiveLocation .ARGUMENT_DEFINITION ))
331309 .withAppliedDirectives(* buildAppliedDirectives(arg.directives))
332310 .build())
333311 }
@@ -337,102 +315,23 @@ class SchemaParser internal constructor(
337315 return graphQLDirective
338316 }
339317
340- private fun buildDirectives (directives : List <Directive >, directiveLocation : Introspection .DirectiveLocation ): Array <GraphQLDirective > {
341- val names = mutableSetOf<String >()
342-
343- val output = mutableListOf<GraphQLDirective >()
344- for (directive in directives) {
345- if (! names.contains(directive.name)) {
346- names.add(directive.name)
347- val graphQLDirective = GraphQLDirective .newDirective()
348- .name(directive.name)
349- .description(getDocumentation(directive, options))
350- .comparatorRegistry(runtimeWiring.comparatorRegistry)
351- .validLocation(directiveLocation)
352- .apply {
353- directive.arguments.forEach { arg ->
354- argument(GraphQLArgument .newArgument()
355- .name(arg.name)
356- .type(buildDirectiveInputType(arg.value))
357- .valueLiteral(arg.value)
358- .build())
359- }
360- }
361- .build()
362-
363- output.add(graphQLDirective)
364- }
365- }
366-
367- return output.toTypedArray()
368- }
369-
370318 private fun buildAppliedDirectives (directives : List <Directive >): Array <GraphQLAppliedDirective > {
371- val names = mutableSetOf<String >()
372-
373- val output = mutableListOf<GraphQLAppliedDirective >()
374- for (directive in directives) {
375- if (! names.contains(directive.name)) {
376- names.add(directive.name)
377- val graphQLDirective = GraphQLAppliedDirective .newDirective()
378- .name(directive.name)
379- .description(getDocumentation(directive, options))
380- .comparatorRegistry(runtimeWiring.comparatorRegistry)
381- .apply {
382- directive.arguments.forEach { arg ->
383- argument(GraphQLAppliedDirectiveArgument .newArgument()
384- .name(arg.name)
385- .type(buildDirectiveInputType(arg.value))
386- .valueLiteral(arg.value)
387- .build())
388- }
319+ return directives.map {
320+ GraphQLAppliedDirective .newDirective()
321+ .name(it.name)
322+ .description(getDocumentation(it, options))
323+ .comparatorRegistry(runtimeWiring.comparatorRegistry)
324+ .apply {
325+ it.arguments.forEach { arg ->
326+ argument(GraphQLAppliedDirectiveArgument .newArgument()
327+ .name(arg.name)
328+ .type(directiveWiringHelper.buildDirectiveInputType(arg.value))
329+ .valueLiteral(arg.value)
330+ .build())
389331 }
390- .build()
391-
392- output.add(graphQLDirective)
393- }
394- }
395-
396- return output.toTypedArray()
397- }
398-
399- private fun buildDirectiveInputType (value : Value <* >): GraphQLInputType ? {
400- return when (value) {
401- is NullValue -> Scalars .GraphQLString
402- is FloatValue -> Scalars .GraphQLFloat
403- is StringValue -> Scalars .GraphQLString
404- is IntValue -> Scalars .GraphQLInt
405- is BooleanValue -> Scalars .GraphQLBoolean
406- is ArrayValue -> GraphQLList .list(buildDirectiveInputType(getArrayValueWrappedType(value)))
407- else -> throw SchemaError (" Directive values of type '${value::class .simpleName} ' are not supported yet." )
408- }
409- }
410-
411- private fun getArrayValueWrappedType (value : ArrayValue ): Value <* > {
412- // empty array [] is equivalent to [null]
413- if (value.values.isEmpty()) {
414- return NullValue .newNullValue().build()
415- }
416-
417- // get rid of null values
418- val nonNullValueList = value.values.filter { v -> v !is NullValue }
419-
420- // [null, null, ...] unwrapped is null
421- if (nonNullValueList.isEmpty()) {
422- return NullValue .newNullValue().build()
423- }
424-
425- // make sure the array isn't polymorphic
426- val distinctTypes = nonNullValueList
427- .map { it::class .java }
428- .distinct()
429-
430- if (distinctTypes.size > 1 ) {
431- throw SchemaError (" Arrays containing multiple types of values are not supported yet." )
432- }
433-
434- // peek at first value, value exists and is assured to be non-null
435- return nonNullValueList[0 ]
332+ }
333+ .build()
334+ }.toTypedArray()
436335 }
437336
438337 private fun determineOutputType (typeDefinition : Type <* >, inputObjects : List <GraphQLInputObjectType >) =
0 commit comments