com.apollographql.federation.graphqljava.SchemaTransformer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of federation-graphql-java-support Show documentation
Show all versions of federation-graphql-java-support Show documentation
GraphQL Java server support for Apollo Federation
package com.apollographql.federation.graphqljava;
import static com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.generateServiceSDL;
import static com.apollographql.federation.graphqljava.printer.ServiceSDLPrinter.generateServiceSDLV2;
import graphql.GraphQLError;
import graphql.schema.Coercing;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetcherFactory;
import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLCodeRegistry;
import graphql.schema.GraphQLDirectiveContainer;
import graphql.schema.GraphQLNamedType;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLType;
import graphql.schema.TypeResolver;
import graphql.schema.idl.errors.SchemaProblem;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
public final class SchemaTransformer {
private static final Object serviceObject = new Object();
private final GraphQLSchema originalSchema;
private final boolean queryTypeShouldBeEmpty;
private TypeResolver entityTypeResolver = null;
private DataFetcher entitiesDataFetcher = null;
private DataFetcherFactory entitiesDataFetcherFactory = null;
private Coercing coercingForAny = _Any.defaultCoercing;
private boolean isFederation2 = false;
SchemaTransformer(GraphQLSchema originalSchema, boolean queryTypeShouldBeEmpty) {
this.originalSchema = originalSchema;
this.queryTypeShouldBeEmpty = queryTypeShouldBeEmpty;
}
@NotNull
public SchemaTransformer resolveEntityType(TypeResolver entityTypeResolver) {
this.entityTypeResolver = entityTypeResolver;
return this;
}
@NotNull
public SchemaTransformer fetchEntities(DataFetcher entitiesDataFetcher) {
this.entitiesDataFetcher = entitiesDataFetcher;
this.entitiesDataFetcherFactory = null;
return this;
}
@NotNull
public SchemaTransformer fetchEntitiesFactory(DataFetcherFactory entitiesDataFetcherFactory) {
this.entitiesDataFetcher = null;
this.entitiesDataFetcherFactory = entitiesDataFetcherFactory;
return this;
}
public SchemaTransformer coercingForAny(Coercing coercing) {
this.coercingForAny = coercing;
return this;
}
public SchemaTransformer setFederation2(boolean isFederation2) {
this.isFederation2 = isFederation2;
return this;
}
@NotNull
public final GraphQLSchema build() throws SchemaProblem {
final List errors = new ArrayList<>();
// Make new Schema
final GraphQLSchema.Builder newSchema = GraphQLSchema.newSchema(originalSchema);
final GraphQLObjectType originalQueryType = originalSchema.getQueryType();
final GraphQLObjectType.Builder newQueryType = GraphQLObjectType.newObject(originalQueryType);
if (queryTypeShouldBeEmpty) newQueryType.clearFields();
newQueryType.field(_Service.field);
final Set entityTypeNames = getFederatedEntities();
// If there are entity types install: Query._entities(representations: [_Any!]!): [_Entity]!
if (!entityTypeNames.isEmpty()) {
newQueryType.field(_Entity.field(entityTypeNames));
final GraphQLType originalAnyType = originalSchema.getType(_Any.typeName);
if (originalAnyType == null) {
newSchema.additionalType(_Any.type(coercingForAny));
}
}
newSchema.query(newQueryType.build());
final GraphQLCodeRegistry.Builder newCodeRegistry =
GraphQLCodeRegistry.newCodeRegistry(originalSchema.getCodeRegistry());
if (!entityTypeNames.isEmpty()) {
if (entityTypeResolver != null) {
newCodeRegistry.typeResolver(_Entity.typeName, entityTypeResolver);
} else {
if (!newCodeRegistry.hasTypeResolver(_Entity.typeName)) {
errors.add(new FederationError("Missing a type resolver for _Entity"));
}
}
final FieldCoordinates _entities =
FieldCoordinates.coordinates(originalQueryType.getName(), _Entity.fieldName);
if (entitiesDataFetcher != null) {
newCodeRegistry.dataFetcher(_entities, entitiesDataFetcher);
} else if (entitiesDataFetcherFactory != null) {
newCodeRegistry.dataFetcher(_entities, entitiesDataFetcherFactory);
} else if (!newCodeRegistry.hasDataFetcher(_entities)) {
errors.add(new FederationError("Missing a data fetcher for _entities"));
}
}
if (!errors.isEmpty()) {
throw new SchemaProblem(errors);
}
// expose the schema as _service.sdl
newCodeRegistry.dataFetcher(
FieldCoordinates.coordinates(originalQueryType.getName(), _Service.fieldName),
(DataFetcher