1
1
package graphql.kickstart.tools
2
2
3
3
import graphql.introspection.Introspection
4
+ import graphql.introspection.Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION
4
5
import graphql.kickstart.tools.directive.DirectiveWiringHelper
5
6
import graphql.kickstart.tools.util.getDocumentation
6
7
import graphql.kickstart.tools.util.getExtendedFieldDefinitions
@@ -122,28 +123,31 @@ class SchemaParser internal constructor(
122
123
.definition(objectDefinition)
123
124
.description(getDocumentation(objectDefinition, options))
124
125
.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
+ }
145
150
}
146
- }
147
151
148
152
return directiveWiringHelper.wireObject(builder.build())
149
153
}
@@ -152,28 +156,33 @@ class SchemaParser internal constructor(
152
156
referencingInputObjects : MutableSet <String >): GraphQLInputObjectType {
153
157
val extensionDefinitions = inputExtensionDefinitions.filter { it.name == definition.name }
154
158
159
+ referencingInputObjects.add(definition.name)
160
+
155
161
val builder = GraphQLInputObjectType .newInputObject()
156
162
.name(definition.name)
157
163
.definition(definition)
158
164
.extensionDefinitions(extensionDefinitions)
159
165
.description(getDocumentation(definition, options))
160
166
.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
+ }
175
185
}
176
- }
177
186
178
187
return directiveWiringHelper.wireInputObject(builder.build())
179
188
}
@@ -189,57 +198,63 @@ class SchemaParser internal constructor(
189
198
.definition(definition)
190
199
.description(getDocumentation(definition, options))
191
200
.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
+ }
210
221
211
222
return directiveWiringHelper.wireEnum(builder.build())
212
223
}
213
224
214
225
private fun createInterfaceObject (interfaceDefinition : InterfaceTypeDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLInterfaceType {
215
- val name = interfaceDefinition.name
216
226
val builder = GraphQLInterfaceType .newInterface()
217
- .name(name)
227
+ .name(interfaceDefinition. name)
218
228
.definition(interfaceDefinition)
219
229
.description(getDocumentation(interfaceDefinition, options))
220
230
.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
+ }
230
243
231
244
return directiveWiringHelper.wireInterFace(builder.build())
232
245
}
233
246
234
247
private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
235
- val name = definition.name
236
248
val builder = GraphQLUnionType .newUnionType()
237
- .name(name)
249
+ .name(definition. name)
238
250
.definition(definition)
239
251
.description(getDocumentation(definition, options))
240
252
.withAppliedDirectives(* buildAppliedDirectives(definition.directives))
253
+ .withDirectives(* buildDirectives(definition.directives, Introspection .DirectiveLocation .UNION ))
254
+ .apply {
255
+ getLeafUnionObjects(definition, types).forEach { possibleType(it) }
256
+ }
241
257
242
- getLeafUnionObjects(definition, types).forEach { builder.possibleType(it) }
243
258
return directiveWiringHelper.wireUnion(builder.build())
244
259
}
245
260
@@ -264,56 +279,50 @@ class SchemaParser internal constructor(
264
279
}
265
280
266
281
private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLFieldDefinition .Builder {
267
- field
282
+ return field
268
283
.name(fieldDefinition.name)
269
284
.description(getDocumentation(fieldDefinition, options))
270
285
.definition(fieldDefinition)
271
286
.apply { getDeprecated(fieldDefinition.directives)?.let { deprecate(it) } }
272
287
.type(determineOutputType(fieldDefinition.type, inputObjects))
273
288
.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
+ }
274
296
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()
289
308
}
290
309
291
310
private fun createDirective (definition : DirectiveDefinition , inputObjects : List <GraphQLInputObjectType >): GraphQLDirective {
292
311
val locations = definition.directiveLocations.map { Introspection .DirectiveLocation .valueOf(it.name) }.toTypedArray()
293
312
294
- val graphQLDirective = GraphQLDirective .newDirective()
313
+ return GraphQLDirective .newDirective()
295
314
.name(definition.name)
296
315
.description(getDocumentation(definition, options))
297
316
.definition(definition)
298
317
.comparatorRegistry(runtimeWiring.comparatorRegistry)
299
318
.validLocations(* locations)
300
319
.repeatable(definition.isRepeatable)
301
320
.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))
312
323
}
313
324
}
314
325
.build()
315
-
316
- return graphQLDirective
317
326
}
318
327
319
328
private fun buildAppliedDirectives (directives : List <Directive >): Array <GraphQLAppliedDirective > {
@@ -328,17 +337,31 @@ class SchemaParser internal constructor(
328
337
.name(arg.name)
329
338
.type(directiveWiringHelper.buildDirectiveInputType(arg.value))
330
339
.valueLiteral(arg.value)
331
- .build())
340
+ .build()
341
+ )
332
342
}
333
343
}
334
344
.build()
335
345
}.toTypedArray()
336
346
}
337
347
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
+
338
356
private fun determineOutputType (typeDefinition : Type <* >, inputObjects : List <GraphQLInputObjectType >) =
339
357
determineType(GraphQLOutputType ::class , typeDefinition, permittedTypesForObject, inputObjects) as GraphQLOutputType
340
358
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 =
342
365
when (typeDefinition) {
343
366
is ListType -> GraphQLList (determineType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects))
344
367
is NonNullType -> GraphQLNonNull (determineType(expectedType, typeDefinition.type, allowedTypeReferences, inputObjects))
0 commit comments