Skip to content

Commit 4dbffff

Browse files
committed
Move scanning related internal classes to scanner package
1 parent 5128006 commit 4dbffff

24 files changed

+378
-328
lines changed

src/main/kotlin/graphql/kickstart/tools/DictionaryTypeResolver.kt

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ import graphql.schema.TypeResolver
1212
/**
1313
* @author Andrew Potter
1414
*/
15-
abstract class DictionaryTypeResolver(private val dictionary: BiMap<JavaType, TypeDefinition<*>>, private val types: Map<String, GraphQLObjectType>) : TypeResolver {
15+
internal abstract class DictionaryTypeResolver(
16+
private val dictionary: BiMap<JavaType, TypeDefinition<*>>,
17+
private val types: Map<String, GraphQLObjectType>
18+
) : TypeResolver {
1619
private fun <T> getTypeName(clazz: Class<T>): String? {
1720
val name = dictionary[clazz]?.name
1821

@@ -35,12 +38,26 @@ abstract class DictionaryTypeResolver(private val dictionary: BiMap<JavaType, Ty
3538
abstract fun getError(name: String): String
3639
}
3740

38-
class InterfaceTypeResolver(dictionary: BiMap<JavaType, TypeDefinition<*>>, private val thisInterface: GraphQLInterfaceType, types: List<GraphQLObjectType>) : DictionaryTypeResolver(dictionary, types.filter { it.interfaces.any { it.name == thisInterface.name } }.associateBy { it.name }) {
41+
internal class InterfaceTypeResolver(
42+
dictionary: BiMap<JavaType, TypeDefinition<*>>,
43+
private val thisInterface: GraphQLInterfaceType,
44+
types: List<GraphQLObjectType>
45+
) : DictionaryTypeResolver(
46+
dictionary,
47+
types.filter { it.interfaces.any { it.name == thisInterface.name } }.associateBy { it.name }
48+
) {
3949
override fun getError(name: String) = "Expected object type with name '$name' to implement interface '${thisInterface.name}', but it doesn't!"
4050
}
4151

42-
class UnionTypeResolver(dictionary: BiMap<JavaType, TypeDefinition<*>>, private val thisUnion: GraphQLUnionType, types: List<GraphQLObjectType>) : DictionaryTypeResolver(dictionary, types.filter { type -> thisUnion.types.any { it.name == type.name } }.associateBy { it.name }) {
52+
internal class UnionTypeResolver(
53+
dictionary: BiMap<JavaType, TypeDefinition<*>>,
54+
private val thisUnion: GraphQLUnionType,
55+
types: List<GraphQLObjectType>
56+
) : DictionaryTypeResolver(
57+
dictionary,
58+
types.filter { type -> thisUnion.types.any { it.name == type.name } }.associateBy { it.name }
59+
) {
4360
override fun getError(name: String) = "Expected object type with name '$name' to exist for union '${thisUnion.name}', but it doesn't!"
4461
}
4562

46-
class TypeResolverError(message: String, cause: Throwable? = null) : RuntimeException(message, cause)
63+
internal class TypeResolverError(message: String, cause: Throwable? = null) : RuntimeException(message, cause)

src/main/kotlin/graphql/kickstart/tools/SchemaObjects.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ data class SchemaObjects(
3131
/**
3232
* Makes a GraphQLSchema with query but without mutation and subscription.
3333
*/
34-
@Suppress("unused")
3534
fun toReadOnlySchema(): GraphQLSchema = GraphQLSchema.newSchema()
3635
.query(query)
3736
.additionalTypes(dictionary)

src/main/kotlin/graphql/kickstart/tools/SchemaParser.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package graphql.kickstart.tools
22

33
import graphql.introspection.Introspection
44
import graphql.kickstart.tools.directive.SchemaGeneratorDirectiveHelper
5+
import graphql.kickstart.tools.scanner.ScannedSchemaObjects
6+
import graphql.kickstart.tools.scanner.SchemaClassScanner
57
import graphql.kickstart.tools.util.getExtendedFieldDefinitions
68
import graphql.kickstart.tools.util.unwrap
79
import graphql.language.*
@@ -74,7 +76,7 @@ class SchemaParser internal constructor(
7476
codeRegistryBuilder.fieldVisibility(NoIntrospectionGraphqlFieldVisibility.NO_INTROSPECTION_FIELD_VISIBILITY)
7577
}
7678
// this overrides the above introspection enabled setting obviously... todo: add documentation
77-
options.fieldVisilibity?.let { codeRegistryBuilder.fieldVisibility(it) }
79+
options.fieldVisibility?.let { codeRegistryBuilder.fieldVisibility(it) }
7880

7981
// Create GraphQL objects
8082
val inputObjects: MutableList<GraphQLInputObjectType> = mutableListOf()
Lines changed: 4 additions & 295 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,23 @@
11
package graphql.kickstart.tools
22

3-
import com.fasterxml.jackson.databind.ObjectMapper
4-
import graphql.kickstart.tools.proxy.*
5-
import graphql.kickstart.tools.relay.RelayConnectionFactory
6-
import graphql.kickstart.tools.util.BiMap
7-
import graphql.kickstart.tools.util.JavaType
8-
import graphql.kickstart.tools.util.coroutineScope
3+
import graphql.kickstart.tools.scanner.ScannedSchemaObjects
4+
import graphql.kickstart.tools.scanner.SchemaClassScanner
95
import graphql.language.Definition
106
import graphql.language.Document
117
import graphql.parser.Parser
12-
import graphql.schema.DataFetchingEnvironment
138
import graphql.schema.GraphQLScalarType
149
import graphql.schema.idl.RuntimeWiring
1510
import graphql.schema.idl.SchemaDirectiveWiring
16-
import graphql.schema.visibility.GraphqlFieldVisibility
17-
import kotlinx.coroutines.Dispatchers
18-
import kotlinx.coroutines.ExperimentalCoroutinesApi
19-
import kotlinx.coroutines.channels.ReceiveChannel
20-
import kotlinx.coroutines.reactive.publish
2111
import org.antlr.v4.runtime.RecognitionException
2212
import org.antlr.v4.runtime.misc.ParseCancellationException
23-
import org.reactivestreams.Publisher
24-
import java.util.concurrent.CompletableFuture
25-
import java.util.concurrent.CompletionStage
26-
import java.util.concurrent.Future
27-
import kotlin.coroutines.CoroutineContext
2813
import kotlin.reflect.KClass
2914

3015
/**
3116
* @author Andrew Potter
3217
*/
33-
class SchemaParserBuilder constructor(private val dictionary: SchemaParserDictionary = SchemaParserDictionary()) {
18+
class SchemaParserBuilder {
3419

20+
private val dictionary = SchemaParserDictionary()
3521
private val schemaString = StringBuilder()
3622
private val files = mutableListOf<String>()
3723
private val resolvers = mutableListOf<GraphQLResolver<*>>()
@@ -215,280 +201,3 @@ class InvalidSchemaError(pce: ParseCancellationException, private val recognitio
215201
override val message: String?
216202
get() = "Invalid schema provided (${recognitionException.javaClass.name}) at: ${recognitionException.offendingToken}"
217203
}
218-
219-
class SchemaParserDictionary {
220-
221-
private val dictionary: BiMap<String, Class<*>> = BiMap.create()
222-
223-
fun getDictionary(): BiMap<String, Class<*>> = BiMap.unmodifiableBiMap(dictionary)
224-
225-
/**
226-
* Add arbitrary classes to the parser's dictionary, overriding the generated type name.
227-
*/
228-
fun add(name: String, clazz: Class<*>) = this.apply {
229-
this.dictionary.put(name, clazz)
230-
}
231-
232-
/**
233-
* Add arbitrary classes to the parser's dictionary, overriding the generated type name.
234-
*/
235-
fun add(name: String, clazz: KClass<*>) = this.apply {
236-
this.dictionary.put(name, clazz.java)
237-
}
238-
239-
/**
240-
* Add arbitrary classes to the parser's dictionary, overriding the generated type name.
241-
*/
242-
fun add(dictionary: Map<String, Class<*>>) = this.apply {
243-
this.dictionary.putAll(dictionary)
244-
}
245-
246-
/**
247-
* Add arbitrary classes to the parser's dictionary.
248-
*/
249-
fun add(clazz: Class<*>) = this.apply {
250-
this.add(clazz.simpleName, clazz)
251-
}
252-
253-
/**
254-
* Add arbitrary classes to the parser's dictionary.
255-
*/
256-
fun add(clazz: KClass<*>) = this.apply {
257-
this.add(clazz.java.simpleName, clazz)
258-
}
259-
260-
/**
261-
* Add arbitrary classes to the parser's dictionary.
262-
*/
263-
fun add(vararg dictionary: Class<*>) = this.apply {
264-
dictionary.forEach { this.add(it) }
265-
}
266-
267-
/**
268-
* Add arbitrary classes to the parser's dictionary.
269-
*/
270-
fun add(vararg dictionary: KClass<*>) = this.apply {
271-
dictionary.forEach { this.add(it) }
272-
}
273-
274-
/**
275-
* Add arbitrary classes to the parser's dictionary.
276-
*/
277-
fun add(dictionary: Collection<Class<*>>) = this.apply {
278-
dictionary.forEach { this.add(it) }
279-
}
280-
}
281-
282-
data class SchemaParserOptions internal constructor(
283-
val contextClass: Class<*>?,
284-
val genericWrappers: List<GenericWrapper>,
285-
val allowUnimplementedResolvers: Boolean,
286-
val objectMapperProvider: PerFieldObjectMapperProvider,
287-
val proxyHandlers: List<ProxyHandler>,
288-
val preferGraphQLResolver: Boolean,
289-
val introspectionEnabled: Boolean,
290-
val coroutineContextProvider: CoroutineContextProvider,
291-
val typeDefinitionFactories: List<TypeDefinitionFactory>,
292-
val fieldVisilibity: GraphqlFieldVisibility?
293-
) {
294-
companion object {
295-
@JvmStatic
296-
fun newOptions() = Builder()
297-
298-
@JvmStatic
299-
@ExperimentalCoroutinesApi
300-
fun defaultOptions() = Builder().build()
301-
}
302-
303-
val coroutineContext: CoroutineContext
304-
get() = coroutineContextProvider.provide()
305-
306-
class Builder {
307-
private var contextClass: Class<*>? = null
308-
private val genericWrappers: MutableList<GenericWrapper> = mutableListOf()
309-
private var useDefaultGenericWrappers = true
310-
private var allowUnimplementedResolvers = false
311-
private var objectMapperProvider: PerFieldObjectMapperProvider = PerFieldConfiguringObjectMapperProvider()
312-
private val proxyHandlers: MutableList<ProxyHandler> = mutableListOf(Spring4AopProxyHandler(), GuiceAopProxyHandler(), JavassistProxyHandler(), WeldProxyHandler())
313-
private var preferGraphQLResolver = false
314-
private var introspectionEnabled = true
315-
private var coroutineContextProvider: CoroutineContextProvider? = null
316-
private var typeDefinitionFactories: MutableList<TypeDefinitionFactory> = mutableListOf(RelayConnectionFactory())
317-
private var fieldVisibility: GraphqlFieldVisibility? = null
318-
319-
fun contextClass(contextClass: Class<*>) = this.apply {
320-
this.contextClass = contextClass
321-
}
322-
323-
fun contextClass(contextClass: KClass<*>) = this.apply {
324-
this.contextClass = contextClass.java
325-
}
326-
327-
fun genericWrappers(genericWrappers: List<GenericWrapper>) = this.apply {
328-
this.genericWrappers.addAll(genericWrappers)
329-
}
330-
331-
fun genericWrappers(vararg genericWrappers: GenericWrapper) = this.apply {
332-
this.genericWrappers.addAll(genericWrappers)
333-
}
334-
335-
fun useDefaultGenericWrappers(useDefaultGenericWrappers: Boolean) = this.apply {
336-
this.useDefaultGenericWrappers = useDefaultGenericWrappers
337-
}
338-
339-
fun allowUnimplementedResolvers(allowUnimplementedResolvers: Boolean) = this.apply {
340-
this.allowUnimplementedResolvers = allowUnimplementedResolvers
341-
}
342-
343-
fun preferGraphQLResolver(preferGraphQLResolver: Boolean) = this.apply {
344-
this.preferGraphQLResolver = preferGraphQLResolver
345-
}
346-
347-
fun objectMapperConfigurer(objectMapperConfigurer: ObjectMapperConfigurer) = this.apply {
348-
this.objectMapperProvider = PerFieldConfiguringObjectMapperProvider(objectMapperConfigurer)
349-
}
350-
351-
fun objectMapperProvider(objectMapperProvider: PerFieldObjectMapperProvider) = this.apply {
352-
this.objectMapperProvider = objectMapperProvider
353-
}
354-
355-
fun objectMapperConfigurer(objectMapperConfigurer: (ObjectMapper, ObjectMapperConfigurerContext) -> Unit) = this.apply {
356-
this.objectMapperConfigurer(ObjectMapperConfigurer(objectMapperConfigurer))
357-
}
358-
359-
fun addProxyHandler(proxyHandler: ProxyHandler) = this.apply {
360-
this.proxyHandlers.add(proxyHandler)
361-
}
362-
363-
fun introspectionEnabled(introspectionEnabled: Boolean) = this.apply {
364-
this.introspectionEnabled = introspectionEnabled
365-
}
366-
367-
fun coroutineContext(context: CoroutineContext) = this.apply {
368-
this.coroutineContextProvider = DefaultCoroutineContextProvider(context)
369-
}
370-
371-
fun coroutineContextProvider(contextProvider: CoroutineContextProvider) = this.apply {
372-
this.coroutineContextProvider = contextProvider
373-
}
374-
375-
fun typeDefinitionFactory(factory: TypeDefinitionFactory) = this.apply {
376-
this.typeDefinitionFactories.add(factory)
377-
}
378-
379-
fun fieldVisibility(fieldVisibility: GraphqlFieldVisibility) = this.apply {
380-
this.fieldVisibility = fieldVisibility
381-
}
382-
383-
@ExperimentalCoroutinesApi
384-
fun build(): SchemaParserOptions {
385-
val coroutineContextProvider = coroutineContextProvider
386-
?: DefaultCoroutineContextProvider(Dispatchers.Default)
387-
val wrappers = if (useDefaultGenericWrappers) {
388-
genericWrappers + listOf(
389-
GenericWrapper(Future::class, 0),
390-
GenericWrapper(CompletableFuture::class, 0),
391-
GenericWrapper(CompletionStage::class, 0),
392-
GenericWrapper(Publisher::class, 0),
393-
GenericWrapper.withTransformer(ReceiveChannel::class, 0, { receiveChannel, environment ->
394-
environment.coroutineScope().publish(coroutineContextProvider.provide()) {
395-
try {
396-
for (item in receiveChannel) {
397-
send(item)
398-
}
399-
} finally {
400-
receiveChannel.cancel()
401-
}
402-
}
403-
})
404-
)
405-
} else {
406-
genericWrappers
407-
}
408-
409-
return SchemaParserOptions(contextClass, wrappers, allowUnimplementedResolvers, objectMapperProvider,
410-
proxyHandlers, preferGraphQLResolver, introspectionEnabled, coroutineContextProvider,
411-
typeDefinitionFactories, fieldVisibility
412-
)
413-
}
414-
}
415-
416-
internal class DefaultCoroutineContextProvider(val coroutineContext: CoroutineContext) : CoroutineContextProvider {
417-
override fun provide(): CoroutineContext {
418-
return coroutineContext
419-
}
420-
}
421-
422-
data class GenericWrapper(
423-
val type: Class<*>,
424-
val index: Int,
425-
val transformer: (Any, DataFetchingEnvironment) -> Any? = { x, _ -> x },
426-
val schemaWrapper: (JavaType) -> JavaType = { x -> x }
427-
) {
428-
constructor(type: Class<*>, index: Int) : this(type, index, { x, _ -> x })
429-
constructor(type: KClass<*>, index: Int) : this(type.java, index, { x, _ -> x })
430-
431-
companion object {
432-
@Suppress("UNCHECKED_CAST")
433-
@JvmStatic
434-
fun <T> withTransformer(
435-
type: Class<T>,
436-
index: Int,
437-
transformer: (T, DataFetchingEnvironment) -> Any?,
438-
schemaWrapper: (JavaType) -> JavaType = { x -> x }
439-
): GenericWrapper where T : Any {
440-
return GenericWrapper(type, index, transformer as (Any, DataFetchingEnvironment) -> Any?, schemaWrapper)
441-
}
442-
443-
fun <T> withTransformer(
444-
type: KClass<T>,
445-
index: Int,
446-
transformer: (T, DataFetchingEnvironment) -> Any?,
447-
schemaWrapper: (JavaType) -> JavaType = { x -> x }
448-
): GenericWrapper where T : Any {
449-
return withTransformer(type.java, index, transformer, schemaWrapper)
450-
}
451-
452-
@JvmStatic
453-
fun <T> withTransformer(
454-
type: Class<T>,
455-
index: Int,
456-
transformer: (T) -> Any?,
457-
schemaWrapper: (JavaType) -> JavaType = { x -> x }
458-
): GenericWrapper where T : Any {
459-
return withTransformer(type, index, { x, _ -> transformer.invoke(x) }, schemaWrapper)
460-
}
461-
462-
fun <T> withTransformer(
463-
type: KClass<T>,
464-
index: Int,
465-
transformer: (T) -> Any?,
466-
schemaWrapper: (JavaType) -> JavaType = { x -> x }
467-
): GenericWrapper where T : Any {
468-
return withTransformer(type.java, index, transformer, schemaWrapper)
469-
}
470-
471-
@JvmStatic
472-
fun <T> listCollectionWithTransformer(
473-
type: Class<T>,
474-
index: Int,
475-
transformer: (T) -> Any?
476-
): GenericWrapper where T : Any {
477-
return withTransformer(
478-
type,
479-
index,
480-
transformer,
481-
{ innerType -> ParameterizedTypeImpl.make(List::class.java, arrayOf(innerType), null) }
482-
)
483-
}
484-
485-
fun <T> listCollectionWithTransformer(
486-
type: KClass<T>,
487-
index: Int,
488-
transformer: (T) -> Any?
489-
): GenericWrapper where T : Any {
490-
return listCollectionWithTransformer(type.java, index, transformer)
491-
}
492-
}
493-
}
494-
}

0 commit comments

Comments
 (0)