Skip to content

Commit f6f9bae

Browse files
andimarekbbakerman
andauthored
add shaded guava collections and use it (#2086)
* add shaded guava collections and use it in Field * remove not needed guava files * use immutable collections more and add Util class * simplify build * add documentation * add Immutable map which allows null values use more immutable collections * More immutable support in more of the places * More immutable support in more and more of the places * More Immutable code in and around the schema * Optimised import * Made the map of types in schema be immutable * More Immutable things * More Immutability and tweaked the ImmutableMapWithNullValues class * More Immutability on things * More Immutability on AST things * More Immutability on AST things and a few other things * renamed listMap to just map and added more tests * Renamed to ImmutableKit * Used ImmutableList collector * Used ImmutableList collector - except for sort * PR feedback Co-authored-by: Brad Baker <bbaker@atlassian.com>
1 parent 3dd5e02 commit f6f9bae

File tree

120 files changed

+1261
-772
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+1261
-772
lines changed

build.gradle

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ plugins {
77
id 'maven'
88
id 'maven-publish'
99
id 'antlr'
10-
11-
// id 'osgi' doesn't work anymore for gradle 6.6
12-
10+
id "com.github.johnrengelman.shadow" version "6.1.0"
11+
// id 'osgi' doesn't work anymore for gradle 6.6
1312
}
1413

1514

@@ -62,6 +61,7 @@ dependencies {
6261
api 'com.graphql-java:java-dataloader:2.2.3'
6362
api 'org.reactivestreams:reactive-streams:' + reactiveStreamsVersion
6463
antlr "org.antlr:antlr4:4.8"
64+
implementation 'com.google.guava:guava:30.0-jre'
6565
testImplementation group: 'junit', name: 'junit', version: '4.12'
6666
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
6767
testImplementation 'org.codehaus.groovy:groovy-all:2.5.13'
@@ -83,6 +83,43 @@ dependencies {
8383
testImplementation 'org.openjdk.jmh:jmh-generator-annprocess:1.21'
8484
}
8585

86+
shadowJar {
87+
minimize()
88+
archiveClassifier.set('')
89+
configurations = [project.configurations.compileClasspath]
90+
relocate('com.google.common', 'graphql.com.google.common') {
91+
include 'com.google.common.collect.*'
92+
include 'com.google.common.base.*'
93+
}
94+
dependencies {
95+
include(dependency('com.google.guava:guava:30.0-jre'))
96+
}
97+
from "LICENSE.md"
98+
from "src/main/antlr/Graphql.g4"
99+
from "src/main/antlr/GraphqlOperation.g4"
100+
from "src/main/antlr/GraphqlSDL.g4"
101+
from "src/main/antlr/GraphqlCommon.g4"
102+
manifest {
103+
attributes('Automatic-Module-Name': 'com.graphql-java')
104+
}
105+
}
106+
107+
108+
task removeNotNeededGuava(type: Zip) {
109+
from({ zipTree({"build/libs/graphql-java-${project.version}.jar"})}) {
110+
exclude('/com/**')
111+
}
112+
archiveFileName = "graphql-java-tmp.jar"
113+
destinationDirectory = file("${project.buildDir}/libs")
114+
doLast {
115+
delete("build/libs/graphql-java-${project.version}.jar")
116+
file("build/libs/graphql-java-tmp.jar").renameTo(file("build/libs/graphql-java-${project.version}.jar"))
117+
}
118+
}
119+
120+
121+
shadowJar.finalizedBy removeNotNeededGuava
122+
86123

87124
task testng(type: Test) {
88125
useTestNG()
@@ -130,8 +167,6 @@ allprojects {
130167
tasks.withType(Javadoc) {
131168
exclude('**/antlr/**')
132169
}
133-
134-
135170
}
136171

137172
publishing {
@@ -152,9 +187,12 @@ publishing {
152187
// The ANTLR-related code below--introduced in `1ac98bf`--addresses an issue with
153188
// the Gradle ANTLR plugin. `1ac98bf` can be reverted and this comment removed once
154189
// that issue is fixed and Gradle upgraded. See https://goo.gl/L92KiF and https://goo.gl/FY0PVR.
190+
//
191+
// We are removing here guava because the classes we want to use is "shaded" into the jar itself
192+
// via the shadowJar task
155193
Node pomNode = asNode()
156194
pomNode.dependencies.'*'.findAll() {
157-
it.artifactId.text() == 'antlr4'
195+
it.artifactId.text() == 'antlr4' || it.artifactId.text() == 'guava'
158196
}.each() {
159197
it.parent().remove(it)
160198
}
@@ -228,3 +266,4 @@ task myWrapper(type: Wrapper) {
228266
gradleVersion = '6.6.1'
229267
distributionUrl = "https://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip"
230268
}
269+

src/main/java/graphql/Directives.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
import graphql.language.Description;
55
import graphql.language.DirectiveDefinition;
6-
import graphql.language.InputValueDefinition;
76
import graphql.language.StringValue;
87
import graphql.schema.GraphQLDirective;
98

@@ -16,7 +15,7 @@
1615
import static graphql.introspection.Introspection.DirectiveLocation.INLINE_FRAGMENT;
1716
import static graphql.introspection.Introspection.DirectiveLocation.SCALAR;
1817
import static graphql.language.DirectiveLocation.newDirectiveLocation;
19-
import static graphql.language.InputValueDefinition.*;
18+
import static graphql.language.InputValueDefinition.newInputValueDefinition;
2019
import static graphql.language.NonNullType.newNonNullType;
2120
import static graphql.language.TypeName.newTypeName;
2221
import static graphql.schema.GraphQLArgument.newArgument;

src/main/java/graphql/ExecutionResultImpl.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
package graphql;
22

33

4+
import com.google.common.collect.ImmutableList;
5+
import graphql.collect.ImmutableKit;
6+
47
import java.util.ArrayList;
58
import java.util.Collections;
69
import java.util.LinkedHashMap;
710
import java.util.List;
811
import java.util.Map;
912
import java.util.function.Consumer;
1013

11-
import static java.util.stream.Collectors.toList;
14+
import static graphql.collect.ImmutableKit.map;
1215

1316
@Internal
1417
public class ExecutionResultImpl implements ExecutionResult {
@@ -43,9 +46,9 @@ private ExecutionResultImpl(boolean dataPresent, Object data, List<? extends Gra
4346
this.data = data;
4447

4548
if (errors != null && !errors.isEmpty()) {
46-
this.errors = Collections.unmodifiableList(new ArrayList<>(errors));
49+
this.errors = ImmutableList.copyOf(errors);
4750
} else {
48-
this.errors = Collections.emptyList();
51+
this.errors = ImmutableKit.emptyList();
4952
}
5053

5154
this.extensions = extensions;
@@ -88,7 +91,7 @@ public Map<String, Object> toSpecification() {
8891
}
8992

9093
private Object errorsToSpec(List<GraphQLError> errors) {
91-
return errors.stream().map(GraphQLError::toSpecification).collect(toList());
94+
return map(errors, GraphQLError::toSpecification);
9295
}
9396

9497
@Override

src/main/java/graphql/GraphqlErrorHelper.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import java.util.Map;
88
import java.util.Objects;
99

10-
import static java.util.stream.Collectors.toList;
10+
import static graphql.collect.ImmutableKit.map;
1111

1212
/**
1313
* This little helper allows GraphQlErrors to implement
@@ -51,7 +51,7 @@ public static Map<String, Object> toSpecification(GraphQLError error) {
5151
}
5252

5353
public static Object locations(List<SourceLocation> locations) {
54-
return locations.stream().map(GraphqlErrorHelper::location).collect(toList());
54+
return map(locations, GraphqlErrorHelper::location);
5555
}
5656

5757
public static Object location(SourceLocation location) {

src/main/java/graphql/TypeResolutionEnvironment.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package graphql;
22

3+
import graphql.collect.ImmutableMapWithNullValues;
34
import graphql.execution.MergedField;
45
import graphql.schema.GraphQLSchema;
56
import graphql.schema.GraphQLType;
@@ -16,15 +17,15 @@
1617
public class TypeResolutionEnvironment {
1718

1819
private final Object object;
19-
private final Map<String, Object> arguments;
20+
private final ImmutableMapWithNullValues<String, Object> arguments;
2021
private final MergedField field;
2122
private final GraphQLType fieldType;
2223
private final GraphQLSchema schema;
2324
private final Object context;
2425

2526
public TypeResolutionEnvironment(Object object, Map<String, Object> arguments, MergedField field, GraphQLType fieldType, GraphQLSchema schema, final Object context) {
2627
this.object = object;
27-
this.arguments = arguments;
28+
this.arguments = ImmutableMapWithNullValues.copyOf(arguments);
2829
this.field = field;
2930
this.fieldType = fieldType;
3031
this.schema = schema;

src/main/java/graphql/cachecontrol/CacheControl.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
import static graphql.Assert.assertNotEmpty;
1515
import static graphql.Assert.assertNotNull;
16-
import static graphql.util.FpKit.map;
16+
import static graphql.collect.ImmutableKit.map;
1717

1818
/**
1919
* This class implements the graphql Cache Control specification as outlined in https://github.com/apollographql/apollo-cache-control
@@ -79,7 +79,6 @@ private CacheControl() {
7979
* @param path the path to the field that has the cache control hint
8080
* @param maxAge the caching time in seconds
8181
* @param scope the scope of the cache control hint
82-
*
8382
* @return this object builder style
8483
*/
8584
public CacheControl hint(ResultPath path, Integer maxAge, Scope scope) {
@@ -94,7 +93,6 @@ public CacheControl hint(ResultPath path, Integer maxAge, Scope scope) {
9493
*
9594
* @param path the path to the field that has the cache control hint
9695
* @param scope the scope of the cache control hint
97-
*
9896
* @return this object builder style
9997
*/
10098
public CacheControl hint(ResultPath path, Scope scope) {
@@ -106,7 +104,6 @@ public CacheControl hint(ResultPath path, Scope scope) {
106104
*
107105
* @param path the path to the field that has the cache control hint
108106
* @param maxAge the caching time in seconds
109-
*
110107
* @return this object builder style
111108
*/
112109
public CacheControl hint(ResultPath path, Integer maxAge) {
@@ -119,7 +116,6 @@ public CacheControl hint(ResultPath path, Integer maxAge) {
119116
* @param dataFetchingEnvironment the path to the field that has the cache control hint
120117
* @param maxAge the caching time in seconds
121118
* @param scope the scope of the cache control hint
122-
*
123119
* @return this object builder style
124120
*/
125121
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Integer maxAge, Scope scope) {
@@ -134,7 +130,6 @@ public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Intege
134130
*
135131
* @param dataFetchingEnvironment the path to the field that has the cache control hint
136132
* @param maxAge the caching time in seconds
137-
*
138133
* @return this object builder style
139134
*/
140135
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Integer maxAge) {
@@ -147,7 +142,6 @@ public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Intege
147142
*
148143
* @param dataFetchingEnvironment the path to the field that has the cache control hint
149144
* @param scope the scope of the cache control hint
150-
*
151145
* @return this object builder style
152146
*/
153147
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Scope scope) {
@@ -168,14 +162,13 @@ public static CacheControl newCacheControl() {
168162
* object back out
169163
*
170164
* @param executionResult the starting execution result object
171-
*
172165
* @return a new execution result with the hints in the extensions map.
173166
*/
174167
public ExecutionResult addTo(ExecutionResult executionResult) {
175168
return ExecutionResultImpl.newExecutionResult()
176-
.from(executionResult)
177-
.addExtension(CACHE_CONTROL_EXTENSION_KEY, hintsToCacheControlProperties())
178-
.build();
169+
.from(executionResult)
170+
.addExtension(CACHE_CONTROL_EXTENSION_KEY, hintsToCacheControlProperties())
171+
.build();
179172
}
180173

181174
private Map<String, Object> hintsToCacheControlProperties() {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package graphql.collect;
2+
3+
import com.google.common.collect.ImmutableList;
4+
import com.google.common.collect.ImmutableMap;
5+
import graphql.Assert;
6+
import graphql.Internal;
7+
8+
import java.util.Collection;
9+
import java.util.List;
10+
import java.util.Map;
11+
import java.util.function.Function;
12+
13+
@Internal
14+
public final class ImmutableKit {
15+
16+
public static <T> ImmutableList<T> emptyList() {
17+
return ImmutableList.of();
18+
}
19+
20+
public static <T> ImmutableList<T> nonNullCopyOf(Collection<T> collection) {
21+
return collection == null ? emptyList() : ImmutableList.copyOf(collection);
22+
}
23+
24+
public static <K, V> ImmutableMap<K, V> emptyMap() {
25+
return ImmutableMap.of();
26+
}
27+
28+
/**
29+
* ImmutableMaps are hard to build via {@link Map#computeIfAbsent(Object, Function)} style. This methods
30+
* allows you to take a mutable map with mutable list of keys and make it immutable.
31+
* <p>
32+
* This of course has a cost - if the map is very large you will be using more memory. But for static
33+
* maps that live a long life it maybe be worth it.
34+
*
35+
* @param startingMap the starting input map
36+
* @param <K> for key
37+
* @param <V> for victory
38+
*
39+
* @return and Immutable map of ImmutableList values
40+
*/
41+
42+
public static <K, V> ImmutableMap<K, ImmutableList<V>> toImmutableMapOfLists(Map<K, List<V>> startingMap) {
43+
Assert.assertNotNull(startingMap);
44+
ImmutableMap.Builder<K, ImmutableList<V>> map = ImmutableMap.builder();
45+
for (Map.Entry<K, List<V>> e : startingMap.entrySet()) {
46+
ImmutableList<V> value = ImmutableList.copyOf(startingMap.getOrDefault(e.getKey(), emptyList()));
47+
map.put(e.getKey(), value);
48+
}
49+
return map.build();
50+
}
51+
52+
53+
public static <K, V> ImmutableMap<K, V> addToMap(Map<K, V> existing, K newKey, V newVal) {
54+
return ImmutableMap.<K, V>builder().putAll(existing).put(newKey, newVal).build();
55+
}
56+
57+
public static <K, V> ImmutableMap<K, V> mergeMaps(Map<K, V> m1, Map<K, V> m2) {
58+
return ImmutableMap.<K, V>builder().putAll(m1).putAll(m2).build();
59+
}
60+
61+
public static <T> ImmutableList<T> concatLists(List<T> l1, List<T> l2) {
62+
return ImmutableList.<T>builder().addAll(l1).addAll(l2).build();
63+
}
64+
65+
/**
66+
* This is more efficient than `c.stream().map().collect()` because it does not create the intermediate objects needed
67+
* for the flexible style. Benchmarking has shown this to outperform `stream()`.
68+
*
69+
* @param collection the collection to map
70+
* @param mapper the mapper function
71+
* @param <T> for two
72+
* @param <R> for result
73+
*
74+
* @return a map immutable list of results
75+
*/
76+
public static <T, R> ImmutableList<R> map(Collection<T> collection, Function<? super T, ? extends R> mapper) {
77+
Assert.assertNotNull(collection);
78+
Assert.assertNotNull(mapper);
79+
@SuppressWarnings("RedundantTypeArguments")
80+
ImmutableList.Builder<R> builder = ImmutableList.<R>builder();
81+
for (T t : collection) {
82+
R r = mapper.apply(t);
83+
builder.add(r);
84+
}
85+
return builder.build();
86+
}
87+
}

0 commit comments

Comments
 (0)