@@ -4,10 +4,7 @@ import com.expedia.graphql.TopLevelObjectDef
44import com.expedia.graphql.schema.KotlinDataFetcher
55import com.expedia.graphql.schema.Parameter
66import com.expedia.graphql.schema.SchemaGeneratorConfig
7- import com.expedia.graphql.schema.exceptions.ConflictingTypesException
8- import com.expedia.graphql.schema.exceptions.CouldNotGetNameOfEnumException
97import com.expedia.graphql.schema.exceptions.InvalidInputFieldTypeException
10- import com.expedia.graphql.schema.exceptions.TypeNotSupportedException
118import com.expedia.graphql.schema.extensions.directives
129import com.expedia.graphql.schema.extensions.getDeprecationReason
1310import com.expedia.graphql.schema.extensions.graphQLDescription
@@ -52,7 +49,7 @@ internal class SchemaGenerator(
5249 private val config : SchemaGeneratorConfig
5350) {
5451
55- private val typesCache : MutableMap < String , KGraphQLType > = mutableMapOf ( )
52+ private val cache = TypesCache (config.supportedPackages )
5653 private val additionTypes = mutableSetOf<GraphQLType >()
5754 private val directives = mutableSetOf<GraphQLDirective >()
5855 private val reflections = Reflections (config.supportedPackages)
@@ -73,7 +70,7 @@ internal class SchemaGenerator(
7370
7471 private fun addAdditionalTypes (builder : GraphQLSchema .Builder ) {
7572 additionTypes
76- .filter { typesCache.none { (_, v) -> v.graphQLType.name == it.name } }
73+ .filter { cache.doesNotContainGraphQLType(it) }
7774 .forEach { builder.additionalType(it) }
7875 }
7976
@@ -83,9 +80,7 @@ internal class SchemaGenerator(
8380 val queryBuilder = GraphQLObjectType .Builder ()
8481 queryBuilder.name(config.topLevelQueryName)
8582 for (query in queries) {
86- query.klazz.declaredMemberFunctions
87- .filter { config.hooks.isValidFunction(it) }
88- .filter { func -> functionFilters.all { it.invoke(func) } }
83+ query.klazz.getValidFunctions(config.hooks)
8984 .forEach {
9085 val function = function(it, query.obj)
9186 val functionFromHook = config.hooks.didGenerateQueryType(it, function)
@@ -101,9 +96,7 @@ internal class SchemaGenerator(
10196 mutationBuilder.name(config.topLevelMutationName)
10297
10398 for (mutation in mutations) {
104- mutation.klazz.declaredMemberFunctions
105- .filter { config.hooks.isValidFunction(it) }
106- .filter { func -> functionFilters.all { it.invoke(func) } }
99+ mutation.klazz.getValidFunctions(config.hooks)
107100 .forEach {
108101 val function = function(it, mutation.obj)
109102 val functionFromHook = config.hooks.didGenerateMutationType(it, function)
@@ -163,10 +156,10 @@ internal class SchemaGenerator(
163156 private fun argument (parameter : KParameter ): GraphQLArgument {
164157 throwIfInterfaceIsNotAuthorized(parameter)
165158 return GraphQLArgument .newArgument()
166- .name(parameter.name)
167- .description(parameter.graphQLDescription() ? : parameter.type.graphQLDescription())
168- .type(graphQLTypeOf(parameter.type, true ) as GraphQLInputType )
169- .build()
159+ .name(parameter.name)
160+ .description(parameter.graphQLDescription() ? : parameter.type.graphQLDescription())
161+ .type(graphQLTypeOf(parameter.type, true ) as GraphQLInputType )
162+ .build()
170163 }
171164
172165 private fun graphQLTypeOf (type : KType , inputType : Boolean = false): GraphQLType {
@@ -178,21 +171,18 @@ internal class SchemaGenerator(
178171 }
179172
180173 private fun objectFromReflection (type : KType , inputType : Boolean ): GraphQLType {
181- val kClass = type.classifier as KClass <* >
182- val cacheKey = getCacheKey(kClass, type, inputType)
183- val cachedType = typesCache[cacheKey]
174+ val cacheKey = TypesCacheKey (type, inputType)
175+ val cachedType = cache.get(cacheKey)
184176
185177 if (cachedType != null ) {
186- val isSameNameButNotSameClass = cachedType.kClass != kClass
187- when {
188- isSameNameButNotSameClass -> throw ConflictingTypesException (cachedType.kClass, kClass)
189- else -> return cachedType.graphQLType
190- }
178+ return cachedType
191179 }
192180
181+ val kClass = type.classifier as KClass <* >
193182 val graphQLType = getGraphQLType(kClass, inputType, type)
183+ val kGraphQLType = KGraphQLType (kClass, graphQLType)
194184
195- typesCache[cacheKey] = KGraphQLType (kClass, graphQLType )
185+ cache.put(cacheKey, kGraphQLType )
196186
197187 return graphQLType
198188 }
@@ -210,31 +200,6 @@ internal class SchemaGenerator(
210200 private fun KClass <* >.canBeGraphQLUnion (): Boolean =
211201 this .canBeGraphQLInterface() && this .declaredMemberProperties.isEmpty() && this .declaredMemberFunctions.isEmpty()
212202
213- private fun getCacheKey (kClass : KClass <* >, type : KType , inputType : Boolean ): String {
214- if (kClass.isSubclassOf(Enum ::class )) {
215- return kClass.simpleName ? : throw CouldNotGetNameOfEnumException (kClass)
216- }
217- val cacheKeyFromTypeName = when {
218- kClass.isSubclassOf(List ::class ) -> " List<${type.arguments.first().type!! .jvmErasure.simpleName} >"
219- kClass.java.isArray -> " Array<${type.arguments.first().type!! .jvmErasure.simpleName} >"
220- else -> {
221- throwIfTypeIsNotSupported(type)
222- type.jvmErasure.simpleName
223- }
224- }
225-
226- return " $cacheKeyFromTypeName :$inputType "
227- }
228-
229- @Throws(TypeNotSupportedException ::class )
230- private fun throwIfTypeIsNotSupported (type : KType ) {
231- val qualifiedName = type.jvmErasure.qualifiedName ? : " "
232- val comesFromSupportedPackageName = qualifiedName.startsWith(config.supportedPackages)
233- if (! comesFromSupportedPackageName) {
234- throw TypeNotSupportedException (qualifiedName, config.supportedPackages)
235- }
236- }
237-
238203 @Throws(InvalidInputFieldTypeException ::class )
239204 private fun throwIfInterfaceIsNotAuthorized (parameter : KParameter ) {
240205 if (parameter.type.jvmErasure.java.isInterface) throw InvalidInputFieldTypeException ()
@@ -253,51 +218,45 @@ internal class SchemaGenerator(
253218 private fun listType (type : KType , inputType : Boolean ): GraphQLList =
254219 GraphQLList .list(graphQLTypeOf(type.arguments.first().type!! , inputType))
255220
256- private fun objectType (klass : KClass <* >, interfaceType : GraphQLInterfaceType ? = null): GraphQLType {
221+ private fun objectType (kClass : KClass <* >, interfaceType : GraphQLInterfaceType ? = null): GraphQLType {
257222 val builder = GraphQLObjectType .newObject()
258223
259- builder.name(klass .simpleName)
260- builder.description(klass .graphQLDescription())
224+ builder.name(kClass .simpleName)
225+ builder.description(kClass .graphQLDescription())
261226
262- klass .directives().map {
227+ kClass .directives().map {
263228 builder.withDirective(it)
264229 directives.add(it)
265230 }
266231
267232 if (interfaceType != null ) {
268233 builder.withInterface(interfaceType)
269234 } else {
270- klass .superclasses
235+ kClass .superclasses
271236 .asSequence()
272237 .filter { it.canBeGraphQLInterface() && ! it.canBeGraphQLUnion() }
273238 .map { objectFromReflection(it.createType(), false ) as GraphQLInterfaceType }
274239 .forEach { builder.withInterface(it) }
275240 }
276241
277- klass.declaredMemberProperties
278- .filter { config.hooks.isValidProperty(it) }
279- .filter { prop -> propertyFilters.all { it.invoke(prop) } }
242+ kClass.getValidProperties(config.hooks)
280243 .forEach { builder.field(property(it)) }
281244
282- klass.declaredMemberFunctions
283- .filter { config.hooks.isValidFunction(it) }
284- .filter { func -> functionFilters.all { it.invoke(func) } }
245+ kClass.getValidFunctions(config.hooks)
285246 .forEach { builder.field(function(it)) }
286247
287248 return builder.build()
288249 }
289250
290- private fun inputObjectType (klass : KClass <* >): GraphQLType {
251+ private fun inputObjectType (kClass : KClass <* >): GraphQLType {
291252 val builder = GraphQLInputObjectType .newInputObject()
292- val name = getGraphQLClassName(klass , true )
253+ val name = getGraphQLClassName(kClass , true )
293254
294255 builder.name(name)
295- builder.description(klass .graphQLDescription())
256+ builder.description(kClass .graphQLDescription())
296257
297258 // It does not make sense to run functions against the input types so we only process data fields
298- klass.declaredMemberProperties
299- .filter { config.hooks.isValidProperty(it) }
300- .filter { prop -> propertyFilters.all { it.invoke(prop) } }
259+ kClass.getValidProperties(config.hooks)
301260 .forEach { builder.field(inputProperty(it)) }
302261
303262 return builder.build()
@@ -319,20 +278,16 @@ internal class SchemaGenerator(
319278 builder.name(kClass.simpleName)
320279 builder.description(kClass.graphQLDescription())
321280
322- kClass.declaredMemberProperties
323- .filter { config.hooks.isValidProperty(it) }
324- .filter { prop -> propertyFilters.all { it.invoke(prop) } }
325- .forEach { builder.field(property(it)) }
281+ kClass.getValidProperties(config.hooks)
282+ .forEach { builder.field(property(it)) }
326283
327- kClass.declaredMemberFunctions
328- .filter { config.hooks.isValidFunction(it) }
329- .filter { func -> functionFilters.all { it.invoke(func) } }
330- .forEach { builder.field(function(it, abstract = true )) }
284+ kClass.getValidFunctions(config.hooks)
285+ .forEach { builder.field(function(it, abstract = true )) }
331286
332287 builder.typeResolver { env: TypeResolutionEnvironment -> env.schema.getObjectType(env.getObject<Any >().javaClass.simpleName) }
333288 val interfaceType = builder.build()
334289
335- val implementations = reflections. getSubTypesOf(Class .forName( kClass.javaObjectType.name) )
290+ val implementations = getSubTypesOf(kClass)
336291 implementations.forEach {
337292 additionTypes.add(objectType(it.kotlin, interfaceType))
338293 }
@@ -347,12 +302,15 @@ internal class SchemaGenerator(
347302 builder.description(kClass.graphQLDescription())
348303 builder.typeResolver { env: TypeResolutionEnvironment -> env.schema.getObjectType(env.getObject<Any >().javaClass.simpleName) }
349304
350- val implementations = reflections. getSubTypesOf(Class .forName( kClass.javaObjectType.name) )
305+ val implementations = getSubTypesOf(kClass)
351306 implementations
352307 .forEach {
353308 builder.possibleType(objectType(it.kotlin) as GraphQLObjectType )
354309 }
355310
356311 return builder.build()
357312 }
313+
314+ private fun getSubTypesOf (kclass : KClass <* >): MutableSet <out Class <out Any >> =
315+ reflections.getSubTypesOf(Class .forName(kclass.javaObjectType.name))
358316}
0 commit comments