All Downloads are FREE. Search and download functionalities are using the official Maven repository.

graphql.nadel.engine.FieldInfos Maven / Gradle / Ivy

Go to download

Nadel is a Java library that combines multiple GrahpQL services together into one API.

The newest version!
package graphql.nadel.engine;

import graphql.Assert;
import graphql.Internal;
import graphql.VisibleForTesting;
import graphql.language.FieldDefinition;
import graphql.language.ObjectTypeDefinition;
import graphql.nadel.Service;
import graphql.nadel.util.FpKit;
import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLNamedType;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLOutputType;
import graphql.schema.GraphQLSchema;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static graphql.nadel.schema.NadelDirectives.NAMESPACED_DIRECTIVE_DEFINITION;

@Internal
public class FieldInfos {

    private final Map fieldInfoByDefinition;

    @VisibleForTesting
    public FieldInfos(Map fieldInfoByDefinition) {
        this.fieldInfoByDefinition = fieldInfoByDefinition;
    }

    public static FieldInfos createFieldsInfos(GraphQLSchema overallSchema, Collection services) {
        Map fieldInfoByDefinition = new LinkedHashMap<>();

        Set namespacedGraphqlTypes = Stream.of(
                overallSchema.getQueryType(),
                overallSchema.getMutationType()
        )
                .filter(Objects::nonNull)
                .flatMap(graphQLObjectType -> graphQLObjectType.getFieldDefinitions().stream())
                .filter(topLevelFieldDef -> !topLevelFieldDef.getDirectives(NAMESPACED_DIRECTIVE_DEFINITION.getName()).isEmpty())
                .map(GraphQLFieldDefinition::getType)
                .collect(Collectors.toSet());

        if (!namespacedGraphqlTypes.isEmpty()) {
            extractNamespacedFieldInfos(fieldInfoByDefinition, namespacedGraphqlTypes, overallSchema, services);
        }

        GraphQLObjectType schemaQueryType = overallSchema.getQueryType();
        GraphQLObjectType schemaMutationType = overallSchema.getMutationType();
        GraphQLObjectType schemaSubscriptionType = overallSchema.getSubscriptionType();
        for (Service service : services) {
            List queryTypeDefinitions = service.getDefinitionRegistry().getQueryType();
            updateFieldInfoMap(fieldInfoByDefinition, schemaQueryType, service, queryTypeDefinitions);

            List mutationTypeDefinitions = service.getDefinitionRegistry().getMutationType();
            updateFieldInfoMap(fieldInfoByDefinition, schemaMutationType, service, mutationTypeDefinitions);

            List subscriptionTypeDefinitions = service.getDefinitionRegistry().getSubscriptionType();
            updateFieldInfoMap(fieldInfoByDefinition, schemaSubscriptionType, service, subscriptionTypeDefinitions);
        }

        return new FieldInfos(fieldInfoByDefinition);
    }

    private static void updateFieldInfoMap(Map fieldInfoByDefinition, GraphQLObjectType schemaQueryType, Service service, List queryType) {
        for (ObjectTypeDefinition objectTypeDefinition : queryType) {
            for (FieldDefinition fieldDefinition : objectTypeDefinition.getFieldDefinitions()) {
                GraphQLFieldDefinition graphQLFieldDefinition = schemaQueryType.getFieldDefinition(fieldDefinition.getName());
                FieldInfo fieldInfo = new FieldInfo(FieldInfo.FieldKind.TOPLEVEL, service, graphQLFieldDefinition);
                fieldInfoByDefinition.put(graphQLFieldDefinition, fieldInfo);
            }
        }
    }

    private static void extractNamespacedFieldInfos(
            Map fieldInfoByDefinition, Set namespacedGraphqlTypes, GraphQLSchema overallSchema, Collection services
    ) {
        for (Service service : services) {
            for (ObjectTypeDefinition typeDefinition : service.getDefinitionRegistry().getDefinitions(ObjectTypeDefinition.class)) {
                boolean isNamespacedDefinition = namespacedGraphqlTypes.stream()
                        .filter(type -> type instanceof GraphQLNamedType)
                        .map(type -> (GraphQLNamedType) type)
                        .anyMatch(type -> type.getName().equals(typeDefinition.getName()));
                if (!isNamespacedDefinition) {
                    continue;
                }
                GraphQLObjectType namespacedGraphQLObjectType = overallSchema.getObjectType(typeDefinition.getName());
                List graphQLFieldDefinitionsWithinNamespacedType = namespacedGraphQLObjectType.getFieldDefinitions();

                List serviceFieldDefinitionsWithinNamespacedType = typeDefinition.getFieldDefinitions();

                for (FieldDefinition serviceSecondLevelFieldDefinition : serviceFieldDefinitionsWithinNamespacedType) {
                    GraphQLFieldDefinition secondLeveGraphqlFieldDefinition = FpKit.findOneOrNull(
                            graphQLFieldDefinitionsWithinNamespacedType,
                            gqlDef -> gqlDef.getName().equals(serviceSecondLevelFieldDefinition.getName())
                    );

                    Assert.assertNotNull(secondLeveGraphqlFieldDefinition,
                            () -> "field definition for a field in a namespaced type is not found in the overall schema");

                    FieldInfo fieldInfo = new FieldInfo(FieldInfo.FieldKind.NAMESPACE_SUBFIELD, service, secondLeveGraphqlFieldDefinition);
                    fieldInfoByDefinition.put(secondLeveGraphqlFieldDefinition, fieldInfo);
                }
            }
        }
    }

    public FieldInfo getInfo(GraphQLFieldDefinition fieldDefinition) {
        return fieldInfoByDefinition.get(fieldDefinition);
    }

    public Map> splitObjectFieldsByServices(GraphQLObjectType namespacedObjectType) {
        return namespacedObjectType.getFieldDefinitions()
                .stream()
                .collect(Collectors.groupingBy(
                        fieldDefinition -> getInfo(fieldDefinition).getService(),
                        Collectors.toSet()));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy