|
1 | 1 | package graphql.kickstart.tools |
2 | 2 |
|
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 |
9 | 5 | import graphql.language.Definition |
10 | 6 | import graphql.language.Document |
11 | 7 | import graphql.parser.Parser |
12 | | -import graphql.schema.DataFetchingEnvironment |
13 | 8 | import graphql.schema.GraphQLScalarType |
14 | 9 | import graphql.schema.idl.RuntimeWiring |
15 | 10 | 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 |
21 | 11 | import org.antlr.v4.runtime.RecognitionException |
22 | 12 | 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 |
28 | 13 | import kotlin.reflect.KClass |
29 | 14 |
|
30 | 15 | /** |
31 | 16 | * @author Andrew Potter |
32 | 17 | */ |
33 | | -class SchemaParserBuilder constructor(private val dictionary: SchemaParserDictionary = SchemaParserDictionary()) { |
| 18 | +class SchemaParserBuilder { |
34 | 19 |
|
| 20 | + private val dictionary = SchemaParserDictionary() |
35 | 21 | private val schemaString = StringBuilder() |
36 | 22 | private val files = mutableListOf<String>() |
37 | 23 | private val resolvers = mutableListOf<GraphQLResolver<*>>() |
@@ -215,280 +201,3 @@ class InvalidSchemaError(pce: ParseCancellationException, private val recognitio |
215 | 201 | override val message: String? |
216 | 202 | get() = "Invalid schema provided (${recognitionException.javaClass.name}) at: ${recognitionException.offendingToken}" |
217 | 203 | } |
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