Skip to content

Commit 5f8ba01

Browse files
committed
2 parents 40819a1 + 0d3016d commit 5f8ba01

33 files changed

+1079
-181
lines changed

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,45 @@ GraphQLInterfaceType object = GraphQLAnnotations.iface(SomeInterface.class);
5454
An instance of the type resolver will be created from the specified class. If a `getInstance` method is present on the
5555
class, it will be used instead of the default constructor.
5656

57+
## Defining Unions
58+
59+
To have a union, you must annotate an interface with `@GraphQLUnion`. In the annotation, you must declare all the
60+
possible types of the union, and a type resolver.
61+
If no type resolver is specified, `UnionTypeResovler` is used. It follows this algorithm:
62+
The resolver assumes the the DB entity's name is the same as the API entity's name.
63+
If so, it takes the result from the dataFetcher and decides to which
64+
API entity it should be mapped (according to the name).
65+
Example: If you have a `Pet` union type, and the dataFetcher returns `Dog`, the typeResolver
66+
will check for each API entity if its name is equal to `Dog`, and returns if it finds something
67+
68+
```java
69+
@GraphQLUnion(possibleTypes={Dog.class, Cat.class})
70+
public interface Pet {}
71+
```
72+
and an example with custom `TypeResovler`:
73+
```java
74+
@GraphQLUnion(possibleTypes={DogApi.class, Cat.class}, typeResolver = PetTypeResolver.class)
75+
public interface Pet {}
76+
77+
78+
public class PetTypeResolver implements TypeResolver {
79+
@Override
80+
GraphQLObjectType getType(TypeResolutionEnvironment env) {
81+
Object obj = env.getObject();
82+
if(obj instanceof DogDB) {
83+
return (GraphQLObjectType) env.getSchema().getType("DogApi");
84+
}
85+
else {
86+
return (GraphQLObjectType) env.getSchema().getType("Cat");
87+
}
88+
89+
}
90+
}
91+
```
92+
NOTE: you can have (but not mandatory) a type resolver with constructor that has `Class<?>[]` as the first parameter and
93+
`ProcessingElementsContainer` as the second. the `Class<?>[]` parameter contains the possibleTypes class
94+
and `ProcessingElementsContainer` has all sorts of utils (you can check `UnionTypeResolver` to see how we use it there)
95+
5796
## Fields
5897

5998
In addition to specifying a field over a Java class field, a field can be defined over a method:
@@ -268,3 +307,17 @@ NOTE: because `PropertyDataFetcher` and `FieldDataFetcher` can't handle connecti
268307
By default, GraphQLAnnotations will use the `graphql.relay.Relay` class to create the Relay specific schema types (Mutations, Connections, Edges, PageInfo, ...).
269308
It is possible to set a custom implementation of the Relay class with `GraphQLAnnotations.setRelay` method. The class should inherit from `graphql.relay.Relay` and
270309
can redefine methods that create Relay types.
310+
311+
It is also possible to specify for every connection which relay do you want to use, by giving a value to the annotation:
312+
`@GraphQLConnection(connectionType = customRelay.class)`. If you do that, please also give values to `connectionFetcher`
313+
and `validator`.
314+
315+
There is also a support for simple paging, without "Nodes" and "Edges". To use it, annotate you connection like that:
316+
`@GraphQLConnection(connectionFetcher = SimplePaginatedDataConnectionFetcher.class, connectionType = SimpleRelay.class, validator = SimplePaginatedDataConnectionTypeValidator.class)`
317+
and the return type must be of type `SimplePaginatedData`.
318+
It has 2 methods:
319+
1. `getTotalCount` - how many elements are there in total
320+
2. `getData` - get the data
321+
322+
For you convenience, there are two classes that you can use: `AbstractSimplePaginatedData` and `SimplePaginatedDataImpl`
323+
For examples, look at the tests

build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ buildscript {
1111
}
1212
}
1313
plugins {
14-
id "com.github.hierynomus.license" version "0.12.1"
1514
id "com.jfrog.bintray" version "1.7"
1615
id 'net.researchgate.release' version '2.3.4'
16+
id "com.github.hierynomus.license" version "0.14.0"
1717
}
1818

1919
apply plugin: 'java'
@@ -69,7 +69,7 @@ gradle.projectsEvaluated {
6969

7070
dependencies {
7171
compile 'javax.validation:validation-api:1.1.0.Final'
72-
compile 'com.graphql-java:graphql-java:7.0'
72+
compile 'com.graphql-java:graphql-java:8.0'
7373

7474
// OSGi
7575
compileOnly 'org.osgi:org.osgi.core:6.0.0'
@@ -78,6 +78,7 @@ dependencies {
7878
compileOnly 'biz.aQute.bnd:biz.aQute.bndlib:3.2.0'
7979

8080
testCompile 'org.testng:testng:6.9.10'
81+
testCompile 'org.hamcrest:hamcrest-all:1.3'
8182
}
8283

8384
test.useTestNG()

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ org.gradle.jvmargs=-Dfile.encoding=UTF-8
77

88
bintray.user=DUMMY_USER
99
bintray.key=DUMMY_KEY
10+
version = 5.2

src/main/java/graphql/annotations/GraphQLFieldDefinitionWrapper.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import graphql.schema.DataFetcherFactories;
1919
import graphql.schema.GraphQLFieldDefinition;
2020

21-
public class GraphQLFieldDefinitionWrapper extends GraphQLFieldDefinition {
21+
public class GraphQLFieldDefinitionWrapper extends GraphQLFieldDefinition {
2222

2323
public GraphQLFieldDefinitionWrapper(GraphQLFieldDefinition fieldDefinition) {
2424
super(fieldDefinition.getName(), fieldDefinition.getDescription(), fieldDefinition.getType(),
25-
DataFetcherFactories.useDataFetcher((DataFetcher<?>)fieldDefinition.getDataFetcher()), fieldDefinition.getArguments(), fieldDefinition.getDeprecationReason(),
25+
DataFetcherFactories.useDataFetcher((DataFetcher<?>) fieldDefinition.getDataFetcher()),
26+
fieldDefinition.getArguments(), fieldDefinition.getDeprecationReason(),
27+
fieldDefinition.getDirectives(),
2628
fieldDefinition.getDefinition());
2729
}
2830

src/main/java/graphql/annotations/annotationTypes/GraphQLUnion.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
*/
1515
package graphql.annotations.annotationTypes;
1616

17+
import graphql.annotations.typeResolvers.UnionTypeResolver;
18+
import graphql.schema.TypeResolver;
19+
1720
import java.lang.annotation.ElementType;
1821
import java.lang.annotation.Retention;
1922
import java.lang.annotation.RetentionPolicy;
@@ -23,4 +26,6 @@
2326
@Retention(RetentionPolicy.RUNTIME)
2427
public @interface GraphQLUnion {
2528
Class<?>[] possibleTypes();
29+
30+
Class<? extends TypeResolver> typeResolver() default UnionTypeResolver.class;
2631
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright 2016 Yurii Rashkovskii
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
*/
15+
package graphql.annotations.connection;
16+
17+
import graphql.relay.Relay;
18+
19+
/**
20+
* This class is just for the library to know whether to use the relay in the container or not
21+
*/
22+
public final class FakeRelay extends Relay {
23+
}

src/main/java/graphql/annotations/connection/GraphQLConnection.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package graphql.annotations.connection;
1616

1717

18+
import graphql.relay.Relay;
19+
1820
import java.lang.annotation.ElementType;
1921
import java.lang.annotation.Retention;
2022
import java.lang.annotation.RetentionPolicy;
@@ -27,7 +29,7 @@
2729
*
2830
* At the moment, the only allowed type for such field is <code>List&lt;?&gt;</code>
2931
*/
30-
@Target({ElementType.FIELD, ElementType.METHOD})
32+
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
3133
@Retention(RetentionPolicy.RUNTIME)
3234
public @interface GraphQLConnection {
3335
/**
@@ -37,7 +39,7 @@
3739
* your own connection validator
3840
* @return a connection class
3941
*/
40-
Class<? extends ConnectionFetcher> connection() default PaginatedDataConnectionFetcher.class;
42+
Class<? extends ConnectionFetcher> connectionFetcher() default PaginatedDataConnectionFetcher.class;
4143

4244
/**
4345
* By default, wrapped type's name is used for naming TypeConnection, but can be overridden
@@ -59,4 +61,12 @@
5961
* @return if async fetching to be used.
6062
*/
6163
boolean async() default false;
64+
65+
/**
66+
* By default, the relay connection that the container has is used. If you want to change the way connection works
67+
* (For example, you don't want edges and nodes), override the {@link Relay} class and specify it.
68+
*
69+
* @return a class that represents the connection type
70+
*/
71+
Class<? extends Relay> connectionType() default FakeRelay.class;
6272
}

src/main/java/graphql/annotations/connection/SimplePaginatedData.java renamed to src/main/java/graphql/annotations/connection/NaivePaginatedData.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919

2020
import static java.util.Base64.getEncoder;
2121

22-
public class SimplePaginatedData<T> extends AbstractPaginatedData<T> {
22+
public class NaivePaginatedData<T> extends AbstractPaginatedData<T> {
2323
private static final String DUMMY_CURSOR_PREFIX = "simple-cursor";
2424
private final String prefix;
2525

26-
public SimplePaginatedData(boolean hasPreviousPage, boolean hasNextPage, Iterable<T> data) {
26+
public NaivePaginatedData(boolean hasPreviousPage, boolean hasNextPage, Iterable<T> data) {
2727
this(hasPreviousPage, hasNextPage, data, DUMMY_CURSOR_PREFIX);
2828
}
2929

30-
public SimplePaginatedData(boolean hasPreviousPage, boolean hasNextPage, Iterable<T> data, String prefix) {
30+
public NaivePaginatedData(boolean hasPreviousPage, boolean hasNextPage, Iterable<T> data, String prefix) {
3131
super(hasPreviousPage, hasNextPage, data);
3232
this.prefix = prefix;
3333
}

src/main/java/graphql/annotations/connection/PaginatedDataConnectionTypeValidator.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717

1818
import graphql.annotations.annotationTypes.GraphQLDataFetcher;
19+
import graphql.annotations.connection.exceptions.GraphQLConnectionException;
1920

2021
import java.lang.reflect.AccessibleObject;
2122
import java.lang.reflect.Field;

src/main/java/graphql/annotations/connection/GraphQLConnectionException.java renamed to src/main/java/graphql/annotations/connection/exceptions/GraphQLConnectionException.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
* See the License for the specific language governing permissions and
1414
*/
15-
package graphql.annotations.connection;
15+
package graphql.annotations.connection.exceptions;
1616

17-
class GraphQLConnectionException extends RuntimeException {
17+
public class GraphQLConnectionException extends RuntimeException {
1818

19-
GraphQLConnectionException(String error) {
19+
public GraphQLConnectionException(String error) {
2020
super(error);
2121
}
2222
}

0 commit comments

Comments
 (0)