Skip to content

Commit

Permalink
[3656] Add the ability to customize the GraphQL type resolver
Browse files Browse the repository at this point in the history
Bug: #3656
Signed-off-by: Stéphane Bégaudeau <[email protected]>
  • Loading branch information
sbegaudeau committed Jun 20, 2024
1 parent 4f3b627 commit 486c28b
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ image:doc/screenshots/insideLabelPositions.png[Inside label positions, 70%]
- https://github.com/eclipse-sirius/sirius-web/issues/3604[#3604] [diagram] Make node overlap resolution faster during "Arrange All"
- https://github.com/eclipse-sirius/sirius-web/issues/3653[#3653] [gantt] Add documentation for gantt representation
- https://github.com/eclipse-sirius/sirius-web/issues/3634[#3634] [sirius-web] Simplifying the contribution to the GraphQL subscription of the diagram for custom nodes
- https://github.com/eclipse-sirius/sirius-web/issues/3656[#3656] [core] Add the ability to customize the GraphQL type resolver


== v2024.5.0

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.components.graphql.api;

import graphql.TypeResolutionEnvironment;
import graphql.schema.GraphQLObjectType;

/**
* Used to find GraphQL object type not found by the reflective type resolver.
*
* @author sbegaudeau
*/
public interface ITypeResolverDelegate {
GraphQLObjectType getType(TypeResolutionEnvironment environment);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 Obeo.
* Copyright (c) 2019, 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -12,6 +12,9 @@
*******************************************************************************/
package org.eclipse.sirius.components.graphql.api;

import java.util.List;
import java.util.Objects;

import graphql.TypeResolutionEnvironment;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
Expand All @@ -24,11 +27,27 @@
*/
public class ReflectiveTypeResolver implements TypeResolver {

private final List<ITypeResolverDelegate> typeResolverDelegates;

public ReflectiveTypeResolver(List<ITypeResolverDelegate> typeResolverDelegates) {
this.typeResolverDelegates = Objects.requireNonNull(typeResolverDelegates);
}

@Override
public GraphQLObjectType getType(TypeResolutionEnvironment environment) {
GraphQLSchema graphQLSchema = environment.getSchema();
Object object = environment.getObject();
return graphQLSchema.getObjectType(object.getClass().getSimpleName());
var graphQLObjectType = graphQLSchema.getObjectType(object.getClass().getSimpleName());

if (graphQLObjectType == null) {
graphQLObjectType = this.typeResolverDelegates.stream()
.map(typeResolverDelegate -> typeResolverDelegate.getType(environment))
.filter(Objects::nonNull)
.findFirst()
.orElse(null);
}

return graphQLObjectType;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2021, 2022 Obeo.
* Copyright (c) 2021, 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
Expand All @@ -12,6 +12,10 @@
*******************************************************************************/
package org.eclipse.sirius.web.graphql.configuration;

import java.util.List;
import java.util.Objects;

import org.eclipse.sirius.components.graphql.api.ITypeResolverDelegate;
import org.eclipse.sirius.components.graphql.api.ReflectiveTypeResolver;
import org.springframework.stereotype.Service;

Expand All @@ -28,14 +32,20 @@
@Service
public class GraphQLWiringFactory implements WiringFactory {

private final List<ITypeResolverDelegate> typeResolverDelegates;

public GraphQLWiringFactory(List<ITypeResolverDelegate> typeResolverDelegates) {
this.typeResolverDelegates = Objects.requireNonNull(typeResolverDelegates);
}

@Override
public boolean providesTypeResolver(InterfaceWiringEnvironment environment) {
return true;
}

@Override
public TypeResolver getTypeResolver(InterfaceWiringEnvironment environment) {
return new ReflectiveTypeResolver();
return new ReflectiveTypeResolver(this.typeResolverDelegates);
}

@Override
Expand All @@ -45,6 +55,6 @@ public boolean providesTypeResolver(UnionWiringEnvironment environment) {

@Override
public TypeResolver getTypeResolver(UnionWiringEnvironment environment) {
return new ReflectiveTypeResolver();
return new ReflectiveTypeResolver(this.typeResolverDelegates);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
*******************************************************************************/
package org.eclipse.sirius.web.infrastructure.graphql;

import java.util.List;
import java.util.Objects;

import org.eclipse.sirius.components.graphql.api.ITypeResolverDelegate;
import org.eclipse.sirius.components.graphql.api.ReflectiveTypeResolver;
import org.springframework.stereotype.Service;

Expand All @@ -28,14 +32,20 @@
@Service
public class GraphQLWiringFactory implements WiringFactory {

private final List<ITypeResolverDelegate> typeResolverDelegates;

public GraphQLWiringFactory(List<ITypeResolverDelegate> typeResolverDelegates) {
this.typeResolverDelegates = Objects.requireNonNull(typeResolverDelegates);
}

@Override
public boolean providesTypeResolver(InterfaceWiringEnvironment environment) {
return true;
}

@Override
public TypeResolver getTypeResolver(InterfaceWiringEnvironment environment) {
return new ReflectiveTypeResolver();
return new ReflectiveTypeResolver(this.typeResolverDelegates);
}

@Override
Expand All @@ -45,6 +55,6 @@ public boolean providesTypeResolver(UnionWiringEnvironment environment) {

@Override
public TypeResolver getTypeResolver(UnionWiringEnvironment environment) {
return new ReflectiveTypeResolver();
return new ReflectiveTypeResolver(this.typeResolverDelegates);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.web.application.services;

import static org.assertj.core.api.Assertions.assertThat;

import org.eclipse.sirius.web.AbstractIntegrationTests;
import org.eclipse.sirius.web.infrastructure.graphql.GraphQLWiringFactory;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import graphql.GraphQL;
import graphql.execution.TypeResolutionParameters;
import graphql.schema.idl.InterfaceWiringEnvironment;

/**
* Used to test the GraphQL type resolution.
*
* @author sbegaudeau
*/
@Transactional
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TypeResolverTests extends AbstractIntegrationTests {

@Autowired
private GraphQLWiringFactory graphQLWiringFactory;

@Autowired
private GraphQL graphQL;

@Test
@DisplayName("Given the type resolver, when asked for a unknown type, then the expected type is returned")
public void givenTheTypeResolverWhenAskedForUnknownTypeThenTheExpectedTypeIsReturned() {
var environment = TypeResolutionParameters.newParameters()
.schema(this.graphQL.getGraphQLSchema())
.value(this)
.build();

var typeResolver = this.graphQLWiringFactory.getTypeResolver((InterfaceWiringEnvironment) null);
var graphQLObjectType = typeResolver.getType(environment);
assertThat(graphQLObjectType.getName()).isEqualTo("Diagram");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.web.services;

import org.eclipse.sirius.components.graphql.api.ITypeResolverDelegate;
import org.springframework.stereotype.Service;

import graphql.TypeResolutionEnvironment;
import graphql.schema.GraphQLObjectType;

/**
* Used during tests to return a GraphQL object type for unknown objects.
*
* @author sbegaudeau
*/
@Service
public class TestTypeResolverDelegate implements ITypeResolverDelegate {
@Override
public GraphQLObjectType getType(TypeResolutionEnvironment environment) {
return environment.getSchema().getObjectType("Diagram");
}
}

0 comments on commit 486c28b

Please sign in to comment.