in grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/Schema.groovy [255:529]
GraphQLSchema generate() {
if (!initialized) {
initialize()
}
final String queryTypeName = 'Query'
final String mutationTypeName = 'Mutation'
GraphQLObjectType.Builder queryType = newObject().name(queryTypeName)
GraphQLObjectType.Builder mutationType = newObject().name(mutationTypeName)
Set<PersistentEntity> childrenNotMapped = []
for (MappingContext mappingContext : mappingContexts) {
for (PersistentEntity entity : mappingContext.persistentEntities) {
GraphQLMapping mapping = GraphQLEntityHelper.getMapping(entity)
if (mapping == null) {
if (!entity.root) {
childrenNotMapped.add(entity)
}
continue
} else if (!mapping.operations.all.enabled) {
continue
}
List<GraphQLFieldDefinition.Builder> queryFields = []
List<GraphQLFieldDefinition.Builder> mutationFields = []
final GraphQLOutputType objectType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT)
List<GraphQLFieldDefinition.Builder> requiresIdentityArguments = []
List<Closure> postIdentityExecutables = []
InterceptorInvoker queryInterceptorInvoker = new QueryInterceptorInvoker()
ProvidedOperation queryOperation = mapping.operations.query
ProvidedOperation mutationOperation = mapping.operations.mutation
ProvidedOperation getOperation = mapping.operations.get
if (queryOperation.enabled && getOperation.enabled) {
DataFetcher getFetcher = dataFetcherManager.getReadingFetcher(entity, GET).orElse(new SingleEntityDataFetcher(entity))
final String getFieldName = namingConvention.getGet(entity)
GraphQLFieldDefinition.Builder queryOne = newFieldDefinition()
.name(getFieldName)
.type(objectType)
.description(getOperation.description)
.deprecate(getOperation.deprecationReason)
codeRegistry
.dataFetcher(
coordinates(queryTypeName, getFieldName),
new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, GET, getFetcher)
)
requiresIdentityArguments.add(queryOne)
queryFields.add(queryOne)
}
ListOperation listOperation = mapping.operations.list
if (queryOperation.enabled && listOperation.enabled) {
DataFetcher listFetcher = dataFetcherManager.getReadingFetcher(entity, LIST).orElse(null)
final String listFieldName = namingConvention.getList(entity)
GraphQLFieldDefinition.Builder queryAll = newFieldDefinition()
.name(listFieldName)
.description(listOperation.description)
.deprecate(listOperation.deprecationReason)
GraphQLOutputType listOutputType
if (listOperation.paginate) {
if (listFetcher == null) {
listFetcher = new PaginatedEntityDataFetcher(entity)
}
listOutputType = typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT_PAGED)
} else {
if (listFetcher == null) {
listFetcher = new EntityDataFetcher(entity)
}
listOutputType = list(objectType)
}
queryAll.type(listOutputType)
if (listFetcher instanceof PaginatingGormDataFetcher) {
((PaginatingGormDataFetcher) listFetcher).responseHandler = paginationResponseHandler
}
codeRegistry.dataFetcher(
coordinates(queryTypeName, listFieldName),
new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, LIST, listFetcher)
)
queryFields.add(queryAll)
for (Map.Entry<String, GraphQLInputType> argument : listArguments) {
queryAll.argument(
newArgument()
.name(argument.key)
.type(argument.value))
}
}
ProvidedOperation countOperation = mapping.operations.count
if (queryOperation.enabled && countOperation.enabled) {
DataFetcher countFetcher = dataFetcherManager.getReadingFetcher(entity, COUNT).orElse(new CountEntityDataFetcher(entity))
final String countFieldName = namingConvention.getCount(entity)
final GraphQLOutputType countOutputType = (GraphQLOutputType) typeManager.getType(Integer)
GraphQLFieldDefinition.Builder queryCount = newFieldDefinition()
.name(countFieldName)
.type(countOutputType)
.description(countOperation.description)
.deprecate(countOperation.deprecationReason)
codeRegistry.dataFetcher(
coordinates(queryTypeName, countFieldName),
new InterceptingDataFetcher(entity, serviceManager, queryInterceptorInvoker, COUNT, countFetcher)
)
queryFields.add(queryCount)
}
InterceptorInvoker mutationInterceptorInvoker = new MutationInterceptorInvoker()
GraphQLDataBinder dataBinder = dataBinderManager.getDataBinder(entity.javaClass)
ProvidedOperation createOperation = mapping.operations.create
if (mutationOperation.enabled && createOperation.enabled && !Modifier.isAbstract(entity.javaClass.modifiers)) {
if (dataBinder == null) {
throw new DataBinderNotFoundException(entity)
}
GraphQLInputType createObjectType = typeManager.getMutationType(entity, GraphQLPropertyType.CREATE, true)
if (!createObjectType.children.empty) {
BindingGormDataFetcher createFetcher = dataFetcherManager.getBindingFetcher(entity, CREATE).orElse(new CreateEntityDataFetcher(entity))
createFetcher.dataBinder = dataBinder
final String createFieldName = namingConvention.getCreate(entity)
GraphQLFieldDefinition.Builder create = newFieldDefinition()
.name(createFieldName)
.type(objectType)
.description(createOperation.description)
.deprecate(createOperation.deprecationReason)
.argument(newArgument()
.name(entity.decapitalizedName)
.type(createObjectType))
codeRegistry.dataFetcher(
coordinates(mutationTypeName, createFieldName),
new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, CREATE, createFetcher)
)
mutationFields.add(create)
}
}
ProvidedOperation updateOperation = mapping.operations.update
if (mutationOperation.enabled && updateOperation.enabled) {
if (dataBinder == null) {
throw new DataBinderNotFoundException(entity)
}
GraphQLInputType updateObjectType = typeManager.getMutationType(entity, GraphQLPropertyType.UPDATE, true)
BindingGormDataFetcher updateFetcher = dataFetcherManager.getBindingFetcher(entity, UPDATE).orElse(new UpdateEntityDataFetcher(entity))
updateFetcher.dataBinder = dataBinder
final String updateFieldName = namingConvention.getUpdate(entity)
GraphQLFieldDefinition.Builder update = newFieldDefinition()
.name(updateFieldName)
.type(objectType)
.description(updateOperation.description)
.deprecate(updateOperation.deprecationReason)
codeRegistry.dataFetcher(
coordinates(mutationTypeName, updateFieldName),
new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, UPDATE, updateFetcher)
)
postIdentityExecutables.add {
update.argument(newArgument()
.name(entity.decapitalizedName)
.type(updateObjectType))
}
requiresIdentityArguments.add(update)
mutationFields.add(update)
}
ProvidedOperation deleteOperation = mapping.operations.delete
if (mutationOperation.enabled && deleteOperation.enabled) {
DeletingGormDataFetcher deleteFetcher = dataFetcherManager.getDeletingFetcher(entity).orElse(new DeleteEntityDataFetcher(entity))
deleteFetcher.responseHandler = deleteResponseHandler
final String deleteFieldName = namingConvention.getDelete(entity)
final GraphQLObjectType deleteObjectType = deleteResponseHandler.getObjectType(typeManager)
GraphQLFieldDefinition.Builder delete = newFieldDefinition()
.name(deleteFieldName)
.type(deleteObjectType)
.description(deleteOperation.description)
.deprecate(deleteOperation.deprecationReason)
codeRegistry.dataFetcher(
coordinates(mutationTypeName, deleteFieldName),
new InterceptingDataFetcher(entity, serviceManager, mutationInterceptorInvoker, DELETE, deleteFetcher)
)
requiresIdentityArguments.add(delete)
mutationFields.add(delete)
}
final GraphQLFieldDefinition.Builder[] builders = requiresIdentityArguments as GraphQLFieldDefinition.Builder[]
populateIdentityArguments(entity, builders)
for (Closure c : postIdentityExecutables) {
c.call()
}
for (CustomOperation operation : mapping.customQueryOperations) {
queryFields.add(operation.createField(entity, serviceManager, mappingContext, listArguments))
}
for (CustomOperation operation : mapping.customMutationOperations) {
mutationFields.add(operation.createField(entity, serviceManager, mappingContext, Collections.emptyMap()))
}
for (GraphQLSchemaInterceptor schemaInterceptor : interceptorManager.interceptors) {
schemaInterceptor.interceptEntity(entity, queryFields, mutationFields)
}
queryType.fields((List<GraphQLFieldDefinition>) queryFields*.build())
mutationType.fields((List<GraphQLFieldDefinition>) mutationFields*.build())
}
}
Set<GraphQLType> additionalTypes = []
for (PersistentEntity entity : childrenNotMapped) {
GraphQLMapping mapping = GraphQLEntityHelper.getMapping(entity.rootEntity)
if (mapping == null) {
continue
}
additionalTypes.add(typeManager.getQueryType(entity, GraphQLPropertyType.OUTPUT))
}
for (GraphQLSchemaInterceptor schemaInterceptor : interceptorManager.interceptors) {
schemaInterceptor.interceptSchema(queryType, mutationType, additionalTypes)
}
GraphQLSchema.Builder schema = GraphQLSchema.newSchema()
.codeRegistry(codeRegistry.build())
.additionalTypes(additionalTypes)
GraphQLObjectType mutation = mutationType.build()
if (mutation.fieldDefinitions) {
schema.mutation(mutation)
}
GraphQLObjectType query = queryType.build()
if (query.fieldDefinitions) {
schema.query(query)
return schema.build()
}
}