diff --git a/Server/src/main/java/prompto/graphql/GraphQLServlet.java b/Server/src/main/java/prompto/graphql/GraphQLServlet.java index e0838bb1..8dd458f9 100644 --- a/Server/src/main/java/prompto/graphql/GraphQLServlet.java +++ b/Server/src/main/java/prompto/graphql/GraphQLServlet.java @@ -21,6 +21,8 @@ import graphql.ExecutionResult; import graphql.GraphQL; import graphql.schema.GraphQLSchema; +import graphql.schema.idl.SchemaPrinter; +import graphql.schema.idl.SchemaPrinter.Options; import prompto.code.ICodeStore; import prompto.declaration.IDeclaration; import prompto.server.CleverServlet; @@ -92,16 +94,21 @@ private ExecutionResult executeRequest(GraphQLRequest request) { return gql.execute(input); } - GraphQLSchema getGraphQLSchema() { + GraphQLSchema getSchema() { if(schema==null) synchronized(this) { schema = new GraphQLSchemaBuilder().build(); } return schema; } + public String getSDL() { + var options = Options.defaultOptions().includeDirectives(false); + return new SchemaPrinter(options).print(getSchema()); + } + GraphQL getGraphQL() { if(graphQL==null) synchronized(this) { - graphQL = GraphQL.newGraphQL(getGraphQLSchema()).build(); + graphQL = GraphQL.newGraphQL(getSchema()).build(); } return graphQL; } diff --git a/Server/src/main/java/prompto/graphql/GraphQLType.java b/Server/src/main/java/prompto/graphql/GraphQLType.java index f581653a..85ec8392 100644 --- a/Server/src/main/java/prompto/graphql/GraphQLType.java +++ b/Server/src/main/java/prompto/graphql/GraphQLType.java @@ -148,12 +148,15 @@ private GraphQLOutputType _buildOutputCategoryType(CategoryDeclaration decl, Gra private GraphQLUnionType _buildOutputUnionCategoryType(CategoryDeclaration decl, List derived, Builder registry) { var builder = GraphQLUnionType.newUnionType() .name(decl.getName() + "Union"); - builder.possibleType(_buildOutputSimpleCategoryType(decl, registry)); - derived.forEach(type -> { + if(!decl.isAbstract()) + builder = builder.possibleType(_buildOutputSimpleCategoryType(decl, registry)); + for(var type : derived) { var outputType = build(type, registry).outputType(); if(outputType instanceof GraphQLObjectType) - builder.possibleType((GraphQLObjectType)outputType); - }); + builder = builder.possibleType((GraphQLObjectType)outputType); + else if(outputType instanceof GraphQLUnionType) + builder = builder.possibleTypes(((GraphQLUnionType)outputType).getTypes().toArray(new GraphQLObjectType[0])); + }; GraphQLUnionType unionType = builder.build(); registry.typeResolver(unionType, env -> { Object o = env.getObject(); diff --git a/Server/src/test/java/prompto/graphql/TestGraphQLServlet.java b/Server/src/test/java/prompto/graphql/TestGraphQLServlet.java index 4270b6c9..0ff34ba0 100644 --- a/Server/src/test/java/prompto/graphql/TestGraphQLServlet.java +++ b/Server/src/test/java/prompto/graphql/TestGraphQLServlet.java @@ -52,6 +52,8 @@ private T linkResourceAndRunQuery(String resourceName, Dialect dialect, Stri Standalone.synchronizeSchema(ICodeStore.getInstance(), DataStore.getInstance()); GraphQLServlet.reset(); GraphQLServlet servlet = GraphQLServlet.instance.get(); + @SuppressWarnings("unused") + var sdl = servlet.getSDL(); GraphQL graphQL = servlet.getGraphQL(); ExecutionResult result = graphQL.execute(query); assertNotNull(result); @@ -101,20 +103,20 @@ public void returnsInstances() throws Exception { @Test public void returnsAbstractChild() throws Exception { - Map s = linkResourceAndRunQuery("instance", Dialect.O, "{ returnsAbstractChild { __typename ... on Child1 { name, persons { firstName } } ... on Child2 { name, persons { firstName } } } }"); + Map s = linkResourceAndRunQuery("instance", Dialect.O, "{ returnsAbstractChild { __typename ... on Child { name, persons { firstName } } ... on GrandChild { name, persons { firstName } } } }"); Map i = (Map) s.get("returnsAbstractChild"); - assertEquals("Child1", i.get("name")); + assertEquals("Child", i.get("name")); } @Test public void returnsAbstractChildren() throws Exception { - Map s = linkResourceAndRunQuery("instance", Dialect.O, "{ returnsAbstractChildren { __typename ... on Parent { name } ... on Child1 { name, persons { firstName } } ... on Child2 { name, persons { firstName } } } }"); + Map s = linkResourceAndRunQuery("instance", Dialect.O, "{ returnsAbstractChildren { __typename ... on Parent { name } ... on Child { name, persons { firstName } } ... on GrandChild { name, persons { firstName } } } }"); List> l = (List>) s.get("returnsAbstractChildren"); assertEquals(3, l.size()); Map i = l.get(0); - assertEquals("Child1", i.get("name")); + assertEquals("Child", i.get("name")); i = l.get(1); - assertEquals("Child2", i.get("name")); + assertEquals("GrandChild", i.get("name")); i = l.get(2); assertEquals("Parent", i.get("name")); } diff --git a/Server/src/test/resources/graphql-tests/instance.poc b/Server/src/test/resources/graphql-tests/instance.poc index 0005dd41..ee903a34 100644 --- a/Server/src/test/resources/graphql-tests/instance.poc +++ b/Server/src/test/resources/graphql-tests/instance.poc @@ -16,15 +16,15 @@ Person[] method returnsInstances() { attribute persons: Person[]; category Parent(name, persons); -category Child1 extends Parent; -category Child2 extends Parent; +category Child extends Parent; +category GrandChild extends Child; @GraphQLQuery Parent method returnsAbstractChild() { - return (Parent)Child1(name = "Child1", persons = [Person(firstName = "Eric")]); + return (Parent)Child(name = "Child", persons = [Person(firstName = "Eric")]); } @GraphQLQuery Parent[] method returnsAbstractChildren() { - return [Child1(name = "Child1", persons= [Person(firstName = "Eric")]), Child2(name = "Child2"), Parent(name = "Parent")]; + return [Child(name = "Child", persons= [Person(firstName = "Eric")]), GrandChild(name = "GrandChild"), Parent(name = "Parent")]; } \ No newline at end of file