From eb7f62e13772c57f807e08ad419b620d77327a6c Mon Sep 17 00:00:00 2001 From: bbaker Date: Fri, 4 Jul 2025 19:57:57 +1000 Subject: [PATCH 1/7] Improved access speed of isPossibleType --- .../idl/ImmutableTypeDefinitionRegistry.java | 60 +++++++ .../schema/idl/TypeDefinitionRegistry.java | 166 ++++++++++++------ .../java/graphql/schema/idl/TypeInfo.java | 19 ++ ...ImmutableTypeDefinitionRegistryTest.groovy | 59 +++++++ .../schema/idl/SchemaTypeCheckerTest.groovy | 2 +- .../idl/TypeDefinitionRegistryTest.groovy | 35 +++- .../graphql/schema/idl/TypeInfoTest.groovy | 18 ++ 7 files changed, 301 insertions(+), 58 deletions(-) diff --git a/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java index 1604551f2..66cab2c0a 100644 --- a/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java @@ -6,13 +6,17 @@ import graphql.PublicApi; import graphql.language.DirectiveDefinition; import graphql.language.EnumTypeExtensionDefinition; +import graphql.language.ImplementingTypeDefinition; import graphql.language.InputObjectTypeExtensionDefinition; +import graphql.language.InterfaceTypeDefinition; import graphql.language.InterfaceTypeExtensionDefinition; +import graphql.language.ObjectTypeDefinition; import graphql.language.ObjectTypeExtensionDefinition; import graphql.language.SDLDefinition; import graphql.language.ScalarTypeDefinition; import graphql.language.ScalarTypeExtensionDefinition; import graphql.language.SchemaExtensionDefinition; +import graphql.language.Type; import graphql.language.TypeDefinition; import graphql.language.UnionTypeExtensionDefinition; import graphql.schema.idl.errors.SchemaProblem; @@ -34,6 +38,10 @@ @PublicApi @NullMarked public class ImmutableTypeDefinitionRegistry extends TypeDefinitionRegistry { + + private final Map> allImplementationsOf; + private final Map> implementationsOf; + ImmutableTypeDefinitionRegistry(TypeDefinitionRegistry registry) { super( copyOf(registry.objectTypeExtensions), @@ -49,6 +57,48 @@ public class ImmutableTypeDefinitionRegistry extends TypeDefinitionRegistry { registry.schema, registry.schemaParseOrder ); + allImplementationsOf = calculateAllImplementsOf(); + implementationsOf = calculateImplementationsOf(allImplementationsOf); + } + + private Map> calculateAllImplementsOf() { + ImmutableMap.Builder> mapBuilder = ImmutableMap.builder(); + List implementingTypeDefinitions = getTypes(ImplementingTypeDefinition.class); + for (TypeDefinition typeDef : types.values()) { + if (typeDef instanceof InterfaceTypeDefinition) { + InterfaceTypeDefinition interfaceTypeDef = (InterfaceTypeDefinition) typeDef; + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (ImplementingTypeDefinition implementingTypeDefinition : implementingTypeDefinitions) { + List implementsList = implementingTypeDefinition.getImplements(); + for (Type iFace : implementsList) { + Optional implementsAnInterface = getType(iFace, InterfaceTypeDefinition.class); + if (implementsAnInterface.isPresent()) { + boolean equals = implementsAnInterface.get().getName().equals(interfaceTypeDef.getName()); + if (equals) { + listBuilder.add(implementingTypeDefinition); + break; + } + } + } + } + mapBuilder.put(interfaceTypeDef, listBuilder.build()); + } + } + return mapBuilder.build(); + } + + private Map> calculateImplementationsOf(Map> allImplementationsOf1) { + ImmutableMap.Builder> mapBuilder = ImmutableMap.builder(); + for (Map.Entry> entry : allImplementationsOf1.entrySet()) { + ImmutableList.Builder listBuilder = ImmutableList.builder(); + for (ImplementingTypeDefinition implementingTypeDefinition : entry.getValue()) { + if (implementingTypeDefinition instanceof ObjectTypeDefinition) { + listBuilder.add((ObjectTypeDefinition) implementingTypeDefinition); + } + } + mapBuilder.put(entry.getKey(), listBuilder.build()); + } + return mapBuilder.build(); } private UnsupportedOperationException unsupportedOperationException() { @@ -129,4 +179,14 @@ public List getSchemaExtensionDefinitions() { public Map getDirectiveDefinitions() { return directiveDefinitions; } + + @Override + public List getAllImplementationsOf(InterfaceTypeDefinition targetInterface) { + return allImplementationsOf.getOrDefault(targetInterface, ImmutableList.of()); + } + + @Override + public List getImplementationsOf(InterfaceTypeDefinition targetInterface) { + return implementationsOf.getOrDefault(targetInterface, ImmutableList.of()); + } } diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index dcbfb9c41..86733019c 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -1,5 +1,6 @@ package graphql.schema.idl; +import com.google.common.collect.ImmutableList; import graphql.Assert; import graphql.GraphQLError; import graphql.PublicApi; @@ -36,6 +37,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -83,17 +85,17 @@ public TypeDefinitionRegistry() { } protected TypeDefinitionRegistry(Map> objectTypeExtensions, - Map> interfaceTypeExtensions, - Map> unionTypeExtensions, - Map> enumTypeExtensions, - Map> scalarTypeExtensions, - Map> inputObjectTypeExtensions, - Map types, - Map scalarTypes, - Map directiveDefinitions, - List schemaExtensionDefinitions, - @Nullable SchemaDefinition schema, - SchemaParseOrder schemaParseOrder) { + Map> interfaceTypeExtensions, + Map> unionTypeExtensions, + Map> enumTypeExtensions, + Map> scalarTypeExtensions, + Map> inputObjectTypeExtensions, + Map types, + Map scalarTypes, + Map directiveDefinitions, + List schemaExtensionDefinitions, + @Nullable SchemaDefinition schema, + SchemaParseOrder schemaParseOrder) { this.objectTypeExtensions = objectTypeExtensions; this.interfaceTypeExtensions = interfaceTypeExtensions; this.unionTypeExtensions = unionTypeExtensions; @@ -495,38 +497,89 @@ public boolean hasType(TypeName typeName) { return types.containsKey(name) || ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(name) || scalarTypes.containsKey(name) || objectTypeExtensions.containsKey(name); } + protected static String typeName(Type type) { + return TypeInfo.getTypeName(type).getName(); + } + public Optional getType(Type type) { - String typeName = TypeInfo.typeInfo(type).getName(); - return getType(typeName); + return getType(typeName(type)); } public Optional getType(Type type, Class ofType) { - String typeName = TypeInfo.typeInfo(type).getName(); - return getType(typeName, ofType); + return getType(typeName(type), ofType); } public Optional getType(String typeName) { + return Optional.ofNullable(getTypeOrNull(typeName)); + } + + public Optional getType(String typeName, Class ofType) { + return Optional.ofNullable(getTypeOrNull(typeName, ofType)); + } + + /** + * Returns a {@link TypeDefinition} of the specified type or null + * + * @param type the type to check + * + * @return a {@link TypeDefinition} or null if it's not found + */ + @Nullable + public TypeDefinition getTypeOrNull(Type type) { + return getTypeOrNull(typeName(type)); + } + + /** + * Returns a {@link TypeDefinition} of the specified type with the specified class or null + * + * @param type the type to check + * @param ofType the class of {@link TypeDefinition} + * + * @return a {@link TypeDefinition} or null if it's not found + */ + @Nullable + public T getTypeOrNull(Type type, Class ofType) { + return getTypeOrNull(typeName(type), ofType); + } + + /** + * Returns a {@link TypeDefinition} of the specified name or null + * + * @param typeName the type name to check + * + * @return a {@link TypeDefinition} or null if it's not found + */ + @Nullable + public TypeDefinition getTypeOrNull(String typeName) { TypeDefinition typeDefinition = types.get(typeName); if (typeDefinition != null) { - return Optional.of(typeDefinition); + return typeDefinition; } typeDefinition = scalars().get(typeName); if (typeDefinition != null) { - return Optional.of(typeDefinition); + return typeDefinition; } - return Optional.empty(); + return null; } - public Optional getType(String typeName, Class ofType) { - Optional type = getType(typeName); - if (type.isPresent()) { - TypeDefinition typeDefinition = type.get(); - if (typeDefinition.getClass().equals(ofType)) { + /** + * Returns a {@link TypeDefinition} of the specified name and class or null + * + * @param typeName the type name to check + * @param ofType the class of {@link TypeDefinition} + * + * @return a {@link TypeDefinition} or null if it's not found + */ + @Nullable + public T getTypeOrNull(String typeName, Class ofType) { + TypeDefinition type = getTypeOrNull(typeName); + if (type != null) { + if (type.getClass().equals(ofType)) { //noinspection unchecked - return Optional.of((T) typeDefinition); + return (T) type; } } - return Optional.empty(); + return null; } /** @@ -537,10 +590,9 @@ public Optional getType(String typeName, Class * @return true if its abstract */ public boolean isInterfaceOrUnion(Type type) { - Optional typeDefinition = getType(type); - if (typeDefinition.isPresent()) { - TypeDefinition definition = typeDefinition.get(); - return definition instanceof UnionTypeDefinition || definition instanceof InterfaceTypeDefinition; + TypeDefinition typeDefinition = getTypeOrNull(type); + if (typeDefinition != null) { + return typeDefinition instanceof UnionTypeDefinition || typeDefinition instanceof InterfaceTypeDefinition; } return false; } @@ -553,10 +605,9 @@ public boolean isInterfaceOrUnion(Type type) { * @return true if its an object type or interface */ public boolean isObjectTypeOrInterface(Type type) { - Optional typeDefinition = getType(type); - if (typeDefinition.isPresent()) { - TypeDefinition definition = typeDefinition.get(); - return definition instanceof ObjectTypeDefinition || definition instanceof InterfaceTypeDefinition; + TypeDefinition typeDefinition = getTypeOrNull(type); + if (typeDefinition != null) { + return typeDefinition instanceof ObjectTypeDefinition || typeDefinition instanceof InterfaceTypeDefinition; } return false; } @@ -569,7 +620,7 @@ public boolean isObjectTypeOrInterface(Type type) { * @return true if its an object type */ public boolean isObjectType(Type type) { - return getType(type, ObjectTypeDefinition.class).isPresent(); + return getTypeOrNull(type, ObjectTypeDefinition.class) != null; } /** @@ -581,10 +632,14 @@ public boolean isObjectType(Type type) { * @return a list of types of the target class */ public List getTypes(Class targetClass) { - return types.values().stream() - .filter(targetClass::isInstance) - .map(targetClass::cast) - .collect(Collectors.toList()); + ImmutableList.Builder builder = ImmutableList.builder(); + for (TypeDefinition type : types.values()) { + if (targetClass.isInstance(type)) { + T typeCast = targetClass.cast(type); + builder.add(typeCast); + } + } + return builder.build(); } /** @@ -610,20 +665,21 @@ public Map getTypesMap(Class targetClas * @see TypeDefinitionRegistry#getImplementationsOf(InterfaceTypeDefinition) */ public List getAllImplementationsOf(InterfaceTypeDefinition targetInterface) { + ImmutableList.Builder list = ImmutableList.builder(); List typeDefinitions = getTypes(ImplementingTypeDefinition.class); - return typeDefinitions.stream().filter(typeDefinition -> { - List implementsList = typeDefinition.getImplements(); + for (ImplementingTypeDefinition implementingTypeDefinition : typeDefinitions) { + List implementsList = implementingTypeDefinition.getImplements(); for (Type iFace : implementsList) { - Optional interfaceTypeDef = getType(iFace, InterfaceTypeDefinition.class); - if (interfaceTypeDef.isPresent()) { - boolean equals = interfaceTypeDef.get().getName().equals(targetInterface.getName()); + InterfaceTypeDefinition interfaceTypeDef = getTypeOrNull(iFace, InterfaceTypeDefinition.class); + if (interfaceTypeDef != null) { + boolean equals = interfaceTypeDef.getName().equals(targetInterface.getName()); if (equals) { - return true; + list.add(implementingTypeDefinition); } } } - return false; - }).collect(Collectors.toList()); + } + return list.build(); } /** @@ -658,14 +714,14 @@ public boolean isPossibleType(Type abstractType, Type possibleType) { if (!isObjectTypeOrInterface(possibleType)) { return false; } - TypeDefinition targetObjectTypeDef = getType(possibleType).get(); - TypeDefinition abstractTypeDef = getType(abstractType).get(); + TypeDefinition targetObjectTypeDef = Objects.requireNonNull(getTypeOrNull(possibleType)); + TypeDefinition abstractTypeDef = Objects.requireNonNull(getTypeOrNull(abstractType)); if (abstractTypeDef instanceof UnionTypeDefinition) { List memberTypes = ((UnionTypeDefinition) abstractTypeDef).getMemberTypes(); for (Type memberType : memberTypes) { - Optional checkType = getType(memberType, ObjectTypeDefinition.class); - if (checkType.isPresent()) { - if (checkType.get().getName().equals(targetObjectTypeDef.getName())) { + ObjectTypeDefinition checkType = getTypeOrNull(memberType, ObjectTypeDefinition.class); + if (checkType != null) { + if (checkType.getName().equals(targetObjectTypeDef.getName())) { return true; } } @@ -674,8 +730,12 @@ public boolean isPossibleType(Type abstractType, Type possibleType) { } else { InterfaceTypeDefinition iFace = (InterfaceTypeDefinition) abstractTypeDef; List implementingTypeDefinitions = getAllImplementationsOf(iFace); - return implementingTypeDefinitions.stream() - .anyMatch(od -> od.getName().equals(targetObjectTypeDef.getName())); + for (ImplementingTypeDefinition implementingTypeDefinition : implementingTypeDefinitions) { + if (implementingTypeDefinition.getName().equals(targetObjectTypeDef.getName())) { + return true; + } + } + return false; } } diff --git a/src/main/java/graphql/schema/idl/TypeInfo.java b/src/main/java/graphql/schema/idl/TypeInfo.java index fe12d4988..9258912af 100644 --- a/src/main/java/graphql/schema/idl/TypeInfo.java +++ b/src/main/java/graphql/schema/idl/TypeInfo.java @@ -139,6 +139,25 @@ public Type unwrapOneType() { return unwrapOne().getRawType(); } + /** + * Gets the type name of a [Type], unwrapping any lists or non-null decorations + * + * @param type the Type + * + * @return the inner TypeName for this type + */ + public static TypeName getTypeName(Type type) { + while (!(type instanceof TypeName)) { + if (type instanceof NonNullType) { + type = ((NonNullType) type).getType(); + } + if (type instanceof ListType) { + type = ((ListType) type).getType(); + } + } + return (TypeName) type; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy b/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy index c29636b3e..95a6ff0b3 100644 --- a/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy +++ b/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy @@ -1,5 +1,6 @@ package graphql.schema.idl +import graphql.language.InterfaceTypeDefinition import graphql.language.TypeDefinition import spock.lang.Specification @@ -169,6 +170,64 @@ class ImmutableTypeDefinitionRegistryTest extends Specification { immutableRegistry.remove("key", someDef) then: thrown(UnsupportedOperationException) + } + + def "get implementations of"() { + def sdl = serializableSchema + """ + interface IType { + i : String + } + + interface DerivedIType implements IType { + i : String + d : String + } + + """ + for (int i = 0; i < 10; i++) { + sdl += """ + type OT$i implements IType { + i : String + } + """ + + } + for (int i = 0; i < 5; i++) { + sdl += """ + type DT$i implements DerivedIType { + i : String + d : String + } + """ + + } + def immutableRegistry = new SchemaParser().parse(sdl).readOnly() + + Map interfaces = immutableRegistry.getTypesMap(InterfaceTypeDefinition.class) + + when: + def iFieldType = interfaces.get("IType") + def allImplementationsOf = immutableRegistry.getAllImplementationsOf(iFieldType) + def implementationsOf = immutableRegistry.getImplementationsOf(iFieldType) + + then: + allImplementationsOf.size() == 11 + allImplementationsOf.collect({ it.getName() }).every { it.startsWith("OT") || it == "DerivedIType" } + + implementationsOf.size() == 10 + implementationsOf.collect({ it.getName() }).every { it.startsWith("OT") } + + when: + def iDerivedType = interfaces.get("DerivedIType") + allImplementationsOf = immutableRegistry.getAllImplementationsOf(iDerivedType) + implementationsOf = immutableRegistry.getImplementationsOf(iDerivedType) + + then: + allImplementationsOf.size() == 5 + allImplementationsOf.collect({ it.getName() }).every { it.startsWith("DT") } + + implementationsOf.size() == 5 + implementationsOf.collect({ it.getName() }).every { it.startsWith("DT") } } diff --git a/src/test/groovy/graphql/schema/idl/SchemaTypeCheckerTest.groovy b/src/test/groovy/graphql/schema/idl/SchemaTypeCheckerTest.groovy index 7bdd2fea0..50cbade72 100644 --- a/src/test/groovy/graphql/schema/idl/SchemaTypeCheckerTest.groovy +++ b/src/test/groovy/graphql/schema/idl/SchemaTypeCheckerTest.groovy @@ -32,7 +32,7 @@ import static java.lang.String.format class SchemaTypeCheckerTest extends Specification { static TypeDefinitionRegistry parseSDL(String spec) { - new SchemaParser().parse(spec) + new SchemaParser().parse(spec).readOnly() } def resolver = new TypeResolver() { diff --git a/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy b/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy index 91aef9d93..9c48e9308 100644 --- a/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy +++ b/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy @@ -375,7 +375,7 @@ class TypeDefinitionRegistryTest extends Specification { } - def "test can get implements of interface"() { + def "test can get implements of interface #typeOfReg"() { def spec = ''' interface Interface { name : String @@ -407,11 +407,19 @@ class TypeDefinitionRegistryTest extends Specification { ''' when: def registry = parse(spec) + if (typeOfReg == "immutable") { + registry = registry.readOnly() + } def interfaceDef = registry.getType("Interface", InterfaceTypeDefinition.class).get() def implementingTypeDefinitions = registry.getAllImplementationsOf(interfaceDef) def names = implementingTypeDefinitions.collect { it.getName() } then: names == ["Type1", "Type2", "Type3", "Type5"] + + where: + typeOfReg | _ + "mutable" | _ + "immutable" | _ } def animalia = ''' @@ -461,9 +469,16 @@ class TypeDefinitionRegistryTest extends Specification { ''' - def "test possible type detection"() { + def "test possible type detection #typeOfReg"() { + given: + TypeDefinitionRegistry mutableReg = parse(animalia) + ImmutableTypeDefinitionRegistry immutableReg = mutableReg.readOnly() + when: - def registry = parse(animalia) + def registry = mutableReg + if (typeOfReg == "immutable") { + registry = immutableReg + } then: registry.isPossibleType(type("Mammal"), type("Canine")) @@ -485,12 +500,19 @@ class TypeDefinitionRegistryTest extends Specification { !registry.isPossibleType(type("Platypus"), type("Dog")) !registry.isPossibleType(type("Platypus"), type("Cat")) + where: + typeOfReg | _ + "mutable" | _ + "immutable" | _ } - def "isSubTypeOf detection"() { + def "isSubTypeOf detection #typeOfReg"() { when: def registry = parse(animalia) + if (typeOfReg == "immutable") { + registry = registry.readOnly() + } then: registry.isSubTypeOf(type("Mammal"), type("Mammal")) @@ -517,6 +539,11 @@ class TypeDefinitionRegistryTest extends Specification { registry.isSubTypeOf(listType(nonNullType(listType(type("Canine")))), listType(nonNullType(listType(type("Mammal"))))) !registry.isSubTypeOf(listType(nonNullType(listType(type("Turtle")))), listType(nonNullType(listType(type("Mammal"))))) + + where: + typeOfReg | _ + "mutable" | _ + "immutable" | _ } @Unroll diff --git a/src/test/groovy/graphql/schema/idl/TypeInfoTest.groovy b/src/test/groovy/graphql/schema/idl/TypeInfoTest.groovy index 92ec7b1b8..556755e43 100644 --- a/src/test/groovy/graphql/schema/idl/TypeInfoTest.groovy +++ b/src/test/groovy/graphql/schema/idl/TypeInfoTest.groovy @@ -136,4 +136,22 @@ class TypeInfoTest extends Specification { "[named!]!" | "[newName!]!" "[[named!]!]" | "[[newName!]!]" } + + @Unroll + def "test getTypeName gets to the inner type"() { + + expect: + Type actualType = TestUtil.parseType(actual) + def typeName = TypeInfo.getTypeName(actualType) + typeName.getName() == expected + + where: + actual | expected + "named" | "named" + "named!" | "named" + "[named]" | "named" + "[named!]" | "named" + "[named!]!" | "named" + "[[named!]!]" | "named" + } } From 88057b0f5eba6f6c03b9b65196d3ad9bec3fb23c Mon Sep 17 00:00:00 2001 From: bbaker Date: Sat, 5 Jul 2025 09:19:02 +1000 Subject: [PATCH 2/7] Improved access speed of isPossibleType - added javadoc --- .../schema/idl/TypeDefinitionRegistry.java | 71 +++++++++++++------ 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index 86733019c..0d21d6c4e 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -4,6 +4,7 @@ import graphql.Assert; import graphql.GraphQLError; import graphql.PublicApi; +import graphql.collect.ImmutableKit; import graphql.language.DirectiveDefinition; import graphql.language.EnumTypeExtensionDefinition; import graphql.language.ImplementingTypeDefinition; @@ -40,7 +41,6 @@ import java.util.Objects; import java.util.Optional; import java.util.function.Function; -import java.util.stream.Collectors; import static graphql.Assert.assertNotNull; import static graphql.schema.idl.SchemaExtensionsChecker.defineOperationDefs; @@ -497,22 +497,52 @@ public boolean hasType(TypeName typeName) { return types.containsKey(name) || ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(name) || scalarTypes.containsKey(name) || objectTypeExtensions.containsKey(name); } - protected static String typeName(Type type) { + private static String typeName(Type type) { return TypeInfo.getTypeName(type).getName(); } + /** + * Returns am optional {@link TypeDefinition} of the specified type or {@link Optional#empty()} + * + * @param type the type to check + * + * @return an optional {@link TypeDefinition} or empty if it's not found + */ public Optional getType(Type type) { return getType(typeName(type)); } + /** + * Returns am optional {@link TypeDefinition} of the specified type with the specified class or {@link Optional#empty()} + * + * @param type the type to check + * @param ofType the class of {@link TypeDefinition} + * + * @return an optional {@link TypeDefinition} or empty if it's not found + */ public Optional getType(Type type, Class ofType) { return getType(typeName(type), ofType); } + /** + * Returns am optional {@link TypeDefinition} of the specified type name or {@link Optional#empty()} + * + * @param typeName the type to check + * + * @return an optional {@link TypeDefinition} or empty if it's not found + */ public Optional getType(String typeName) { return Optional.ofNullable(getTypeOrNull(typeName)); } + /** + * Returns am optional {@link TypeDefinition} of the specified type name with the specified class or {@link Optional#empty()} + * + * @param typeName the type to check + * @param ofType the class of {@link TypeDefinition} + * + * @return an optional {@link TypeDefinition} or empty if it's not found + */ public Optional getType(String typeName, Class ofType) { return Optional.ofNullable(getTypeOrNull(typeName, ofType)); } @@ -665,21 +695,20 @@ public Map getTypesMap(Class targetClas * @see TypeDefinitionRegistry#getImplementationsOf(InterfaceTypeDefinition) */ public List getAllImplementationsOf(InterfaceTypeDefinition targetInterface) { - ImmutableList.Builder list = ImmutableList.builder(); - List typeDefinitions = getTypes(ImplementingTypeDefinition.class); - for (ImplementingTypeDefinition implementingTypeDefinition : typeDefinitions) { - List implementsList = implementingTypeDefinition.getImplements(); - for (Type iFace : implementsList) { - InterfaceTypeDefinition interfaceTypeDef = getTypeOrNull(iFace, InterfaceTypeDefinition.class); - if (interfaceTypeDef != null) { - boolean equals = interfaceTypeDef.getName().equals(targetInterface.getName()); - if (equals) { - list.add(implementingTypeDefinition); + return ImmutableKit.filter( + getTypes(ImplementingTypeDefinition.class), + implementingTypeDefinition -> { + List> implementsList = implementingTypeDefinition.getImplements(); + for (Type iFace : implementsList) { + InterfaceTypeDefinition interfaceTypeDef = getTypeOrNull(iFace, InterfaceTypeDefinition.class); + if (interfaceTypeDef != null) { + if (interfaceTypeDef.getName().equals(targetInterface.getName())) { + return true; + } + } } - } - } - } - return list.build(); + return false; + }); } /** @@ -692,11 +721,11 @@ public List getAllImplementationsOf(InterfaceTypeDef * @see TypeDefinitionRegistry#getAllImplementationsOf(InterfaceTypeDefinition) */ public List getImplementationsOf(InterfaceTypeDefinition targetInterface) { - return this.getAllImplementationsOf(targetInterface) - .stream() - .filter(typeDefinition -> typeDefinition instanceof ObjectTypeDefinition) - .map(typeDefinition -> (ObjectTypeDefinition) typeDefinition) - .collect(Collectors.toList()); + return ImmutableKit.filterAndMap( + getAllImplementationsOf(targetInterface), + typeDefinition -> typeDefinition instanceof ObjectTypeDefinition, + typeDefinition -> (ObjectTypeDefinition) typeDefinition + ); } /** From 04cbbd64e12ebe810e73f0dbd783fd459bcaafda Mon Sep 17 00:00:00 2001 From: bbaker Date: Sat, 5 Jul 2025 09:32:24 +1000 Subject: [PATCH 3/7] Improved access speed of isPossibleType - added javadoc and code tweaks --- .../graphql/schema/idl/SchemaTypeChecker.java | 10 ++++---- .../schema/idl/TypeDefinitionRegistry.java | 23 +++++++++++++++---- .../java/graphql/schema/idl/TypeInfo.java | 15 ++++++++++-- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/graphql/schema/idl/SchemaTypeChecker.java b/src/main/java/graphql/schema/idl/SchemaTypeChecker.java index 5d702b644..09aa131ab 100644 --- a/src/main/java/graphql/schema/idl/SchemaTypeChecker.java +++ b/src/main/java/graphql/schema/idl/SchemaTypeChecker.java @@ -333,8 +333,9 @@ private void checkFieldTypesPresent(TypeDefinitionRegistry typeRegistry, List checkTypeExists(String typeOfType, TypeDefinitionRegistry typeRegistry, List errors, TypeDefinition typeDefinition) { return t -> { - TypeName unwrapped = TypeInfo.typeInfo(t).getTypeName(); - if (!typeRegistry.hasType(unwrapped)) { + String name = TypeInfo.typeName(t); + if (!typeRegistry.hasType(name)) { + TypeName unwrapped = TypeInfo.typeInfo(t).getTypeName(); errors.add(new MissingTypeError(typeOfType, typeDefinition, unwrapped)); } }; @@ -342,8 +343,9 @@ private Consumer checkTypeExists(String typeOfType, TypeDefinitionRegistry private Consumer checkTypeExists(TypeDefinitionRegistry typeRegistry, List errors, String typeOfType, Node element, String elementName) { return ivType -> { - TypeName unwrapped = TypeInfo.typeInfo(ivType).getTypeName(); - if (!typeRegistry.hasType(unwrapped)) { + String name = TypeInfo.typeName(ivType); + if (!typeRegistry.hasType(name)) { + TypeName unwrapped = TypeInfo.typeInfo(ivType).getTypeName(); errors.add(new MissingTypeError(typeOfType, element, elementName, unwrapped)); } }; diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index 0d21d6c4e..3a49163e3 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -45,6 +45,7 @@ import static graphql.Assert.assertNotNull; import static graphql.schema.idl.SchemaExtensionsChecker.defineOperationDefs; import static graphql.schema.idl.SchemaExtensionsChecker.gatherOperationDefs; +import static graphql.schema.idl.TypeInfo.typeName; import static java.util.Optional.ofNullable; /** @@ -492,19 +493,33 @@ public Map getDirectiveDefinitions() { return new LinkedHashMap<>(directiveDefinitions); } + /** + * Returns true if the registry has a type of the specified {@link TypeName} + * + * @param typeName the type name to check + * + * @return true if the registry has a type by that type name + */ public boolean hasType(TypeName typeName) { String name = typeName.getName(); - return types.containsKey(name) || ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(name) || scalarTypes.containsKey(name) || objectTypeExtensions.containsKey(name); + return hasType(name); } - private static String typeName(Type type) { - return TypeInfo.getTypeName(type).getName(); + /** + * Returns true if the registry has a type of the specified name + * + * @param name the name to check + * + * @return true if the registry has a type by that name + */ + public boolean hasType(String name) { + return types.containsKey(name) || ScalarInfo.GRAPHQL_SPECIFICATION_SCALARS_DEFINITIONS.containsKey(name) || scalarTypes.containsKey(name) || objectTypeExtensions.containsKey(name); } /** * Returns am optional {@link TypeDefinition} of the specified type or {@link Optional#empty()} * - * @param type the type to check + * @param type the type to check * * @return an optional {@link TypeDefinition} or empty if it's not found */ diff --git a/src/main/java/graphql/schema/idl/TypeInfo.java b/src/main/java/graphql/schema/idl/TypeInfo.java index 9258912af..82a3499fe 100644 --- a/src/main/java/graphql/schema/idl/TypeInfo.java +++ b/src/main/java/graphql/schema/idl/TypeInfo.java @@ -140,11 +140,11 @@ public Type unwrapOneType() { } /** - * Gets the type name of a [Type], unwrapping any lists or non-null decorations + * Gets the {@link TypeName} type name of a [Type], unwrapping any lists or non-null decorations * * @param type the Type * - * @return the inner TypeName for this type + * @return the inner {@link TypeName} for this type */ public static TypeName getTypeName(Type type) { while (!(type instanceof TypeName)) { @@ -158,6 +158,17 @@ public static TypeName getTypeName(Type type) { return (TypeName) type; } + /** + * Gets the string type name of a [Type], unwrapping any lists or non-null decorations + * + * @param type the Type + * + * @return the inner string name for this type + */ + public static String typeName(Type type) { + return getTypeName(type).getName(); + } + @Override public boolean equals(Object o) { if (this == o) return true; From eaf6e40f3bdeb8b1e3907beef1c9b7cf54406d99 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sat, 5 Jul 2025 09:43:25 +1000 Subject: [PATCH 4/7] Improved access speed of isPossibleType - less code same cost --- .../graphql/schema/idl/TypeDefinitionRegistry.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index 3a49163e3..d953ef26c 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -1,6 +1,5 @@ package graphql.schema.idl; -import com.google.common.collect.ImmutableList; import graphql.Assert; import graphql.GraphQLError; import graphql.PublicApi; @@ -677,14 +676,10 @@ public boolean isObjectType(Type type) { * @return a list of types of the target class */ public List getTypes(Class targetClass) { - ImmutableList.Builder builder = ImmutableList.builder(); - for (TypeDefinition type : types.values()) { - if (targetClass.isInstance(type)) { - T typeCast = targetClass.cast(type); - builder.add(typeCast); - } - } - return builder.build(); + return ImmutableKit.filterAndMap(types.values(), + targetClass::isInstance, + targetClass::cast + ); } /** From 3e82b74372b3e2e4ef35a7f6e57d14bdea96c2f0 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sun, 6 Jul 2025 13:06:43 +1000 Subject: [PATCH 5/7] Moved back to Marc's implementation instead of precaching --- .../idl/ImmutableTypeDefinitionRegistry.java | 56 +------------------ .../schema/idl/TypeDefinitionRegistry.java | 16 ++++-- 2 files changed, 13 insertions(+), 59 deletions(-) diff --git a/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java index 66cab2c0a..fee750ac0 100644 --- a/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/ImmutableTypeDefinitionRegistry.java @@ -39,9 +39,6 @@ @NullMarked public class ImmutableTypeDefinitionRegistry extends TypeDefinitionRegistry { - private final Map> allImplementationsOf; - private final Map> implementationsOf; - ImmutableTypeDefinitionRegistry(TypeDefinitionRegistry registry) { super( copyOf(registry.objectTypeExtensions), @@ -57,50 +54,9 @@ public class ImmutableTypeDefinitionRegistry extends TypeDefinitionRegistry { registry.schema, registry.schemaParseOrder ); - allImplementationsOf = calculateAllImplementsOf(); - implementationsOf = calculateImplementationsOf(allImplementationsOf); - } - - private Map> calculateAllImplementsOf() { - ImmutableMap.Builder> mapBuilder = ImmutableMap.builder(); - List implementingTypeDefinitions = getTypes(ImplementingTypeDefinition.class); - for (TypeDefinition typeDef : types.values()) { - if (typeDef instanceof InterfaceTypeDefinition) { - InterfaceTypeDefinition interfaceTypeDef = (InterfaceTypeDefinition) typeDef; - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (ImplementingTypeDefinition implementingTypeDefinition : implementingTypeDefinitions) { - List implementsList = implementingTypeDefinition.getImplements(); - for (Type iFace : implementsList) { - Optional implementsAnInterface = getType(iFace, InterfaceTypeDefinition.class); - if (implementsAnInterface.isPresent()) { - boolean equals = implementsAnInterface.get().getName().equals(interfaceTypeDef.getName()); - if (equals) { - listBuilder.add(implementingTypeDefinition); - break; - } - } - } - } - mapBuilder.put(interfaceTypeDef, listBuilder.build()); - } - } - return mapBuilder.build(); - } - - private Map> calculateImplementationsOf(Map> allImplementationsOf1) { - ImmutableMap.Builder> mapBuilder = ImmutableMap.builder(); - for (Map.Entry> entry : allImplementationsOf1.entrySet()) { - ImmutableList.Builder listBuilder = ImmutableList.builder(); - for (ImplementingTypeDefinition implementingTypeDefinition : entry.getValue()) { - if (implementingTypeDefinition instanceof ObjectTypeDefinition) { - listBuilder.add((ObjectTypeDefinition) implementingTypeDefinition); - } - } - mapBuilder.put(entry.getKey(), listBuilder.build()); - } - return mapBuilder.build(); } + private UnsupportedOperationException unsupportedOperationException() { return new UnsupportedOperationException("The TypeDefinitionRegistry is in read only mode"); } @@ -179,14 +135,4 @@ public List getSchemaExtensionDefinitions() { public Map getDirectiveDefinitions() { return directiveDefinitions; } - - @Override - public List getAllImplementationsOf(InterfaceTypeDefinition targetInterface) { - return allImplementationsOf.getOrDefault(targetInterface, ImmutableList.of()); - } - - @Override - public List getImplementationsOf(InterfaceTypeDefinition targetInterface) { - return implementationsOf.getOrDefault(targetInterface, ImmutableList.of()); - } } diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index d953ef26c..5a1e0ba09 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -768,10 +768,18 @@ public boolean isPossibleType(Type abstractType, Type possibleType) { return false; } else { InterfaceTypeDefinition iFace = (InterfaceTypeDefinition) abstractTypeDef; - List implementingTypeDefinitions = getAllImplementationsOf(iFace); - for (ImplementingTypeDefinition implementingTypeDefinition : implementingTypeDefinitions) { - if (implementingTypeDefinition.getName().equals(targetObjectTypeDef.getName())) { - return true; + for (TypeDefinition t : types.values()) { + if (t instanceof ImplementingTypeDefinition) { + if (t.getName().equals(targetObjectTypeDef.getName())) { + ImplementingTypeDefinition itd = (ImplementingTypeDefinition) t; + + for (Type implementsType : itd.getImplements()) { + TypeDefinition matchingInterface = types.get(typeName(implementsType)); + if (matchingInterface != null && matchingInterface.getName().equals(iFace.getName())) { + return true; + } + } + } } } return false; From 21ac5c99ad4c4397dae37d0ccd89693a36747c55 Mon Sep 17 00:00:00 2001 From: bbaker Date: Sun, 6 Jul 2025 13:31:03 +1000 Subject: [PATCH 6/7] Added benchmark and bin helper --- bin/jmh.sh | 9 ++ .../CreateExtendedSchemaBenchmark.java | 121 ++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100755 bin/jmh.sh create mode 100644 src/jmh/java/benchmark/CreateExtendedSchemaBenchmark.java diff --git a/bin/jmh.sh b/bin/jmh.sh new file mode 100755 index 000000000..26aa5e946 --- /dev/null +++ b/bin/jmh.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +BRANCH=$(git rev-parse --abbrev-ref HEAD) +JAR="build/libs/graphql-java-0.0.0-$BRANCH-SNAPSHOT-jmh.jar" +echo "build and then running jmh for $JAR" + +./gradlew clean jmhJar + +java -jar "$JAR" "$@" \ No newline at end of file diff --git a/src/jmh/java/benchmark/CreateExtendedSchemaBenchmark.java b/src/jmh/java/benchmark/CreateExtendedSchemaBenchmark.java new file mode 100644 index 000000000..92c624967 --- /dev/null +++ b/src/jmh/java/benchmark/CreateExtendedSchemaBenchmark.java @@ -0,0 +1,121 @@ +package benchmark; + +import graphql.schema.GraphQLSchema; +import graphql.schema.idl.RuntimeWiring; +import graphql.schema.idl.SchemaGenerator; +import graphql.schema.idl.SchemaParser; +import graphql.schema.idl.TypeDefinitionRegistry; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.RunnerException; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.concurrent.TimeUnit; + +import static benchmark.BenchmarkUtils.runInToolingForSomeTimeThenExit; + +/** + * This JMH + */ +@Warmup(iterations = 2, time = 5) +@Measurement(iterations = 3) +@Fork(3) +public class CreateExtendedSchemaBenchmark { + + private static final String SDL = mkSDL(); + + @Benchmark + @BenchmarkMode(Mode.Throughput) + @OutputTimeUnit(TimeUnit.MINUTES) + public void benchmarkLargeSchemaCreate(Blackhole blackhole) { + blackhole.consume(createSchema(SDL)); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.MILLISECONDS) + public void benchmarkLargeSchemaCreateAvgTime(Blackhole blackhole) { + blackhole.consume(createSchema(SDL)); + } + + private static GraphQLSchema createSchema(String sdl) { + TypeDefinitionRegistry registry = new SchemaParser().parse(sdl); + return new SchemaGenerator().makeExecutableSchema(registry, RuntimeWiring.MOCKED_WIRING); + } + + /* something like + type Query { q : String } interface I { f : String } + interface I1 implements I { + f : String + f1 : String + } + type O1_1 implements I1 & I { + f : String + f1 : String + } + type O1_2 implements I1 & I { + f : String + f1 : String + } + */ + private static String mkSDL() { + int numTypes = 10000; + int numExtends = 10; + + StringBuilder sb = new StringBuilder(); + sb.append("type Query { q : String } interface I { f : String } interface X { x : String }\n"); + for (int i = 0; i < numTypes; i++) { + sb.append("interface I").append(i).append(" implements I { \n") + .append("\tf : String \n") + .append("\tf").append(i).append(" : String \n").append("}\n"); + + sb.append("type O").append(i).append(" implements I").append(i).append(" & I { \n") + .append("\tf : String \n") + .append("\tf").append(i).append(" : String \n") + .append("}\n"); + + sb.append("extend type O").append(i).append(" implements X").append(" { \n") + .append("\tx : String \n") + .append("}\n"); + + for (int j = 0; j < numExtends; j++) { + sb.append("extend type O").append(i).append(" { \n") + .append("\textendedF").append(j).append(" : String \n") + .append("}\n"); + + } + } + return sb.toString(); + } + + public static void main(String[] args) throws RunnerException { + try { + runAtStartup(); + } catch (Throwable e) { + throw new RuntimeException(e); + } + Options opt = new OptionsBuilder() + .include("benchmark.CreateExtendedSchemaBenchmark") + .build(); + + new Runner(opt).run(); + } + + private static void runAtStartup() { + runInToolingForSomeTimeThenExit( + () -> { + }, + () -> createSchema(SDL), + () -> { + } + ); + } +} \ No newline at end of file From d0cbc6361354de5cf9e65c8381cf44bbcda79d29 Mon Sep 17 00:00:00 2001 From: bbaker Date: Mon, 7 Jul 2025 20:03:46 +1000 Subject: [PATCH 7/7] deprecated the Optional getType methods and replaced all their usages --- .../idl/ArgValueOfAllowedTypeChecker.java | 6 ++- .../schema/idl/ImplementingTypesChecker.java | 15 ++++--- .../schema/idl/SchemaExtensionsChecker.java | 16 ++++---- .../schema/idl/SchemaGeneratorHelper.java | 36 ++++++++--------- .../graphql/schema/idl/SchemaTypeChecker.java | 7 ++-- .../idl/SchemaTypeDirectivesChecker.java | 16 +++++--- .../idl/SchemaTypeExtensionsChecker.java | 39 +++++++++++-------- .../schema/idl/TypeDefinitionRegistry.java | 34 ++++++++++------ .../graphql/schema/idl/UnionTypesChecker.java | 20 +++------- ...ImmutableTypeDefinitionRegistryTest.groovy | 8 ++-- .../idl/TypeDefinitionRegistryTest.groovy | 12 +++--- .../schema/idl/WiringFactoryTest.groovy | 4 +- 12 files changed, 113 insertions(+), 100 deletions(-) diff --git a/src/main/java/graphql/schema/idl/ArgValueOfAllowedTypeChecker.java b/src/main/java/graphql/schema/idl/ArgValueOfAllowedTypeChecker.java index e00a40812..1711b635c 100644 --- a/src/main/java/graphql/schema/idl/ArgValueOfAllowedTypeChecker.java +++ b/src/main/java/graphql/schema/idl/ArgValueOfAllowedTypeChecker.java @@ -122,8 +122,10 @@ private void checkArgValueMatchesAllowedTypeName(List errors, Valu } String allowedTypeName = ((TypeName) allowedArgType).getName(); - TypeDefinition allowedTypeDefinition = typeRegistry.getType(allowedTypeName) - .orElseThrow(() -> new AssertException(format("Directive unknown argument type '%s'. This should have been validated before.", allowedTypeName))); + TypeDefinition allowedTypeDefinition = typeRegistry.getTypeOrNull(allowedTypeName); + if (allowedTypeDefinition == null) { + throw new AssertException(format("Directive unknown argument type '%s'. This should have been validated before.", allowedTypeName)); + } if (allowedTypeDefinition instanceof ScalarTypeDefinition) { checkArgValueMatchesAllowedScalar(errors, instanceValue, (ScalarTypeDefinition) allowedTypeDefinition); diff --git a/src/main/java/graphql/schema/idl/ImplementingTypesChecker.java b/src/main/java/graphql/schema/idl/ImplementingTypesChecker.java index 6f2a22ec1..0294e290a 100644 --- a/src/main/java/graphql/schema/idl/ImplementingTypesChecker.java +++ b/src/main/java/graphql/schema/idl/ImplementingTypesChecker.java @@ -29,7 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Optional; +import java.util.Objects; import java.util.Set; import java.util.function.BinaryOperator; import java.util.function.Function; @@ -73,7 +73,7 @@ void checkImplementingTypes(List errors, TypeDefinitionRegistry ty private void checkImplementingType( List errors, TypeDefinitionRegistry typeRegistry, - ImplementingTypeDefinition type) { + ImplementingTypeDefinition type) { Map implementedInterfaces = checkInterfacesNotImplementedMoreThanOnce(errors, type, typeRegistry); @@ -172,7 +172,7 @@ private void checkInterfaceIsImplemented( private void checkArgumentConsistency( String typeOfType, - ImplementingTypeDefinition objectTypeDef, + ImplementingTypeDefinition objectTypeDef, InterfaceTypeDefinition interfaceTypeDef, FieldDefinition objectFieldDef, FieldDefinition interfaceFieldDef, @@ -211,7 +211,7 @@ private void checkArgumentConsistency( } private Map> getLogicallyImplementedInterfaces( - ImplementingTypeDefinition type, + ImplementingTypeDefinition type, TypeDefinitionRegistry typeRegistry ) { @@ -255,18 +255,17 @@ private BinaryOperator mergeFirstValue() { return (v1, v2) -> v1; } - private Optional toInterfaceTypeDefinition(Type type, TypeDefinitionRegistry typeRegistry) { + private InterfaceTypeDefinition toInterfaceTypeDefinition(Type type, TypeDefinitionRegistry typeRegistry) { TypeInfo typeInfo = TypeInfo.typeInfo(type); TypeName unwrapped = typeInfo.getTypeName(); - return typeRegistry.getType(unwrapped, InterfaceTypeDefinition.class); + return typeRegistry.getTypeOrNull(unwrapped, InterfaceTypeDefinition.class); } private Set toInterfaceTypeDefinitions(TypeDefinitionRegistry typeRegistry, Collection implementsTypes) { return implementsTypes.stream() .map(t -> toInterfaceTypeDefinition(t, typeRegistry)) - .filter(Optional::isPresent) - .map(Optional::get) + .filter(Objects::nonNull) .collect(toSet()); } } diff --git a/src/main/java/graphql/schema/idl/SchemaExtensionsChecker.java b/src/main/java/graphql/schema/idl/SchemaExtensionsChecker.java index cb022bb66..9a3fb7d11 100644 --- a/src/main/java/graphql/schema/idl/SchemaExtensionsChecker.java +++ b/src/main/java/graphql/schema/idl/SchemaExtensionsChecker.java @@ -76,10 +76,10 @@ static List checkSchemaInvariants(List er // ensure we have a "query" one Optional query = operationTypeDefinitions.stream().filter(op -> "query".equals(op.getName())).findFirst(); - if (!query.isPresent()) { + if (query.isEmpty()) { // its ok if they have a type named Query - Optional queryType = typeRegistry.getType("Query"); - if (!queryType.isPresent()) { + TypeDefinition queryType = typeRegistry.getTypeOrNull("Query"); + if (queryType == null) { errors.add(new QueryOperationMissingError()); } } @@ -117,13 +117,13 @@ private static Consumer checkOperationTypesExist(TypeDe private static Consumer checkOperationTypesAreObjects(TypeDefinitionRegistry typeRegistry, List errors) { return op -> { // make sure it is defined as a ObjectTypeDef - Type queryType = op.getTypeName(); - Optional type = typeRegistry.getType(queryType); - type.ifPresent(typeDef -> { - if (!(typeDef instanceof ObjectTypeDefinition)) { + Type queryType = op.getTypeName(); + TypeDefinition type = typeRegistry.getTypeOrNull(queryType); + if (type != null) { + if (!(type instanceof ObjectTypeDefinition)) { errors.add(new OperationTypesMustBeObjects(op)); } - }); + } }; } diff --git a/src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java b/src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java index 521bb185b..768253fe5 100644 --- a/src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java +++ b/src/main/java/graphql/schema/idl/SchemaGeneratorHelper.java @@ -141,11 +141,12 @@ public TypeDefinitionRegistry getTypeRegistry() { } TypeDefinition getTypeDefinition(Type type) { - Optional optionalTypeDefinition = typeRegistry.getType(type); - - return optionalTypeDefinition.orElseThrow( - () -> new AssertException(format(" type definition for type '%s' not found", type)) - ); + TypeDefinition typeDefinition = typeRegistry.getTypeOrNull(type); + if (typeDefinition != null) { + return typeDefinition; + } else { + throw new AssertException(format(" type definition for type '%s' not found", type)); + } } boolean stackContains(TypeInfo typeInfo) { @@ -905,9 +906,8 @@ void buildOperations(BuildContext buildCtx, GraphQLSchema.Builder schemaBuilder) GraphQLObjectType subscription; Optional queryOperation = getOperationNamed("query", operationTypeDefs); - if (!queryOperation.isPresent()) { - @SuppressWarnings({"OptionalGetWithoutIsPresent"}) - TypeDefinition queryTypeDef = typeRegistry.getType("Query").get(); + if (queryOperation.isEmpty()) { + TypeDefinition queryTypeDef = Objects.requireNonNull(typeRegistry.getTypeOrNull("Query")); query = buildOutputType(buildCtx, TypeName.newTypeName().name(queryTypeDef.getName()).build()); } else { query = buildOperation(buildCtx, queryOperation.get()); @@ -915,12 +915,12 @@ void buildOperations(BuildContext buildCtx, GraphQLSchema.Builder schemaBuilder) schemaBuilder.query(query); Optional mutationOperation = getOperationNamed("mutation", operationTypeDefs); - if (!mutationOperation.isPresent()) { - if (!typeRegistry.schemaDefinition().isPresent()) { + if (mutationOperation.isEmpty()) { + if (typeRegistry.schemaDefinition().isEmpty()) { // If no schema definition, then there is no schema keyword. Default to using type called Mutation - Optional mutationTypeDef = typeRegistry.getType("Mutation"); - if (mutationTypeDef.isPresent()) { - mutation = buildOutputType(buildCtx, TypeName.newTypeName().name(mutationTypeDef.get().getName()).build()); + TypeDefinition mutationTypeDef = typeRegistry.getTypeOrNull("Mutation"); + if (mutationTypeDef != null) { + mutation = buildOutputType(buildCtx, TypeName.newTypeName().name(mutationTypeDef.getName()).build()); schemaBuilder.mutation(mutation); } } @@ -930,12 +930,12 @@ void buildOperations(BuildContext buildCtx, GraphQLSchema.Builder schemaBuilder) } Optional subscriptionOperation = getOperationNamed("subscription", operationTypeDefs); - if (!subscriptionOperation.isPresent()) { - if (!typeRegistry.schemaDefinition().isPresent()) { + if (subscriptionOperation.isEmpty()) { + if (typeRegistry.schemaDefinition().isEmpty()) { // If no schema definition, then there is no schema keyword. Default to using type called Subscription - Optional subscriptionTypeDef = typeRegistry.getType("Subscription"); - if (subscriptionTypeDef.isPresent()) { - subscription = buildOutputType(buildCtx, TypeName.newTypeName().name(subscriptionTypeDef.get().getName()).build()); + TypeDefinition subscriptionTypeDef = typeRegistry.getTypeOrNull("Subscription"); + if (subscriptionTypeDef != null) { + subscription = buildOutputType(buildCtx, TypeName.newTypeName().name(subscriptionTypeDef.getName()).build()); schemaBuilder.subscription(subscription); } } diff --git a/src/main/java/graphql/schema/idl/SchemaTypeChecker.java b/src/main/java/graphql/schema/idl/SchemaTypeChecker.java index 09aa131ab..b57a4f879 100644 --- a/src/main/java/graphql/schema/idl/SchemaTypeChecker.java +++ b/src/main/java/graphql/schema/idl/SchemaTypeChecker.java @@ -34,7 +34,6 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -355,10 +354,10 @@ private Consumer checkInterfaceTypeExists(TypeDefinitionRegistry t return t -> { TypeInfo typeInfo = TypeInfo.typeInfo(t); TypeName unwrapped = typeInfo.getTypeName(); - Optional type = typeRegistry.getType(unwrapped); - if (!type.isPresent()) { + TypeDefinition type = typeRegistry.getTypeOrNull(unwrapped); + if (type == null) { errors.add(new MissingInterfaceTypeError("interface", typeDefinition, unwrapped)); - } else if (!(type.get() instanceof InterfaceTypeDefinition)) { + } else if (!(type instanceof InterfaceTypeDefinition)) { errors.add(new MissingInterfaceTypeError("interface", typeDefinition, unwrapped)); } }; diff --git a/src/main/java/graphql/schema/idl/SchemaTypeDirectivesChecker.java b/src/main/java/graphql/schema/idl/SchemaTypeDirectivesChecker.java index 8ec32a055..eb87b563a 100644 --- a/src/main/java/graphql/schema/idl/SchemaTypeDirectivesChecker.java +++ b/src/main/java/graphql/schema/idl/SchemaTypeDirectivesChecker.java @@ -137,7 +137,7 @@ private void checkFieldsDirectives(List errors, TypeDefinitionRegi private void checkDirectives(DirectiveLocation expectedLocation, List errors, TypeDefinitionRegistry typeRegistry, Node element, String elementName, List directives) { directives.forEach(directive -> { Optional directiveDefinition = typeRegistry.getDirectiveDefinition(directive.getName()); - if (!directiveDefinition.isPresent()) { + if (directiveDefinition.isEmpty()) { errors.add(new DirectiveUndeclaredError(element, elementName, directive.getName())); } else { if (!inRightLocation(expectedLocation, directiveDefinition.get())) { @@ -157,7 +157,7 @@ private boolean inRightLocation(DirectiveLocation expectedLocation, DirectiveDef return names.contains(expectedLocation.name().toUpperCase()); } - private void checkDirectiveArguments(List errors, TypeDefinitionRegistry typeRegistry, Node element, String elementName, Directive directive, DirectiveDefinition directiveDefinition) { + private void checkDirectiveArguments(List errors, TypeDefinitionRegistry typeRegistry, Node element, String elementName, Directive directive, DirectiveDefinition directiveDefinition) { Map allowedArgs = getByName(directiveDefinition.getInputValueDefinitions(), (InputValueDefinition::getName), mergeFirst()); Map providedArgs = getByName(directive.getArguments(), (Argument::getName), mergeFirst()); directive.getArguments().forEach(argument -> { @@ -195,7 +195,7 @@ private void commonCheck(Collection directiveDefinitions, L }); } - private void assertTypeName(NamedNode node, List errors) { + private void assertTypeName(NamedNode node, List errors) { if (node.getName().length() >= 2 && node.getName().startsWith("__")) { errors.add((new IllegalNameError(node))); } @@ -204,7 +204,7 @@ private void assertTypeName(NamedNode node, List errors) { public void assertExistAndIsInputType(InputValueDefinition definition, List errors) { TypeName namedType = TypeUtil.unwrapAll(definition.getType()); - TypeDefinition unwrappedType = findTypeDefFromRegistry(namedType.getName(), typeRegistry); + TypeDefinition unwrappedType = findTypeDefFromRegistry(namedType.getName(), typeRegistry); if (unwrappedType == null) { errors.add(new MissingTypeError(namedType.getName(), definition, definition.getName())); @@ -218,7 +218,11 @@ public void assertExistAndIsInputType(InputValueDefinition definition, List typeRegistry.scalars().get(typeName)); + private TypeDefinition findTypeDefFromRegistry(String typeName, TypeDefinitionRegistry typeRegistry) { + TypeDefinition typeDefinition = typeRegistry.getTypeOrNull(typeName); + if (typeDefinition != null) { + return typeDefinition; + } + return typeRegistry.scalars().get(typeName); } } \ No newline at end of file diff --git a/src/main/java/graphql/schema/idl/SchemaTypeExtensionsChecker.java b/src/main/java/graphql/schema/idl/SchemaTypeExtensionsChecker.java index 36b4a2c3f..fe233dcbf 100644 --- a/src/main/java/graphql/schema/idl/SchemaTypeExtensionsChecker.java +++ b/src/main/java/graphql/schema/idl/SchemaTypeExtensionsChecker.java @@ -88,9 +88,10 @@ private void checkObjectTypeExtensions(List errors, TypeDefinition // // then check for field re-defs from the base type - Optional baseTypeOpt = typeRegistry.getType(extension.getName(), ObjectTypeDefinition.class); - baseTypeOpt.ifPresent(baseTypeDef -> checkForFieldRedefinition(errors, extension, fieldDefinitions, baseTypeDef.getFieldDefinitions())); - + ObjectTypeDefinition baseTypeDef = typeRegistry.getTypeOrNull(extension.getName(), ObjectTypeDefinition.class); + if (baseTypeDef != null) { + checkForFieldRedefinition(errors, extension, fieldDefinitions, baseTypeDef.getFieldDefinitions()); + } }); } ); @@ -132,8 +133,10 @@ private void checkInterfaceTypeExtensions(List errors, TypeDefinit // // then check for field re-defs from the base type - Optional baseTypeOpt = typeRegistry.getType(extension.getName(), InterfaceTypeDefinition.class); - baseTypeOpt.ifPresent(baseTypeDef -> checkForFieldRedefinition(errors, extension, fieldDefinitions, baseTypeDef.getFieldDefinitions())); + InterfaceTypeDefinition baseTypeDef = typeRegistry.getTypeOrNull(extension.getName(), InterfaceTypeDefinition.class); + if (baseTypeDef != null) { + checkForFieldRedefinition(errors, extension, fieldDefinitions, baseTypeDef.getFieldDefinitions()); + } }); }); } @@ -161,8 +164,8 @@ private void checkUnionTypeExtensions(List errors, TypeDefinitionR memberTypes.forEach( memberType -> { - Optional unionTypeDefinition = typeRegistry.getType(memberType, ObjectTypeDefinition.class); - if (!unionTypeDefinition.isPresent()) { + ObjectTypeDefinition unionTypeDefinition = typeRegistry.getTypeOrNull(memberType, ObjectTypeDefinition.class); + if (unionTypeDefinition == null) { errors.add(new MissingTypeError("union member", extension, memberType)); } } @@ -197,8 +200,10 @@ private void checkEnumTypeExtensions(List errors, TypeDefinitionRe // // then check for field re-defs from the base type - Optional baseTypeOpt = typeRegistry.getType(extension.getName(), EnumTypeDefinition.class); - baseTypeOpt.ifPresent(baseTypeDef -> checkForEnumValueRedefinition(errors, extension, enumValueDefinitions, baseTypeDef.getEnumValueDefinitions())); + EnumTypeDefinition baseTypeDef = typeRegistry.getTypeOrNull(extension.getName(), EnumTypeDefinition.class); + if (baseTypeDef != null) { + checkForEnumValueRedefinition(errors, extension, enumValueDefinitions, baseTypeDef.getEnumValueDefinitions()); + } }); @@ -251,8 +256,10 @@ private void checkInputObjectTypeExtensions(List errors, TypeDefin // // then check for field re-defs from the base type - Optional baseTypeOpt = typeRegistry.getType(extension.getName(), InputObjectTypeDefinition.class); - baseTypeOpt.ifPresent(baseTypeDef -> checkForInputValueRedefinition(errors, extension, inputValueDefinitions, baseTypeDef.getInputValueDefinitions())); + InputObjectTypeDefinition baseTypeDef = typeRegistry.getTypeOrNull(extension.getName(), InputObjectTypeDefinition.class); + if (baseTypeDef != null) { + checkForInputValueRedefinition(errors, extension, inputValueDefinitions, baseTypeDef.getInputValueDefinitions()); + } }); }); @@ -260,16 +267,16 @@ private void checkInputObjectTypeExtensions(List errors, TypeDefin private void checkTypeExtensionHasCorrespondingType(List errors, TypeDefinitionRegistry typeRegistry, String name, List extTypeList, Class targetClass) { - TypeDefinition extensionDefinition = extTypeList.get(0); - Optional typeDefinition = typeRegistry.getType(TypeName.newTypeName().name(name).build(), targetClass); - if (!typeDefinition.isPresent()) { + TypeDefinition extensionDefinition = extTypeList.get(0); + TypeDefinition typeDefinition = typeRegistry.getTypeOrNull(TypeName.newTypeName().name(name).build(), targetClass); + if (typeDefinition == null) { errors.add(new TypeExtensionMissingBaseTypeError(extensionDefinition)); } } @SuppressWarnings("unchecked") - private void checkForFieldRedefinition(List errors, TypeDefinition typeDefinition, List fieldDefinitions, List referenceFieldDefinitions) { + private void checkForFieldRedefinition(List errors, TypeDefinition typeDefinition, List fieldDefinitions, List referenceFieldDefinitions) { Map referenceMap = FpKit.getByName(referenceFieldDefinitions, FieldDefinition::getName, mergeFirst()); @@ -290,7 +297,7 @@ private void checkForInputValueRedefinition(List errors, InputObje }); } - private void checkForEnumValueRedefinition(List errors, TypeDefinition typeDefinition, List enumValueDefinitions, List referenceEnumValueDefinitions) { + private void checkForEnumValueRedefinition(List errors, TypeDefinition typeDefinition, List enumValueDefinitions, List referenceEnumValueDefinitions) { Map referenceMap = FpKit.getByName(referenceEnumValueDefinitions, EnumValueDefinition::getName, mergeFirst()); diff --git a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java index 5a1e0ba09..850e7b215 100644 --- a/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java +++ b/src/main/java/graphql/schema/idl/TypeDefinitionRegistry.java @@ -346,6 +346,7 @@ public void remove(SDLDefinition definition) { } private void removeFromList(Map source, TypeDefinition value) { + //noinspection unchecked List list = (List) source.get(value.getName()); if (list == null) { return; @@ -516,47 +517,61 @@ public boolean hasType(String name) { } /** - * Returns am optional {@link TypeDefinition} of the specified type or {@link Optional#empty()} + * Returns an optional {@link TypeDefinition} of the specified type or {@link Optional#empty()} * * @param type the type to check * * @return an optional {@link TypeDefinition} or empty if it's not found + * + * @deprecated use the {@link #getTypeOrNull(Type)} variants instead since they avoid the allocation of an + * optional object */ + @Deprecated(since = "2025-07-7") public Optional getType(Type type) { - return getType(typeName(type)); + return Optional.ofNullable(getTypeOrNull(type)); } /** - * Returns am optional {@link TypeDefinition} of the specified type with the specified class or {@link Optional#empty()} + * Returns an optional {@link TypeDefinition} of the specified type with the specified class or {@link Optional#empty()} * * @param type the type to check * @param ofType the class of {@link TypeDefinition} * * @return an optional {@link TypeDefinition} or empty if it's not found + * + * @deprecated use the {@link #getTypeOrNull(Type)} variants instead since they avoid the allocation of an + * optional object */ + @Deprecated(since = "2025-07-7") public Optional getType(Type type, Class ofType) { - return getType(typeName(type), ofType); + return Optional.ofNullable(getTypeOrNull(typeName(type), ofType)); } /** - * Returns am optional {@link TypeDefinition} of the specified type name or {@link Optional#empty()} + * Returns an optional {@link TypeDefinition} of the specified type name or {@link Optional#empty()} * * @param typeName the type to check * * @return an optional {@link TypeDefinition} or empty if it's not found + * + * @deprecated use the {@link #getTypeOrNull(Type)} variants instead since they avoid the allocation of an + * optional object */ + @Deprecated(since = "2025-07-7") public Optional getType(String typeName) { return Optional.ofNullable(getTypeOrNull(typeName)); } /** - * Returns am optional {@link TypeDefinition} of the specified type name with the specified class or {@link Optional#empty()} + * Returns an optional {@link TypeDefinition} of the specified type name with the specified class or {@link Optional#empty()} * * @param typeName the type to check * @param ofType the class of {@link TypeDefinition} * - * @return an optional {@link TypeDefinition} or empty if it's not found + * @deprecated use the {@link #getTypeOrNull(Type)} variants instead since they avoid the allocation of an + * optional object */ + @Deprecated(since = "2025-07-7") public Optional getType(String typeName, Class ofType) { return Optional.ofNullable(getTypeOrNull(typeName, ofType)); } @@ -600,10 +615,7 @@ public TypeDefinition getTypeOrNull(String typeName) { return typeDefinition; } typeDefinition = scalars().get(typeName); - if (typeDefinition != null) { - return typeDefinition; - } - return null; + return typeDefinition; } /** diff --git a/src/main/java/graphql/schema/idl/UnionTypesChecker.java b/src/main/java/graphql/schema/idl/UnionTypesChecker.java index 73e11b3e0..f2134b2d5 100644 --- a/src/main/java/graphql/schema/idl/UnionTypesChecker.java +++ b/src/main/java/graphql/schema/idl/UnionTypesChecker.java @@ -10,11 +10,8 @@ import graphql.language.UnionTypeExtensionDefinition; import graphql.schema.idl.errors.UnionTypeError; -import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.Set; import java.util.stream.Stream; @@ -33,13 +30,6 @@ */ @Internal class UnionTypesChecker { - private static final Map, String> TYPE_OF_MAP = new HashMap<>(); - - static { - TYPE_OF_MAP.put(UnionTypeDefinition.class, "union"); - TYPE_OF_MAP.put(UnionTypeExtensionDefinition.class, "union extension"); - } - void checkUnionType(List errors, TypeDefinitionRegistry typeRegistry) { List unionTypes = typeRegistry.getTypes(UnionTypeDefinition.class); @@ -52,18 +42,18 @@ void checkUnionType(List errors, TypeDefinitionRegistry typeRegist private void checkUnionType(TypeDefinitionRegistry typeRegistry, UnionTypeDefinition unionTypeDefinition, List errors) { assertTypeName(unionTypeDefinition, errors); + //noinspection rawtypes List memberTypes = unionTypeDefinition.getMemberTypes(); - if (memberTypes == null || memberTypes.size() == 0) { + if (memberTypes == null || memberTypes.isEmpty()) { errors.add(new UnionTypeError(unionTypeDefinition, format("Union type '%s' must include one or more member types.", unionTypeDefinition.getName()))); return; } Set typeNames = new LinkedHashSet<>(); - for (Type memberType : memberTypes) { + for (Type memberType : memberTypes) { String memberTypeName = ((TypeName) memberType).getName(); - Optional memberTypeDefinition = typeRegistry.getType(memberTypeName); - - if (!memberTypeDefinition.isPresent() || !(memberTypeDefinition.get() instanceof ObjectTypeDefinition)) { + TypeDefinition memberTypeDefinition = typeRegistry.getTypeOrNull(memberTypeName); + if (!(memberTypeDefinition instanceof ObjectTypeDefinition)) { errors.add(new UnionTypeError(unionTypeDefinition, format("The member types of a Union type must all be Object base types. member type '%s' in Union '%s' is invalid.", ((TypeName) memberType).getName(), unionTypeDefinition.getName()))); continue; } diff --git a/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy b/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy index 95a6ff0b3..9bf440c57 100644 --- a/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy +++ b/src/test/groovy/graphql/schema/idl/ImmutableTypeDefinitionRegistryTest.groovy @@ -51,8 +51,8 @@ class ImmutableTypeDefinitionRegistryTest extends Specification { then: - TypeDefinition typeIn = registryIn.getType(typeName).get() - TypeDefinition typeOut = registryOut.getType(typeName).get() + TypeDefinition typeIn = registryIn.getTypeOrNull(typeName) + TypeDefinition typeOut = registryOut.getTypeOrNull(typeName) typeIn.isEqualTo(typeOut) where: @@ -74,8 +74,8 @@ class ImmutableTypeDefinitionRegistryTest extends Specification { containsSameObjects(mutableRegistry.types(), immutableRegistry.types()) - TypeDefinition typeIn = mutableRegistry.getType(typeName).get() - TypeDefinition typeOut = immutableRegistry.getType(typeName).get() + TypeDefinition typeIn = mutableRegistry.getTypeOrNull(typeName) + TypeDefinition typeOut = immutableRegistry.getTypeOrNull(typeName) typeIn.isEqualTo(typeOut) where: diff --git a/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy b/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy index 9c48e9308..0ebd6dc88 100644 --- a/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy +++ b/src/test/groovy/graphql/schema/idl/TypeDefinitionRegistryTest.groovy @@ -410,7 +410,7 @@ class TypeDefinitionRegistryTest extends Specification { if (typeOfReg == "immutable") { registry = registry.readOnly() } - def interfaceDef = registry.getType("Interface", InterfaceTypeDefinition.class).get() + def interfaceDef = registry.getTypeOrNull("Interface", InterfaceTypeDefinition.class) def implementingTypeDefinitions = registry.getAllImplementationsOf(interfaceDef) def names = implementingTypeDefinitions.collect { it.getName() } then: @@ -554,7 +554,7 @@ class TypeDefinitionRegistryTest extends Specification { when: registry.remove(definition) then: - !registry.getType(definition.getName()).isPresent() + registry.getTypeOrNull(definition.getName()) == null where: definition | _ @@ -947,8 +947,8 @@ class TypeDefinitionRegistryTest extends Specification { when: registry.addAll(Arrays.asList(obj1, obj2)) then: - registry.getType("foo").isPresent() - registry.getType("bar").isPresent() + registry.getTypeOrNull("foo") != null + registry.getTypeOrNull("bar") != null } def "addAll will return an error on the first abd thing"() { @@ -1001,8 +1001,8 @@ class TypeDefinitionRegistryTest extends Specification { TypeDefinitionRegistry registryIn = serialise(registryOut) then: - TypeDefinition typeIn = registryIn.getType(typeName).get() - TypeDefinition typeOut = registryOut.getType(typeName).get() + TypeDefinition typeIn = registryIn.getTypeOrNull(typeName) + TypeDefinition typeOut = registryOut.getTypeOrNull(typeName) typeIn.isEqualTo(typeOut) where: diff --git a/src/test/groovy/graphql/schema/idl/WiringFactoryTest.groovy b/src/test/groovy/graphql/schema/idl/WiringFactoryTest.groovy index edb7efc12..70c96fc7d 100644 --- a/src/test/groovy/graphql/schema/idl/WiringFactoryTest.groovy +++ b/src/test/groovy/graphql/schema/idl/WiringFactoryTest.groovy @@ -259,7 +259,7 @@ class WiringFactoryTest extends Specification { boolean providesDataFetcher(FieldWiringEnvironment environment) { assert ["id", "name", "homePlanet"].contains(environment.fieldDefinition.name) assert environment.parentType.name == "Human" - assert environment.registry.getType("Human").isPresent() + assert environment.registry.getTypeOrNull("Human") != null return true } @@ -267,7 +267,7 @@ class WiringFactoryTest extends Specification { DataFetcher getDataFetcher(FieldWiringEnvironment environment) { assert ["id", "name", "homePlanet"].contains(environment.fieldDefinition.name) assert environment.parentType.name == "Human" - assert environment.registry.getType("Human").isPresent() + assert environment.registry.getTypeOrNull("Human") != null new PropertyDataFetcher(environment.fieldDefinition.name) } }