@@ -2,7 +2,6 @@ package graphql.kickstart.tools.resolver
2
2
3
3
import com.fasterxml.jackson.core.type.TypeReference
4
4
import graphql.GraphQLContext
5
- import graphql.TrivialDataFetcher
6
5
import graphql.kickstart.tools.*
7
6
import graphql.kickstart.tools.SchemaParserOptions.GenericWrapper
8
7
import graphql.kickstart.tools.util.JavaType
@@ -12,12 +11,15 @@ import graphql.kickstart.tools.util.unwrap
12
11
import graphql.language.*
13
12
import graphql.schema.DataFetcher
14
13
import graphql.schema.DataFetchingEnvironment
14
+ import graphql.schema.GraphQLFieldDefinition
15
15
import graphql.schema.GraphQLTypeUtil.isScalar
16
+ import graphql.schema.LightDataFetcher
16
17
import kotlinx.coroutines.future.future
17
18
import org.slf4j.LoggerFactory
18
19
import java.lang.reflect.InvocationTargetException
19
20
import java.lang.reflect.Method
20
21
import java.util.*
22
+ import java.util.function.Supplier
21
23
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
22
24
import kotlin.reflect.full.valueParameters
23
25
import kotlin.reflect.jvm.javaType
@@ -122,9 +124,9 @@ internal class MethodFieldResolver(
122
124
}
123
125
124
126
return if (args.isEmpty() && isTrivialDataFetcher(this .method)) {
125
- TrivialMethodFieldResolverDataFetcher (getSourceResolver (), this .method, args , options)
127
+ LightMethodFieldResolverDataFetcher (createSourceResolver (), this .method, options)
126
128
} else {
127
- MethodFieldResolverDataFetcher (getSourceResolver (), this .method, args, options)
129
+ MethodFieldResolverDataFetcher (createSourceResolver (), this .method, args, options)
128
130
}
129
131
}
130
132
@@ -203,17 +205,8 @@ internal open class MethodFieldResolverDataFetcher(
203
205
false
204
206
}
205
207
206
- private class CompareGenericWrappers {
207
- companion object : Comparator <GenericWrapper > {
208
- override fun compare (w1 : GenericWrapper , w2 : GenericWrapper ): Int = when {
209
- w1.type.isAssignableFrom(w2.type) -> 1
210
- else -> - 1
211
- }
212
- }
213
- }
214
-
215
208
override fun get (environment : DataFetchingEnvironment ): Any? {
216
- val source = sourceResolver(environment)
209
+ val source = sourceResolver.resolve (environment)
217
210
val args = this .args.map { it(environment) }.toTypedArray()
218
211
219
212
return if (isSuspendFunction) {
@@ -240,18 +233,59 @@ internal open class MethodFieldResolverDataFetcher(
240
233
*/
241
234
@Suppress(" unused" )
242
235
open fun getWrappedFetchingObject (environment : DataFetchingEnvironment ): Any {
243
- return sourceResolver(environment)
236
+ return sourceResolver.resolve (environment)
244
237
}
245
238
}
246
239
247
- // TODO use graphql.schema.LightDataFetcher
248
- internal class TrivialMethodFieldResolverDataFetcher (
249
- sourceResolver : SourceResolver ,
250
- method : Method ,
251
- args : List <ArgumentPlaceholder >,
252
- options : SchemaParserOptions ,
253
- ) : MethodFieldResolverDataFetcher(sourceResolver, method, args, options),
254
- TrivialDataFetcher <Any > // just to mark it for tracing and optimizations
240
+ /* *
241
+ * Similar to [MethodFieldResolverDataFetcher] but for light data fetchers which do not require the environment to be supplied unless suspend functions or
242
+ * generic wrappers are used.
243
+ */
244
+ internal class LightMethodFieldResolverDataFetcher (
245
+ private val sourceResolver : SourceResolver ,
246
+ private val method : Method ,
247
+ private val options : SchemaParserOptions ,
248
+ ) : LightDataFetcher<Any?> {
249
+
250
+ private val resolverMethod = method
251
+ private val isSuspendFunction = try {
252
+ method.kotlinFunction?.isSuspend == true
253
+ } catch (e: InternalError ) {
254
+ false
255
+ }
256
+
257
+ override fun get (fieldDefinition : GraphQLFieldDefinition , sourceObject : Any , environmentSupplier : Supplier <DataFetchingEnvironment >): Any? {
258
+ return if (isSuspendFunction) {
259
+ environmentSupplier.get().coroutineScope().future(options.coroutineContextProvider.provide()) {
260
+ invokeSuspend(sourceObject, resolverMethod, emptyArray())?.transformWithGenericWrapper(environmentSupplier)
261
+ }
262
+ } else {
263
+ invoke(resolverMethod, sourceObject, emptyArray())?.transformWithGenericWrapper(environmentSupplier)
264
+ }
265
+ }
266
+
267
+ private fun Any.transformWithGenericWrapper (environment : Supplier <DataFetchingEnvironment >): Any? {
268
+ return options.genericWrappers
269
+ .asSequence()
270
+ .filter { it.type.isInstance(this ) }
271
+ .sortedWith(CompareGenericWrappers )
272
+ .firstOrNull()
273
+ ?.transformer?.invoke(this , environment.get()) ? : this
274
+ }
275
+
276
+ override fun get (environment : DataFetchingEnvironment ): Any? {
277
+ throw UnsupportedOperationException (" This method should not be called as this is a LightDataFetcher." )
278
+ }
279
+ }
280
+
281
+ private class CompareGenericWrappers {
282
+ companion object : Comparator <GenericWrapper > {
283
+ override fun compare (w1 : GenericWrapper , w2 : GenericWrapper ): Int = when {
284
+ w1.type.isAssignableFrom(w2.type) -> 1
285
+ else -> - 1
286
+ }
287
+ }
288
+ }
255
289
256
290
private suspend inline fun invokeSuspend (target : Any , resolverMethod : Method , args : Array <Any ?>): Any? {
257
291
return suspendCoroutineUninterceptedOrReturn { continuation ->
0 commit comments