@@ -23,9 +23,12 @@ import graphql.language.TypeDefinition
2323import graphql.language.TypeName
2424import graphql.language.UnionTypeDefinition
2525import graphql.language.Value
26+ import graphql.schema.GraphQLArgument
2627import graphql.schema.GraphQLDirective
2728import graphql.schema.GraphQLEnumType
29+ import graphql.schema.GraphQLEnumValueDefinition
2830import graphql.schema.GraphQLFieldDefinition
31+ import graphql.schema.GraphQLInputObjectField
2932import graphql.schema.GraphQLInputObjectType
3033import graphql.schema.GraphQLInputType
3134import graphql.schema.GraphQLInterfaceType
@@ -42,8 +45,7 @@ import graphql.schema.idl.DirectiveBehavior
4245import graphql.schema.idl.RuntimeWiring
4346import graphql.schema.idl.ScalarInfo
4447import graphql.schema.idl.SchemaGeneratorHelper
45- import java.util.ArrayList
46- import java.util.HashSet
48+ import java.util.*
4749import kotlin.reflect.KClass
4850
4951/* *
@@ -56,9 +58,11 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
5658 companion object {
5759 const val DEFAULT_DEPRECATION_MESSAGE = " No longer supported"
5860
59- @JvmStatic fun newParser () = SchemaParserBuilder ()
61+ @JvmStatic
62+ fun newParser () = SchemaParserBuilder ()
63+
6064 internal fun getDocumentation (node : AbstractNode <* >): String? = node.comments?.asSequence()
61- ?.filter {! it.content.startsWith(" #" )}
65+ ?.filter { ! it.content.startsWith(" #" ) }
6266 ?.joinToString(" \n " ) { it.content.trimEnd() }
6367 ?.trimIndent()
6468 }
@@ -110,9 +114,12 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
110114 val mutationName = rootInfo.getMutationName()
111115 val subscriptionName = rootInfo.getSubscriptionName()
112116
113- val query = objects.find { it.name == queryName } ? : throw SchemaError (" Expected a Query object with name '$queryName ' but found none!" )
114- val mutation = objects.find { it.name == mutationName } ? : if (rootInfo.isMutationRequired()) throw SchemaError (" Expected a Mutation object with name '$mutationName ' but found none!" ) else null
115- val subscription = objects.find { it.name == subscriptionName } ? : if (rootInfo.isSubscriptionRequired()) throw SchemaError (" Expected a Subscription object with name '$subscriptionName ' but found none!" ) else null
117+ val query = objects.find { it.name == queryName }
118+ ? : throw SchemaError (" Expected a Query object with name '$queryName ' but found none!" )
119+ val mutation = objects.find { it.name == mutationName }
120+ ? : if (rootInfo.isMutationRequired()) throw SchemaError (" Expected a Mutation object with name '$mutationName ' but found none!" ) else null
121+ val subscription = objects.find { it.name == subscriptionName }
122+ ? : if (rootInfo.isSubscriptionRequired()) throw SchemaError (" Expected a Subscription object with name '$subscriptionName ' but found none!" ) else null
116123
117124 return SchemaObjects (query, mutation, subscription, (objects + inputObjects + enums + interfaces + unions).toSet())
118125 }
@@ -130,22 +137,24 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
130137 private fun createObject (definition : ObjectTypeDefinition , interfaces : List <GraphQLInterfaceType >): GraphQLObjectType {
131138 val name = definition.name
132139 val builder = GraphQLObjectType .newObject()
133- .name(name)
134- .definition(definition)
135- .description(getDocumentation(definition))
140+ .name(name)
141+ .definition(definition)
142+ .description(getDocumentation(definition))
136143
137144 builder.withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .OBJECT ))
138145
139146 definition.implements.forEach { implementsDefinition ->
140147 val interfaceName = (implementsDefinition as TypeName ).name
141- builder.withInterface(interfaces.find { it.name == interfaceName } ? : throw SchemaError (" Expected interface type with name '$interfaceName ' but found none!" ))
148+ builder.withInterface(interfaces.find { it.name == interfaceName }
149+ ? : throw SchemaError (" Expected interface type with name '$interfaceName ' but found none!" ))
142150 }
143151
144152 definition.getExtendedFieldDefinitions(extensionDefinitions).forEach { fieldDefinition ->
145153 fieldDefinition.description
146154 builder.field { field ->
147155 createField(field, fieldDefinition)
148- field.dataFetcher(fieldResolversByType[definition]?.get(fieldDefinition)?.createDataFetcher() ? : throw SchemaError (" No resolver method found for object type '${definition.name} ' and field '${fieldDefinition.name} ', this is most likely a bug with graphql-java-tools" ))
156+ field.dataFetcher(fieldResolversByType[definition]?.get(fieldDefinition)?.createDataFetcher()
157+ ? : throw SchemaError (" No resolver method found for object type '${definition.name} ' and field '${fieldDefinition.name} ', this is most likely a bug with graphql-java-tools" ))
149158
150159 val wiredField = directiveGenerator.onField(field.build(), DirectiveBehavior .Params (runtimeWiring))
151160 GraphQLFieldDefinition .Builder (wiredField)
@@ -172,21 +181,21 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
172181
173182 private fun createInputObject (definition : InputObjectTypeDefinition ): GraphQLInputObjectType {
174183 val builder = GraphQLInputObjectType .newInputObject()
175- .name(definition.name)
176- .definition(definition)
177- .description(getDocumentation(definition))
184+ .name(definition.name)
185+ .definition(definition)
186+ .description(getDocumentation(definition))
178187
179188 builder.withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .INPUT_OBJECT ))
180189
181190 definition.inputValueDefinitions.forEach { inputDefinition ->
182- builder.field { field ->
183- field .name(inputDefinition.name)
184- field .definition(inputDefinition)
185- field .description(getDocumentation(inputDefinition))
186- field .defaultValue(inputDefinition.defaultValue)
187- field .type(determineInputType(inputDefinition.type))
188- field .withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .INPUT_FIELD_DEFINITION ))
189- }
191+ val fieldBuilder = GraphQLInputObjectField .newInputObjectField()
192+ .name(inputDefinition.name)
193+ .definition(inputDefinition)
194+ .description(getDocumentation(inputDefinition))
195+ .defaultValue(inputDefinition.defaultValue)
196+ .type(determineInputType(inputDefinition.type))
197+ .withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .INPUT_FIELD_DEFINITION ))
198+ builder.field(directiveGenerator.onInputObjectField(fieldBuilder.build(), DirectiveBehavior . Params (runtimeWiring)))
190199 }
191200
192201 return directiveGenerator.onInputObject(builder.build(), DirectiveBehavior .Params (runtimeWiring))
@@ -198,20 +207,20 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
198207 if (! type.unwrap().isEnum) throw SchemaError (" Type '$name ' is declared as an enum in the GraphQL schema but is not a Java enum!" )
199208
200209 val builder = GraphQLEnumType .newEnum()
201- .name(name)
202- .definition(definition)
203- .description(getDocumentation(definition))
210+ .name(name)
211+ .definition(definition)
212+ .description(getDocumentation(definition))
204213
205214 builder.withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .ENUM ))
206215
207216 definition.enumValueDefinitions.forEach { enumDefinition ->
208217 val enumName = enumDefinition.name
209- val enumValue = type.unwrap().enumConstants.find { (it as Enum <* >).name == enumName } ? : throw SchemaError (" Expected value for name '$enumName ' in enum '${type.unwrap().simpleName} ' but found none!" )
218+ val enumValue = type.unwrap().enumConstants.find { (it as Enum <* >).name == enumName }
219+ ? : throw SchemaError (" Expected value for name '$enumName ' in enum '${type.unwrap().simpleName} ' but found none!" )
220+ val enumValueDirectives = buildDirectives(enumDefinition.directives, setOf (), Introspection .DirectiveLocation .ENUM_VALUE ).toMutableList()
210221 getDeprecated(enumDefinition.directives).let {
211- when (it) {
212- is String -> builder.value(enumName, enumValue, getDocumentation(enumDefinition), it)
213- else -> builder.value(enumName, enumValue, getDocumentation(enumDefinition))
214- }
222+ val enumValueDefinition = GraphQLEnumValueDefinition (enumName, getDocumentation(enumDefinition), enumValue, it, enumValueDirectives)
223+ builder.value(directiveGenerator.onEnumValue(enumValueDefinition, DirectiveBehavior .Params (runtimeWiring)))
215224 }
216225 }
217226
@@ -221,10 +230,10 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
221230 private fun createInterfaceObject (definition : InterfaceTypeDefinition ): GraphQLInterfaceType {
222231 val name = definition.name
223232 val builder = GraphQLInterfaceType .newInterface()
224- .name(name)
225- .definition(definition)
226- .description(getDocumentation(definition))
227- .typeResolver(TypeResolverProxy ())
233+ .name(name)
234+ .definition(definition)
235+ .description(getDocumentation(definition))
236+ .typeResolver(TypeResolverProxy ())
228237
229238 builder.withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .INTERFACE ))
230239
@@ -238,10 +247,10 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
238247 private fun createUnionObject (definition : UnionTypeDefinition , types : List <GraphQLObjectType >): GraphQLUnionType {
239248 val name = definition.name
240249 val builder = GraphQLUnionType .newUnionType()
241- .name(name)
242- .definition(definition)
243- .description(getDocumentation(definition))
244- .typeResolver(TypeResolverProxy ())
250+ .name(name)
251+ .definition(definition)
252+ .description(getDocumentation(definition))
253+ .typeResolver(TypeResolverProxy ())
245254
246255 builder.withDirectives(* buildDirectives(definition.directives, setOf (), Introspection .DirectiveLocation .UNION ))
247256
@@ -257,40 +266,40 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
257266 val typeName = (it as TypeName ).name
258267
259268 // Is this a nested union? If so, expand
260- val nestedUnion : UnionTypeDefinition ? = unionDefinitions.find { otherDefinition -> typeName == otherDefinition.name }
269+ val nestedUnion: UnionTypeDefinition ? = unionDefinitions.find { otherDefinition -> typeName == otherDefinition.name }
261270
262271 if (nestedUnion != null ) {
263272 leafObjects.addAll(getLeafUnionObjects(nestedUnion, types))
264273 } else {
265- leafObjects.add(types.find { it.name == typeName } ? : throw SchemaError (" Expected object type '$typeName ' for union type '$name ', but found none!" ))
274+ leafObjects.add(types.find { it.name == typeName }
275+ ? : throw SchemaError (" Expected object type '$typeName ' for union type '$name ', but found none!" ))
266276 }
267277 }
268278 return leafObjects
269279 }
270280
271- private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition ): GraphQLFieldDefinition .Builder {
281+ private fun createField (field : GraphQLFieldDefinition .Builder , fieldDefinition : FieldDefinition ): GraphQLFieldDefinition .Builder {
272282 field.name(fieldDefinition.name)
273283 field.description(getDocumentation(fieldDefinition))
274284 field.definition(fieldDefinition)
275285 getDeprecated(fieldDefinition.directives)?.let { field.deprecate(it) }
276286 field.type(determineOutputType(fieldDefinition.type))
277287 fieldDefinition.inputValueDefinitions.forEach { argumentDefinition ->
278- field.argument { argument ->
279- argument.name(argumentDefinition.name)
280- argument.definition(argumentDefinition)
281- argument.description(getDocumentation(argumentDefinition))
282- argument.defaultValue(buildDefaultValue(argumentDefinition.defaultValue))
283- argument.type(determineInputType(argumentDefinition.type))
284- argument.withDirectives(* buildDirectives(argumentDefinition.directives, setOf (), Introspection .DirectiveLocation .ARGUMENT_DEFINITION ))
285-
286- }
288+ val argumentBuilder = GraphQLArgument .newArgument()
289+ .name(argumentDefinition.name)
290+ .definition(argumentDefinition)
291+ .description(getDocumentation(argumentDefinition))
292+ .defaultValue(buildDefaultValue(argumentDefinition.defaultValue))
293+ .type(determineInputType(argumentDefinition.type))
294+ .withDirectives(* buildDirectives(argumentDefinition.directives, setOf (), Introspection .DirectiveLocation .ARGUMENT_DEFINITION ))
295+ field.argument(directiveGenerator.onArgument(argumentBuilder.build(), DirectiveBehavior .Params (runtimeWiring)))
287296 }
288297 field.withDirectives(* buildDirectives(fieldDefinition.directives, setOf (), Introspection .DirectiveLocation .FIELD_DEFINITION ))
289298 return field
290299 }
291300
292301 private fun buildDefaultValue (value : Value <* >? ): Any? {
293- return when (value) {
302+ return when (value) {
294303 null -> null
295304 is IntValue -> value.value
296305 is FloatValue -> value.value
@@ -305,10 +314,11 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
305314
306315 private fun determineOutputType (typeDefinition : Type <* >) =
307316 determineType(GraphQLOutputType ::class , typeDefinition, permittedTypesForObject) as GraphQLOutputType
317+
308318 private fun determineInputType (typeDefinition : Type <* >) =
309319 determineType(GraphQLInputType ::class , typeDefinition, permittedTypesForInputObject) as GraphQLInputType
310320
311- private fun <T : Any > determineType (expectedType : KClass <T >, typeDefinition : Type <* >, allowedTypeReferences : Set <String >): GraphQLType =
321+ private fun <T : Any > determineType (expectedType : KClass <T >, typeDefinition : Type <* >, allowedTypeReferences : Set <String >): GraphQLType =
312322 when (typeDefinition) {
313323 is ListType -> GraphQLList (determineType(expectedType, typeDefinition.type, allowedTypeReferences))
314324 is NonNullType -> GraphQLNonNull (determineType(expectedType, typeDefinition.type, allowedTypeReferences))
@@ -335,10 +345,10 @@ class SchemaParser internal constructor(scanResult: ScannedSchemaObjects, privat
335345 * indicating no deprecation directive was found within the directives list.
336346 */
337347 private fun getDeprecated (directives : List <Directive >): String? =
338- getDirective(directives, " deprecated" )?.let { directive ->
339- (directive.arguments.find { it.name == " reason" }?.value as ? StringValue )?.value ? :
340- DEFAULT_DEPRECATION_MESSAGE
341- }
348+ getDirective(directives, " deprecated" )?.let { directive ->
349+ (directive.arguments.find { it.name == " reason" }?.value as ? StringValue )?.value
350+ ? : DEFAULT_DEPRECATION_MESSAGE
351+ }
342352
343353 private fun getDirective (directives : List <Directive >, name : String ): Directive ? = directives.find {
344354 it.name == name
0 commit comments