Skip to content

add shaded guava collections and use it #2086

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 22 commits into from
Nov 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7b39d8f
add shaded guava collections and use it in Field
andimarek Oct 29, 2020
e0cd2bf
remove not needed guava files
andimarek Nov 1, 2020
cccba56
use immutable collections more and add Util class
andimarek Nov 1, 2020
82f4c6d
simplify build
andimarek Nov 2, 2020
a834b78
add documentation
andimarek Nov 2, 2020
fda0f99
add Immutable map which allows null values
andimarek Nov 2, 2020
3fff29f
More immutable support in more of the places
bbakerman Nov 3, 2020
dde4322
More immutable support in more and more of the places
bbakerman Nov 3, 2020
59d2878
More Immutable code in and around the schema
bbakerman Nov 4, 2020
24b0271
Optimised import
bbakerman Nov 4, 2020
d8d11c8
Made the map of types in schema be immutable
bbakerman Nov 4, 2020
f5b7614
More Immutable things
bbakerman Nov 4, 2020
0c9039d
More Immutability and tweaked the ImmutableMapWithNullValues class
bbakerman Nov 5, 2020
b31850b
More Immutability on things
bbakerman Nov 5, 2020
75f61ac
More Immutability on AST things
bbakerman Nov 5, 2020
8b020b6
More Immutability on AST things and a few other things
bbakerman Nov 5, 2020
df52444
renamed listMap to just map and added more tests
bbakerman Nov 6, 2020
0bcc618
Renamed to ImmutableKit
bbakerman Nov 6, 2020
de88d7a
Used ImmutableList collector
bbakerman Nov 8, 2020
fb7b6af
Used ImmutableList collector - except for sort
bbakerman Nov 8, 2020
03df610
Merge remote-tracking branch 'origin/master' into immutable-collectio…
bbakerman Nov 8, 2020
d9e0f44
PR feedback
bbakerman Nov 10, 2020
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
51 changes: 45 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ plugins {
id 'maven'
id 'maven-publish'
id 'antlr'

// id 'osgi' doesn't work anymore for gradle 6.6

id "com.github.johnrengelman.shadow" version "6.1.0"
// id 'osgi' doesn't work anymore for gradle 6.6
}


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

shadowJar {
minimize()
archiveClassifier.set('')
configurations = [project.configurations.compileClasspath]
relocate('com.google.common', 'graphql.com.google.common') {
include 'com.google.common.collect.*'
include 'com.google.common.base.*'
}
dependencies {
include(dependency('com.google.guava:guava:30.0-jre'))
}
from "LICENSE.md"
from "src/main/antlr/Graphql.g4"
from "src/main/antlr/GraphqlOperation.g4"
from "src/main/antlr/GraphqlSDL.g4"
from "src/main/antlr/GraphqlCommon.g4"
manifest {
attributes('Automatic-Module-Name': 'com.graphql-java')
}
}


task removeNotNeededGuava(type: Zip) {
from({ zipTree({"build/libs/graphql-java-${project.version}.jar"})}) {
exclude('/com/**')
}
archiveFileName = "graphql-java-tmp.jar"
destinationDirectory = file("${project.buildDir}/libs")
doLast {
delete("build/libs/graphql-java-${project.version}.jar")
file("build/libs/graphql-java-tmp.jar").renameTo(file("build/libs/graphql-java-${project.version}.jar"))
}
}


shadowJar.finalizedBy removeNotNeededGuava


task testng(type: Test) {
useTestNG()
Expand Down Expand Up @@ -130,8 +167,6 @@ allprojects {
tasks.withType(Javadoc) {
exclude('**/antlr/**')
}


}

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

3 changes: 1 addition & 2 deletions src/main/java/graphql/Directives.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import graphql.language.Description;
import graphql.language.DirectiveDefinition;
import graphql.language.InputValueDefinition;
import graphql.language.StringValue;
import graphql.schema.GraphQLDirective;

Expand All @@ -16,7 +15,7 @@
import static graphql.introspection.Introspection.DirectiveLocation.INLINE_FRAGMENT;
import static graphql.introspection.Introspection.DirectiveLocation.SCALAR;
import static graphql.language.DirectiveLocation.newDirectiveLocation;
import static graphql.language.InputValueDefinition.*;
import static graphql.language.InputValueDefinition.newInputValueDefinition;
import static graphql.language.NonNullType.newNonNullType;
import static graphql.language.TypeName.newTypeName;
import static graphql.schema.GraphQLArgument.newArgument;
Expand Down
11 changes: 7 additions & 4 deletions src/main/java/graphql/ExecutionResultImpl.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package graphql;


import com.google.common.collect.ImmutableList;
import graphql.collect.ImmutableKit;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import static java.util.stream.Collectors.toList;
import static graphql.collect.ImmutableKit.map;

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

if (errors != null && !errors.isEmpty()) {
this.errors = Collections.unmodifiableList(new ArrayList<>(errors));
this.errors = ImmutableList.copyOf(errors);
} else {
this.errors = Collections.emptyList();
this.errors = ImmutableKit.emptyList();
}

this.extensions = extensions;
Expand Down Expand Up @@ -88,7 +91,7 @@ public Map<String, Object> toSpecification() {
}

private Object errorsToSpec(List<GraphQLError> errors) {
return errors.stream().map(GraphQLError::toSpecification).collect(toList());
return map(errors, GraphQLError::toSpecification);
}

@Override
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/graphql/GraphqlErrorHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import java.util.Map;
import java.util.Objects;

import static java.util.stream.Collectors.toList;
import static graphql.collect.ImmutableKit.map;

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

public static Object locations(List<SourceLocation> locations) {
return locations.stream().map(GraphqlErrorHelper::location).collect(toList());
return map(locations, GraphqlErrorHelper::location);
}

public static Object location(SourceLocation location) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/graphql/TypeResolutionEnvironment.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package graphql;

import graphql.collect.ImmutableMapWithNullValues;
import graphql.execution.MergedField;
import graphql.schema.GraphQLSchema;
import graphql.schema.GraphQLType;
Expand All @@ -16,15 +17,15 @@
public class TypeResolutionEnvironment {

private final Object object;
private final Map<String, Object> arguments;
private final ImmutableMapWithNullValues<String, Object> arguments;
private final MergedField field;
private final GraphQLType fieldType;
private final GraphQLSchema schema;
private final Object context;

public TypeResolutionEnvironment(Object object, Map<String, Object> arguments, MergedField field, GraphQLType fieldType, GraphQLSchema schema, final Object context) {
this.object = object;
this.arguments = arguments;
this.arguments = ImmutableMapWithNullValues.copyOf(arguments);
this.field = field;
this.fieldType = fieldType;
this.schema = schema;
Expand Down
15 changes: 4 additions & 11 deletions src/main/java/graphql/cachecontrol/CacheControl.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import static graphql.Assert.assertNotEmpty;
import static graphql.Assert.assertNotNull;
import static graphql.util.FpKit.map;
import static graphql.collect.ImmutableKit.map;

/**
* This class implements the graphql Cache Control specification as outlined in https://github.com/apollographql/apollo-cache-control
Expand Down Expand Up @@ -79,7 +79,6 @@ private CacheControl() {
* @param path the path to the field that has the cache control hint
* @param maxAge the caching time in seconds
* @param scope the scope of the cache control hint
*
* @return this object builder style
*/
public CacheControl hint(ResultPath path, Integer maxAge, Scope scope) {
Expand All @@ -94,7 +93,6 @@ public CacheControl hint(ResultPath path, Integer maxAge, Scope scope) {
*
* @param path the path to the field that has the cache control hint
* @param scope the scope of the cache control hint
*
* @return this object builder style
*/
public CacheControl hint(ResultPath path, Scope scope) {
Expand All @@ -106,7 +104,6 @@ public CacheControl hint(ResultPath path, Scope scope) {
*
* @param path the path to the field that has the cache control hint
* @param maxAge the caching time in seconds
*
* @return this object builder style
*/
public CacheControl hint(ResultPath path, Integer maxAge) {
Expand All @@ -119,7 +116,6 @@ public CacheControl hint(ResultPath path, Integer maxAge) {
* @param dataFetchingEnvironment the path to the field that has the cache control hint
* @param maxAge the caching time in seconds
* @param scope the scope of the cache control hint
*
* @return this object builder style
*/
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Integer maxAge, Scope scope) {
Expand All @@ -134,7 +130,6 @@ public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Intege
*
* @param dataFetchingEnvironment the path to the field that has the cache control hint
* @param maxAge the caching time in seconds
*
* @return this object builder style
*/
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Integer maxAge) {
Expand All @@ -147,7 +142,6 @@ public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Intege
*
* @param dataFetchingEnvironment the path to the field that has the cache control hint
* @param scope the scope of the cache control hint
*
* @return this object builder style
*/
public CacheControl hint(DataFetchingEnvironment dataFetchingEnvironment, Scope scope) {
Expand All @@ -168,14 +162,13 @@ public static CacheControl newCacheControl() {
* object back out
*
* @param executionResult the starting execution result object
*
* @return a new execution result with the hints in the extensions map.
*/
public ExecutionResult addTo(ExecutionResult executionResult) {
return ExecutionResultImpl.newExecutionResult()
.from(executionResult)
.addExtension(CACHE_CONTROL_EXTENSION_KEY, hintsToCacheControlProperties())
.build();
.from(executionResult)
.addExtension(CACHE_CONTROL_EXTENSION_KEY, hintsToCacheControlProperties())
.build();
}

private Map<String, Object> hintsToCacheControlProperties() {
Expand Down
87 changes: 87 additions & 0 deletions src/main/java/graphql/collect/ImmutableKit.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package graphql.collect;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import graphql.Assert;
import graphql.Internal;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

@Internal
public final class ImmutableKit {

public static <T> ImmutableList<T> emptyList() {
return ImmutableList.of();
}

public static <T> ImmutableList<T> nonNullCopyOf(Collection<T> collection) {
return collection == null ? emptyList() : ImmutableList.copyOf(collection);
}

public static <K, V> ImmutableMap<K, V> emptyMap() {
return ImmutableMap.of();
}

/**
* ImmutableMaps are hard to build via {@link Map#computeIfAbsent(Object, Function)} style. This methods
* allows you to take a mutable map with mutable list of keys and make it immutable.
* <p>
* This of course has a cost - if the map is very large you will be using more memory. But for static
* maps that live a long life it maybe be worth it.
*
* @param startingMap the starting input map
* @param <K> for key
* @param <V> for victory
*
* @return and Immutable map of ImmutableList values
*/

public static <K, V> ImmutableMap<K, ImmutableList<V>> toImmutableMapOfLists(Map<K, List<V>> startingMap) {
Assert.assertNotNull(startingMap);
ImmutableMap.Builder<K, ImmutableList<V>> map = ImmutableMap.builder();
for (Map.Entry<K, List<V>> e : startingMap.entrySet()) {
ImmutableList<V> value = ImmutableList.copyOf(startingMap.getOrDefault(e.getKey(), emptyList()));
map.put(e.getKey(), value);
}
return map.build();
}


public static <K, V> ImmutableMap<K, V> addToMap(Map<K, V> existing, K newKey, V newVal) {
return ImmutableMap.<K, V>builder().putAll(existing).put(newKey, newVal).build();
}

public static <K, V> ImmutableMap<K, V> mergeMaps(Map<K, V> m1, Map<K, V> m2) {
return ImmutableMap.<K, V>builder().putAll(m1).putAll(m2).build();
}

public static <T> ImmutableList<T> concatLists(List<T> l1, List<T> l2) {
return ImmutableList.<T>builder().addAll(l1).addAll(l2).build();
}

/**
* This is more efficient than `c.stream().map().collect()` because it does not create the intermediate objects needed
* for the flexible style. Benchmarking has shown this to outperform `stream()`.
*
* @param collection the collection to map
* @param mapper the mapper function
* @param <T> for two
* @param <R> for result
*
* @return a map immutable list of results
*/
public static <T, R> ImmutableList<R> map(Collection<T> collection, Function<? super T, ? extends R> mapper) {
Assert.assertNotNull(collection);
Assert.assertNotNull(mapper);
@SuppressWarnings("RedundantTypeArguments")
ImmutableList.Builder<R> builder = ImmutableList.<R>builder();
for (T t : collection) {
R r = mapper.apply(t);
builder.add(r);
}
return builder.build();
}
}
Loading