Skip to content

Commit 9ef5836

Browse files
authored
Merge pull request #245 from yarinvak/feature/upgrade-to-gql-java-14
upgrade to gql java 14
2 parents 1d889b3 + 99a16cb commit 9ef5836

25 files changed

+536
-812
lines changed

LICENSE

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
Copyright 2016 Yurii Rashkovskii
2-
31
Licensed under the Apache License, Version 2.0 (the "License");
42
you may not use this file except in compliance with the License.
53
You may obtain a copy of the License at

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ gradle.projectsEvaluated {
6363

6464
dependencies {
6565
compile 'javax.validation:validation-api:1.1.0.Final'
66-
compile 'com.graphql-java:graphql-java:13.0'
66+
compile 'com.graphql-java:graphql-java:14.0'
6767

6868
// OSGi
6969
compileOnly 'org.osgi:org.osgi.core:6.0.0'

src/main/java/graphql/annotations/AnnotationsSchemaCreator.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
/**
2-
* Copyright 2016 Yurii Rashkovskii
3-
*
42
* Licensed under the Apache License, Version 2.0 (the "License");
53
* you may not use this file except in compliance with the License.
64
* You may obtain a copy of the License at
@@ -14,17 +12,23 @@
1412
*/
1513
package graphql.annotations;
1614

15+
import graphql.annotations.directives.AnnotationsDirectiveWiring;
16+
import graphql.annotations.directives.DirectiveSchemaVisitor;
17+
import graphql.annotations.directives.TreeTransformerUtilWrapper;
18+
import graphql.annotations.processor.DirectiveAndWiring;
1719
import graphql.annotations.processor.GraphQLAnnotations;
1820
import graphql.annotations.processor.typeFunctions.TypeFunction;
1921
import graphql.relay.Relay;
2022
import graphql.schema.GraphQLDirective;
2123
import graphql.schema.GraphQLSchema;
2224
import graphql.schema.GraphQLType;
25+
import graphql.schema.SchemaTransformer;
2326

24-
import java.util.HashSet;
25-
import java.util.Set;
27+
import java.util.*;
2628
import java.util.stream.Collectors;
2729

30+
import static graphql.schema.GraphQLSchema.newSchema;
31+
2832
public class AnnotationsSchemaCreator {
2933

3034
public static Builder newAnnotationsSchema() {
@@ -43,6 +47,7 @@ public static class Builder {
4347
private Boolean shouldAlwaysPrettify = null;
4448
private GraphQLAnnotations graphQLAnnotations;
4549
private GraphQLSchema.Builder graphqlSchemaBuilder;
50+
private SchemaTransformer schemaTransformer = new SchemaTransformer();
4651

4752
/**
4853
* You can set your own schema builder, but its optional
@@ -114,12 +119,18 @@ public Builder directives(Set<Class<?>> directiveClasses) {
114119
return this;
115120
}
116121

122+
public Builder directives(Class<?>... directiveClasses) {
123+
this.directivesObjectList.addAll(Arrays.asList(directiveClasses));
124+
return this;
125+
}
126+
117127
/**
118128
* Add directive declaration class to create directives for the graphql schema
129+
*
119130
* @param directiveContainerClass a directive container class (directives are defined as methods inside the class)
120131
* @return the builder after adding the directive container class to the list of directive container classes
121132
*/
122-
public Builder directives(Class<?> directiveContainerClass){
133+
public Builder directives(Class<?> directiveContainerClass) {
123134
this.directiveContainerClasses.add(directiveContainerClass);
124135
return this;
125136
}
@@ -234,7 +245,7 @@ public GraphQLSchema build() {
234245
}
235246

236247
Set<GraphQLDirective> directives = directivesObjectList.stream().map(dir -> graphQLAnnotations.directive(dir)).collect(Collectors.toSet());
237-
directiveContainerClasses.forEach(dir->directives.addAll(graphQLAnnotations.directives(dir)));
248+
directiveContainerClasses.forEach(dir -> directives.addAll(graphQLAnnotations.directives(dir)));
238249

239250
Set<GraphQLType> additionalTypes = additionalTypesList.stream().map(additionalType ->
240251
additionalType.isInterface() ?
@@ -252,7 +263,26 @@ public GraphQLSchema build() {
252263
}
253264
this.graphqlSchemaBuilder.additionalTypes(additionalTypes).additionalType(Relay.pageInfoType)
254265
.codeRegistry(graphQLAnnotations.getContainer().getCodeRegistryBuilder().build());
255-
return this.graphqlSchemaBuilder.build();
266+
GraphQLSchema schema = this.graphqlSchemaBuilder.build();
267+
// wire with directives
268+
HashMap<String, AnnotationsDirectiveWiring> directiveWiringHashMap = transformDirectiveRegistry(this.graphQLAnnotations.getContainer().getDirectiveRegistry());
269+
DirectiveSchemaVisitor directiveSchemaVisitor = new DirectiveSchemaVisitor(directiveWiringHashMap,
270+
graphQLAnnotations.getContainer().getCodeRegistryBuilder(), new TreeTransformerUtilWrapper());
271+
GraphQLSchema transformedSchema = this.schemaTransformer.transform(schema, directiveSchemaVisitor);
272+
return newSchema(transformedSchema).codeRegistry(graphQLAnnotations.getContainer().getCodeRegistryBuilder().build()).build();
273+
}
274+
275+
private HashMap<String, AnnotationsDirectiveWiring> transformDirectiveRegistry(Map<String, DirectiveAndWiring> directiveRegistry) {
276+
HashMap<String, AnnotationsDirectiveWiring> map = new HashMap<>();
277+
directiveRegistry.forEach((directiveName, directiveAndWiring) -> {
278+
try {
279+
map.put(directiveName, directiveAndWiring.getWiringClass().newInstance());
280+
} catch (Exception e) {
281+
throw new RuntimeException(e);
282+
}
283+
});
284+
285+
return map;
256286
}
257287
}
258288
}

src/main/java/graphql/annotations/directives/AnnotationsWiringEnvironment.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import graphql.schema.GraphQLCodeRegistry;
1818
import graphql.schema.GraphQLDirective;
1919
import graphql.schema.GraphQLDirectiveContainer;
20+
import graphql.schema.GraphQLSchemaElement;
2021

2122
public interface AnnotationsWiringEnvironment {
2223
/**
@@ -33,7 +34,7 @@ public interface AnnotationsWiringEnvironment {
3334
*
3435
* @return the parent name of the element
3536
*/
36-
String getParentName();
37+
GraphQLSchemaElement getParentElement();
3738

3839

3940
/**

src/main/java/graphql/annotations/directives/AnnotationsWiringEnvironmentImpl.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,19 @@
1717
import graphql.schema.GraphQLCodeRegistry;
1818
import graphql.schema.GraphQLDirective;
1919
import graphql.schema.GraphQLDirectiveContainer;
20+
import graphql.schema.GraphQLSchemaElement;
2021

2122
public class AnnotationsWiringEnvironmentImpl implements AnnotationsWiringEnvironment {
2223
private final GraphQLDirectiveContainer element;
2324
private final GraphQLDirective directive;
24-
private final String parentName;
25+
private final GraphQLSchemaElement parentElement;
2526
private GraphQLCodeRegistry.Builder codeRegistryBuilder;
2627

2728
public AnnotationsWiringEnvironmentImpl(GraphQLDirectiveContainer element, GraphQLDirective directive,
28-
String parentName, GraphQLCodeRegistry.Builder codeRegistryBuilder) {
29+
GraphQLSchemaElement parentElement, GraphQLCodeRegistry.Builder codeRegistryBuilder) {
2930
this.element = element;
3031
this.directive = directive;
31-
this.parentName = parentName;
32+
this.parentElement = parentElement;
3233
this.codeRegistryBuilder = codeRegistryBuilder;
3334
}
3435

@@ -43,8 +44,8 @@ public GraphQLDirective getDirective() {
4344
}
4445

4546
@Override
46-
public String getParentName() {
47-
return parentName;
47+
public GraphQLSchemaElement getParentElement() {
48+
return parentElement;
4849
}
4950

5051
@Override
@@ -60,7 +61,7 @@ public boolean equals(Object o) {
6061
AnnotationsWiringEnvironmentImpl that = (AnnotationsWiringEnvironmentImpl) o;
6162

6263
if (element != null ? !element.equals(that.element) : that.element != null) return false;
63-
if (parentName != null ? !parentName.equals(that.parentName) : that.parentName != null) return false;
64+
if (parentElement != null ? !parentElement.equals(that.parentElement) : that.parentElement != null) return false;
6465
if (codeRegistryBuilder != null ? !codeRegistryBuilder.equals(that.codeRegistryBuilder) : that.codeRegistryBuilder != null)
6566
return false;
6667
return directive != null ? directive.equals(that.directive) : that.directive == null;
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/**
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
*/
13+
/**
14+
* Licensed under the Apache License, Version 2.0 (the "License");
15+
* you may not use this file except in compliance with the License.
16+
* You may obtain a copy of the License at
17+
* <p>
18+
* http://www.apache.org/licenses/LICENSE-2.0
19+
* <p>
20+
* Unless required by applicable law or agreed to in writing, software
21+
* distributed under the License is distributed on an "AS IS" BASIS,
22+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23+
* See the License for the specific language governing permissions and
24+
*/
25+
package graphql.annotations.directives;
26+
27+
import graphql.introspection.Introspection;
28+
import graphql.schema.*;
29+
import graphql.util.TraversalControl;
30+
import graphql.util.TraverserContext;
31+
32+
import java.lang.reflect.InvocationTargetException;
33+
import java.util.Arrays;
34+
import java.util.HashMap;
35+
import java.util.List;
36+
import java.util.Map;
37+
38+
public class DirectiveSchemaVisitor implements GraphQLTypeVisitor {
39+
private HashMap<String, AnnotationsDirectiveWiring> directiveWiringMap;
40+
private GraphQLCodeRegistry.Builder codeRegistryBuilder;
41+
private TreeTransformerUtilWrapper transformerUtilWrapper;
42+
43+
@FunctionalInterface
44+
interface WiringFunction {
45+
GraphQLDirectiveContainer apply(GraphQLDirective a, GraphQLDirectiveContainer b,
46+
AnnotationsDirectiveWiring wiring, GraphQLSchemaElement parentElement)
47+
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException;
48+
}
49+
50+
private Map<Class, WiringFunction> functionMap;
51+
52+
53+
public DirectiveSchemaVisitor(HashMap<String, AnnotationsDirectiveWiring> directiveWiringMap, GraphQLCodeRegistry.Builder codeRegistryBuilder,
54+
TreeTransformerUtilWrapper treeTransformerUtilWrapper) {
55+
this.directiveWiringMap = directiveWiringMap;
56+
this.functionMap = createFunctionsMap();
57+
this.codeRegistryBuilder = codeRegistryBuilder;
58+
this.transformerUtilWrapper = treeTransformerUtilWrapper;
59+
}
60+
61+
@Override
62+
public TraversalControl visitGraphQLArgument(GraphQLArgument node, TraverserContext<GraphQLSchemaElement> context) {
63+
return this.visitGraphQLType(GraphQLArgument.class, node, context);
64+
}
65+
66+
@Override
67+
public TraversalControl visitGraphQLInterfaceType(GraphQLInterfaceType node, TraverserContext<GraphQLSchemaElement> context) {
68+
return this.visitGraphQLType(GraphQLInterfaceType.class, node, context);
69+
}
70+
71+
@Override
72+
public TraversalControl visitGraphQLEnumType(GraphQLEnumType node, TraverserContext<GraphQLSchemaElement> context) {
73+
return this.visitGraphQLType(GraphQLEnumType.class, node, context);
74+
}
75+
76+
@Override
77+
public TraversalControl visitGraphQLEnumValueDefinition(GraphQLEnumValueDefinition node, TraverserContext<GraphQLSchemaElement> context) {
78+
return this.visitGraphQLType(GraphQLEnumValueDefinition.class, node, context);
79+
}
80+
81+
@Override
82+
public TraversalControl visitGraphQLFieldDefinition(GraphQLFieldDefinition node, TraverserContext<GraphQLSchemaElement> context) {
83+
return this.visitGraphQLType(GraphQLFieldDefinition.class, node, context);
84+
}
85+
86+
@Override
87+
public TraversalControl visitGraphQLDirective(GraphQLDirective node, TraverserContext<GraphQLSchemaElement> context) {
88+
return TraversalControl.CONTINUE;
89+
}
90+
91+
@Override
92+
public TraversalControl visitGraphQLInputObjectField(GraphQLInputObjectField node, TraverserContext<GraphQLSchemaElement> context) {
93+
return this.visitGraphQLType(GraphQLInputObjectField.class, node, context);
94+
}
95+
96+
@Override
97+
public TraversalControl visitGraphQLInputObjectType(GraphQLInputObjectType node, TraverserContext<GraphQLSchemaElement> context) {
98+
return this.visitGraphQLType(GraphQLInputObjectType.class, node, context);
99+
}
100+
101+
@Override
102+
public TraversalControl visitGraphQLList(GraphQLList node, TraverserContext<GraphQLSchemaElement> context) {
103+
return TraversalControl.CONTINUE;
104+
}
105+
106+
@Override
107+
public TraversalControl visitGraphQLNonNull(GraphQLNonNull node, TraverserContext<GraphQLSchemaElement> context) {
108+
return TraversalControl.CONTINUE;
109+
}
110+
111+
@Override
112+
public TraversalControl visitGraphQLObjectType(GraphQLObjectType node, TraverserContext<GraphQLSchemaElement> context) {
113+
return this.visitGraphQLType(GraphQLObjectType.class, node, context);
114+
}
115+
116+
@Override
117+
public TraversalControl visitGraphQLScalarType(GraphQLScalarType node, TraverserContext<GraphQLSchemaElement> context) {
118+
return this.visitGraphQLType(GraphQLScalarType.class, node, context);
119+
}
120+
121+
@Override
122+
public TraversalControl visitGraphQLTypeReference(GraphQLTypeReference node, TraverserContext<GraphQLSchemaElement> context) {
123+
return TraversalControl.CONTINUE;
124+
}
125+
126+
@Override
127+
public TraversalControl visitGraphQLUnionType(GraphQLUnionType node, TraverserContext<GraphQLSchemaElement> context) {
128+
return this.visitGraphQLType(GraphQLUnionType.class, node, context);
129+
}
130+
131+
private TraversalControl visitGraphQLType(Class<? extends GraphQLDirectiveContainer> typeOfContainer,
132+
GraphQLDirectiveContainer node, TraverserContext<GraphQLSchemaElement> context) {
133+
List<GraphQLDirective> directives = node.getDirectives();
134+
if (directives.size() == 0) {
135+
return TraversalControl.CONTINUE;
136+
}
137+
GraphQLDirectiveContainer newNode = node;
138+
for (GraphQLDirective directive : directives) {
139+
AnnotationsDirectiveWiring wiring = this.directiveWiringMap.get(directive.getName());
140+
if (wiring != null) {
141+
try {
142+
GraphQLSchemaElement parentElement = context.getParentNode();
143+
newNode = functionMap.get(typeOfContainer).apply(directive, newNode,
144+
wiring, parentElement);
145+
} catch (Exception e) {
146+
throw new RuntimeException(e);
147+
}
148+
}
149+
}
150+
return transformerUtilWrapper.changeNode(context, newNode);
151+
}
152+
153+
private void putInMap(Map<Class, WiringFunction> map, Class clazz, String functionName,
154+
Introspection.DirectiveLocation... locations) {
155+
map.put(clazz, (d, e, wiring, parentElement) -> {
156+
assertLocation(d, e, locations);
157+
AnnotationsWiringEnvironmentImpl environment =
158+
new AnnotationsWiringEnvironmentImpl(e, e.getDirective(d.getName()), parentElement, codeRegistryBuilder);
159+
return (GraphQLDirectiveContainer) wiring.getClass().getMethod(functionName, AnnotationsWiringEnvironment.class)
160+
.invoke(wiring, environment);
161+
});
162+
}
163+
164+
private Map<Class, WiringFunction> createFunctionsMap() {
165+
Map<Class, WiringFunction> functionMap = new HashMap<>();
166+
putInMap(functionMap, GraphQLFieldDefinition.class, "onField", Introspection.DirectiveLocation.FIELD, Introspection.DirectiveLocation.FIELD_DEFINITION);
167+
putInMap(functionMap, GraphQLObjectType.class, "onObject", Introspection.DirectiveLocation.OBJECT);
168+
putInMap(functionMap, GraphQLArgument.class, "onArgument", Introspection.DirectiveLocation.ARGUMENT_DEFINITION);
169+
putInMap(functionMap, GraphQLInterfaceType.class, "onInterface", Introspection.DirectiveLocation.INTERFACE);
170+
putInMap(functionMap, GraphQLUnionType.class, "onUnion", Introspection.DirectiveLocation.UNION);
171+
putInMap(functionMap, GraphQLEnumType.class, "onEnum", Introspection.DirectiveLocation.ENUM);
172+
putInMap(functionMap, GraphQLEnumValueDefinition.class, "onEnumValue", Introspection.DirectiveLocation.ENUM_VALUE);
173+
putInMap(functionMap, GraphQLScalarType.class, "onScalar", Introspection.DirectiveLocation.SCALAR);
174+
putInMap(functionMap, GraphQLInputObjectType.class, "onInputObjectType", Introspection.DirectiveLocation.INPUT_OBJECT);
175+
putInMap(functionMap, GraphQLInputObjectField.class, "onInputObjectField", Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION);
176+
177+
return functionMap;
178+
}
179+
180+
private void assertLocation(GraphQLDirective graphQLDirective, GraphQLDirectiveContainer element, Introspection.DirectiveLocation... validLocations) {
181+
boolean isSupported = false;
182+
for (Introspection.DirectiveLocation validLocation : validLocations) {
183+
if (graphQLDirective.validLocations().contains(validLocation)) {
184+
isSupported = true;
185+
}
186+
}
187+
if (!isSupported) {
188+
throw getInvalidDirectiveLocationException(element, graphQLDirective, validLocations);
189+
}
190+
}
191+
192+
private InvalidDirectiveLocationException getInvalidDirectiveLocationException(GraphQLDirectiveContainer element, GraphQLDirective graphQLDirective, Introspection.DirectiveLocation... validLocations) {
193+
return new InvalidDirectiveLocationException("The element: '" + element.getName() + "' is annotated with the directive: '"
194+
+ graphQLDirective.getName() + "' which is not valid on the element location: '" + Arrays.toString(Arrays.stream(validLocations).map(Enum::name).toArray()) + "'", null);
195+
}
196+
}

0 commit comments

Comments
 (0)