Skip to content

fix(GH-233): Support Inline optional search criteria for singular and plural attributes #251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.introproventures.graphql.jpa.query.schema.impl;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.dataloader.DataLoader;
import org.dataloader.DataLoaderOptions;
import org.dataloader.DataLoaderRegistry;
import org.dataloader.MappedBatchLoaderWithContext;

public class BatchLoaderRegistry {
private final static Map<String, MappedBatchLoaderWithContext<Object, List<Object>>> mappedToManyBatchLoaders = new LinkedHashMap<>();
private final static Map<String, MappedBatchLoaderWithContext<Object, Object>> mappedToOneBatchLoaders = new LinkedHashMap<>();
private static BatchLoaderRegistry instance = new BatchLoaderRegistry();

public static BatchLoaderRegistry getInstance() {
return instance;
}

public static void registerToMany(String batchLoaderKey, MappedBatchLoaderWithContext<Object, List<Object>> mappedBatchLoader) {
mappedToManyBatchLoaders.putIfAbsent(batchLoaderKey, mappedBatchLoader);
}

public static void registerToOne(String batchLoaderKey, MappedBatchLoaderWithContext<Object, Object> mappedBatchLoader) {
mappedToOneBatchLoaders.putIfAbsent(batchLoaderKey, mappedBatchLoader);
}

public static DataLoaderRegistry newDataLoaderRegistry(DataLoaderOptions dataLoaderOptions) {
DataLoaderRegistry dataLoaderRegistry = new DataLoaderRegistry();

mappedToManyBatchLoaders.entrySet()
.forEach(entry -> {
DataLoader<Object, List<Object>> dataLoader = DataLoader.newMappedDataLoader(entry.getValue(),
dataLoaderOptions);
dataLoaderRegistry.register(entry.getKey(), dataLoader);
});

mappedToOneBatchLoaders.entrySet()
.forEach(entry -> {
DataLoader<Object, Object> dataLoader = DataLoader.newMappedDataLoader(entry.getValue(),
dataLoaderOptions);
dataLoaderRegistry.register(entry.getKey(), dataLoader);
});

return dataLoaderRegistry;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,55 +16,98 @@

package com.introproventures.graphql.jpa.query.schema.impl;

import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;

import org.dataloader.DataLoaderRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory;
import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContext;

import graphql.ExecutionInput;
import graphql.GraphQL;
import graphql.GraphQLContext;
import graphql.execution.instrumentation.ChainedInstrumentation;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions;
import graphql.schema.GraphQLCodeRegistry;
import graphql.schema.GraphQLSchema;
import graphql.schema.visibility.GraphqlFieldVisibility;

public class GraphQLJpaExecutorContext implements GraphQLExecutorContext {


private final static Logger logger = LoggerFactory.getLogger(GraphQLJpaExecutorContext.class);

private final GraphQLSchema graphQLSchema;
private final GraphQLExecutionInputFactory executionInputFactory;
private final Supplier<GraphqlFieldVisibility> graphqlFieldVisibility;
private final Supplier<Instrumentation> instrumentation;
private final Supplier<GraphQLContext> graphqlContext;
private final Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions;
private final Supplier<DataLoaderRegistry> dataLoaderRegistry;

private GraphQLJpaExecutorContext(Builder builder) {
this.graphQLSchema = builder.graphQLSchema;
this.executionInputFactory = builder.executionInputFactory;
this.graphqlFieldVisibility = builder.graphqlFieldVisibility;
this.instrumentation = builder.instrumentation;
this.graphqlContext = builder.graphqlContext;
this.dataLoaderDispatcherInstrumentationOptions = builder.dataLoaderDispatcherInstrumentationOptions;
this.dataLoaderRegistry = builder.dataLoaderRegistry;
}

@Override
public ExecutionInput.Builder newExecutionInput() {
DataLoaderRegistry dataLoaderRegistry = newDataLoaderRegistry();

GraphQLContext context = graphqlContext.get();

context.put("dataLoaderRegistry", dataLoaderRegistry);

return executionInputFactory.create()
.context(graphqlContext.get());
.dataLoaderRegistry(dataLoaderRegistry)
.context(context);
}

@Override
public GraphQL.Builder newGraphQL() {
Instrumentation instrumentation = newIstrumentation();

return GraphQL.newGraphQL(getGraphQLSchema())
.instrumentation(instrumentation.get());
.instrumentation(instrumentation);
}

public DataLoaderRegistry newDataLoaderRegistry() {
return dataLoaderRegistry.get();
}

public Instrumentation newIstrumentation() {
DataLoaderDispatcherInstrumentationOptions options = dataLoaderDispatcherInstrumentationOptions.get();

if (logger.isDebugEnabled()) {
options.includeStatistics(true);
}

DataLoaderDispatcherInstrumentation dispatcherInstrumentation = new DataLoaderDispatcherInstrumentation(options);

List<Instrumentation> list = Arrays.asList(dispatcherInstrumentation,
instrumentation.get());

return new ChainedInstrumentation(list);

}

@Override
public GraphQLSchema getGraphQLSchema() {
GraphQLCodeRegistry codeRegistry = graphQLSchema.getCodeRegistry()
.transform(builder -> builder.fieldVisibility(graphqlFieldVisibility.get()));

return graphQLSchema.transform(builder -> builder.codeRegistry(codeRegistry));
}

/**
* Creates builder to build {@link GraphQLJpaExecutorContext}.
* @return created builder
Expand All @@ -85,9 +128,13 @@ public interface IBuildStage {
public IBuildStage graphqlFieldVisibility(Supplier<GraphqlFieldVisibility> graphqlFieldVisibility);

public IBuildStage instrumentation(Supplier<Instrumentation> instrumentation);

public IBuildStage graphqlContext(Supplier<GraphQLContext> graphqlContext);

public IBuildStage dataLoaderDispatcherInstrumentationOptions(Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions);

public IBuildStage dataLoaderRegistry(Supplier<DataLoaderRegistry> dataLoaderRegistry);

public GraphQLJpaExecutorContext build();
}

Expand All @@ -101,6 +148,8 @@ public static final class Builder implements IGraphQLSchemaStage, IBuildStage {
private Supplier<GraphqlFieldVisibility> graphqlFieldVisibility;
private Supplier<Instrumentation> instrumentation;
private Supplier<GraphQLContext> graphqlContext;
private Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions;
private Supplier<DataLoaderRegistry> dataLoaderRegistry;

private Builder() {
}
Expand Down Expand Up @@ -135,10 +184,23 @@ public IBuildStage graphqlContext(Supplier<GraphQLContext> graphqlContext) {
return this;
}

@Override
public IBuildStage dataLoaderDispatcherInstrumentationOptions(Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions) {
this.dataLoaderDispatcherInstrumentationOptions = dataLoaderDispatcherInstrumentationOptions;

return this;
}

@Override
public IBuildStage dataLoaderRegistry(Supplier<DataLoaderRegistry> dataLoaderRegistry) {
this.dataLoaderRegistry = dataLoaderRegistry;

return this;
}

@Override
public GraphQLJpaExecutorContext build() {
return new GraphQLJpaExecutorContext(this);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,46 @@

import java.util.function.Supplier;

import org.dataloader.DataLoaderOptions;
import org.dataloader.DataLoaderRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.introproventures.graphql.jpa.query.schema.GraphQLExecutionInputFactory;
import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContext;
import com.introproventures.graphql.jpa.query.schema.GraphQLExecutorContextFactory;

import graphql.GraphQLContext;
import graphql.execution.instrumentation.Instrumentation;
import graphql.execution.instrumentation.SimpleInstrumentation;
import graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentationOptions;
import graphql.schema.GraphQLSchema;
import graphql.schema.visibility.DefaultGraphqlFieldVisibility;
import graphql.schema.visibility.GraphqlFieldVisibility;

public class GraphQLJpaExecutorContextFactory implements GraphQLExecutorContextFactory {

private final static Logger logger = LoggerFactory.getLogger(GraphQLJpaExecutorContext.class);

private GraphQLExecutionInputFactory executionInputFactory = new GraphQLExecutionInputFactory() {};
private Supplier<GraphqlFieldVisibility> graphqlFieldVisibility = () -> DefaultGraphqlFieldVisibility.DEFAULT_FIELD_VISIBILITY;
private Supplier<Instrumentation> instrumentation = () -> new SimpleInstrumentation();
private Supplier<GraphQLContext> graphqlContext = () -> GraphQLContext.newContext().build();

private Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions = () -> {
return DataLoaderDispatcherInstrumentationOptions.newOptions();
};

private Supplier<DataLoaderOptions> dataLoaderOptions = () -> DataLoaderOptions.newOptions();

private Supplier<DataLoaderRegistry> dataLoaderRegistry = () -> {
DataLoaderOptions options = dataLoaderOptions.get()
.setCachingEnabled(false);

return BatchLoaderRegistry.newDataLoaderRegistry(options);
};


public GraphQLJpaExecutorContextFactory() {
}

@Override
public GraphQLExecutorContext newExecutorContext(GraphQLSchema graphQLSchema) {
return GraphQLJpaExecutorContext.builder()
Expand All @@ -47,6 +66,8 @@ public GraphQLExecutorContext newExecutorContext(GraphQLSchema graphQLSchema) {
.graphqlFieldVisibility(graphqlFieldVisibility)
.instrumentation(instrumentation)
.graphqlContext(graphqlContext)
.dataLoaderDispatcherInstrumentationOptions(dataLoaderDispatcherInstrumentationOptions)
.dataLoaderRegistry(dataLoaderRegistry)
.build();
}

Expand All @@ -55,13 +76,13 @@ public GraphQLJpaExecutorContextFactory withGraphqlFieldVisibility(Supplier<Grap
return this;
}


public GraphQLJpaExecutorContextFactory withInstrumentation(Supplier<Instrumentation> instrumentation) {
this.instrumentation = instrumentation;
return this;
}


public GraphQLJpaExecutorContextFactory withExecutionInputFactory(GraphQLExecutionInputFactory executionInputFactory) {
this.executionInputFactory = executionInputFactory;
return this;
Expand All @@ -71,11 +92,16 @@ public GraphQLJpaExecutorContextFactory withGraphqlContext(Supplier<GraphQLConte
this.graphqlContext = graphqlContext;
return this;
};


public GraphQLJpaExecutorContextFactory withDataLoaderDispatcherInstrumentationOptions(Supplier<DataLoaderDispatcherInstrumentationOptions> dataLoaderDispatcherInstrumentationOptions) {
this.dataLoaderDispatcherInstrumentationOptions = dataLoaderDispatcherInstrumentationOptions;
return this;
}

public GraphQLExecutionInputFactory getExecutionInputFactory() {
return executionInputFactory;
}

public Supplier<GraphqlFieldVisibility> getGraphqlFieldVisibility() {
return graphqlFieldVisibility;
}
Expand All @@ -84,9 +110,13 @@ public Supplier<Instrumentation> getInstrumentation() {
return instrumentation;
}


public Supplier<GraphQLContext> getGraphqlContext() {
return graphqlContext;
}

public Supplier<DataLoaderDispatcherInstrumentationOptions> getDataLoaderDispatcherInstrumentationOptions() {
return dataLoaderDispatcherInstrumentationOptions;
}

}
Loading