Skip to content

Commit

Permalink
Merge pull request #593 from timward60/timward/get-type
Browse files Browse the repository at this point in the history
DictionaryResolverType should use return GraphQLObjectType from Schema rather than cached map
  • Loading branch information
oryan-block authored Nov 8, 2021
2 parents 004c964 + 28194bd commit 866cfdf
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 15 deletions.
17 changes: 6 additions & 11 deletions src/main/kotlin/graphql/kickstart/tools/DictionaryTypeResolver.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import graphql.schema.TypeResolver
* @author Andrew Potter
*/
internal abstract class DictionaryTypeResolver(
private val dictionary: BiMap<JavaType, TypeDefinition<*>>,
private val types: Map<String, GraphQLObjectType>
private val dictionary: BiMap<JavaType, TypeDefinition<*>>
) : TypeResolver {
private fun <T> getTypeDefinition(clazz: Class<T>): TypeDefinition<*>? {
return dictionary[clazz]
Expand All @@ -25,30 +24,26 @@ internal abstract class DictionaryTypeResolver(
override fun getType(env: TypeResolutionEnvironment): GraphQLObjectType? {
val clazz = env.getObject<Any>().javaClass
val name = getTypeDefinition(clazz)?.name ?: clazz.simpleName
return types[name] ?: throw TypeResolverError(getError(name))
return env.schema.getObjectType(name) ?: throw TypeResolverError(getError(name))
}

abstract fun getError(name: String): String
}

internal class InterfaceTypeResolver(
dictionary: BiMap<JavaType, TypeDefinition<*>>,
private val thisInterface: GraphQLInterfaceType,
types: List<GraphQLObjectType>
private val thisInterface: GraphQLInterfaceType
) : DictionaryTypeResolver(
dictionary,
types.filter { type -> type.interfaces.any { it.name == thisInterface.name } }.associateBy { it.name }
dictionary
) {
override fun getError(name: String) = "Expected object type with name '$name' to implement interface '${thisInterface.name}', but it doesn't!"
}

internal class UnionTypeResolver(
dictionary: BiMap<JavaType, TypeDefinition<*>>,
private val thisUnion: GraphQLUnionType,
types: List<GraphQLObjectType>
private val thisUnion: GraphQLUnionType
) : DictionaryTypeResolver(
dictionary,
types.filter { type -> thisUnion.types.any { it.name == type.name } }.associateBy { it.name }
dictionary
) {
override fun getError(name: String) = "Expected object type with name '$name' to exist for union '${thisUnion.name}', but it doesn't!"
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ class SchemaParser internal constructor(
val enums = enumDefinitions.map { createEnumObject(it) }

// Assign type resolver to interfaces now that we know all of the object types
interfaces.forEach { codeRegistryBuilder.typeResolver(it, InterfaceTypeResolver(dictionary.inverse(), it, objects)) }
unions.forEach { codeRegistryBuilder.typeResolver(it, UnionTypeResolver(dictionary.inverse(), it, objects)) }
interfaces.forEach { codeRegistryBuilder.typeResolver(it, InterfaceTypeResolver(dictionary.inverse(), it)) }
unions.forEach { codeRegistryBuilder.typeResolver(it, UnionTypeResolver(dictionary.inverse(), it)) }

// Find query type and mutation/subscription type (if mutation/subscription type exists)
val queryName = rootInfo.getQueryName()
Expand Down
42 changes: 40 additions & 2 deletions src/test/kotlin/graphql/kickstart/tools/EndToEndTest.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package graphql.kickstart.tools

import com.fasterxml.jackson.module.kotlin.jacksonMapperBuilder
import graphql.*
import graphql.execution.AsyncExecutionStrategy
import graphql.schema.GraphQLEnumType
import graphql.schema.GraphQLSchema
import graphql.schema.*
import graphql.util.TraversalControl
import graphql.util.TraverserContext
import org.junit.Test
import org.reactivestreams.Publisher
import org.reactivestreams.Subscriber
Expand Down Expand Up @@ -670,4 +672,40 @@ class EndToEndTest {
val exceptionWhileDataFetching = result.errors[0] as ExceptionWhileDataFetching
assert(exceptionWhileDataFetching.exception is IllegalArgumentException)
}

class Transformer : GraphQLTypeVisitorStub() {
override fun visitGraphQLObjectType(node: GraphQLObjectType?, context: TraverserContext<GraphQLSchemaElement>?): TraversalControl {
val newNode = node?.transform { builder -> builder.description(node.description + " [MODIFIED]") }
return changeNode(context, newNode)
}
}

@Test
fun `transformed schema should execute query`() {
val transformedSchema = SchemaTransformer().transform(schema, Transformer())
val transformedGql: GraphQL = GraphQL.newGraphQL(transformedSchema)
.queryExecutionStrategy(AsyncExecutionStrategy())
.build()

val data = assertNoGraphQlErrors(transformedGql) {
"""
{
otherUnionItems {
... on Item {
itemId: id
}
... on ThirdItem {
thirdItemId: id
}
}
}
"""
}

assertEquals(data["otherUnionItems"], listOf(
mapOf("itemId" to 0),
mapOf("itemId" to 1),
mapOf("thirdItemId" to 100)
))
}
}

0 comments on commit 866cfdf

Please sign in to comment.