This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch CAUSEWAY-3676
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/CAUSEWAY-3676 by this push:
new ec9cd01626 CAUSEWAY-3676: wip on QueryFieldFactory
ec9cd01626 is described below
commit ec9cd016261c14c3cddb6c7f2d01b160c2bc6204
Author: danhaywood <[email protected]>
AuthorDate: Fri Jan 19 15:55:14 2024 +0000
CAUSEWAY-3676: wip on QueryFieldFactory
---
.../integration/GraphQlSourceForCauseway.java | 16 ++-
.../graphql/viewer/source/GqlvObjectBehaviour.java | 22 ++-
.../viewer/source/GqlvServiceBehaviour.java | 10 ++
.../GqlvTopLevelQueryBehaviour.java | 18 +--
.../graphql/viewer/source/QueryFieldFactory.java | 151 +++++++++++----------
5 files changed, 123 insertions(+), 94 deletions(-)
diff --git
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
index 4482c39756..baf0d56f75 100644
---
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
+++
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GraphQlSourceForCauseway.java
@@ -31,6 +31,7 @@ import org.apache.causeway.applib.id.HasLogicalType;
import org.apache.causeway.core.metamodel.spec.ObjectSpecification;
+import
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryBehaviour;
import
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryStructure;
import org.apache.causeway.viewer.graphql.viewer.source.GraphQLTypeRegistry;
import org.apache.causeway.viewer.graphql.viewer.source.ObjectTypeFactory;
@@ -93,6 +94,9 @@ public class GraphQlSourceForCauseway implements
GraphQlSource {
final GraphQLCodeRegistry.Builder codeRegistryBuilder =
GraphQLCodeRegistry.newCodeRegistry();
+
+ // add to the top-level query
+ // (and also add behaviour to the child types)
val topLevelQueryStructure = new GqlvTopLevelQueryStructure();
specificationLoader.snapshotSpecifications()
@@ -102,11 +106,16 @@ public class GraphQlSourceForCauseway implements
GraphQlSource {
topLevelQueryStructure.buildQueryType();
- val topLevelQueryBehaviour = new
GqlvTopLevelQueryBehaviour(topLevelQueryStructure, serviceRegistry);
- topLevelQueryBehaviour.addFetchersTo(codeRegistryBuilder);
+ // add behaviour to the top-level query's own fields
+ val topLevelQueryBehaviour = new
GqlvTopLevelQueryBehaviour(topLevelQueryStructure, codeRegistryBuilder,
serviceRegistry);
+ topLevelQueryBehaviour.addFetchers();
+
+ // finalize the fetcher/mutator code that's been registered
val codeRegistry = codeRegistryBuilder.build();
+
+ // build the schema
return GraphQLSchema.newSchema()
.query(topLevelQueryStructure.getQueryType())
.additionalTypes(graphQLTypeRegistry.getGraphQLObjectTypes())
@@ -116,7 +125,8 @@ public class GraphQlSourceForCauseway implements
GraphQlSource {
private void addToSchema(
final ObjectSpecification objectSpec,
- final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure, final
GraphQLCodeRegistry.Builder codeRegistryBuilder) {
+ final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure,
+ final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
switch (objectSpec.getBeanSort()) {
diff --git
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
index b257628460..fca594cad5 100644
---
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
+++
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvObjectBehaviour.java
@@ -25,7 +25,7 @@ import static graphql.schema.GraphQLObjectType.newObject;
@RequiredArgsConstructor
public class GqlvObjectBehaviour {
- private final GqlvObjectStructure gqlvObjectStructure;
+ private final GqlvObjectStructure structure;
private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
private final BookmarkService bookmarkService;
private final ObjectManager objectManager;
@@ -36,32 +36,30 @@ public class GqlvObjectBehaviour {
public void createAndRegisterDataFetchersForMetaData() {
codeRegistryBuilder.dataFetcher(
-
FieldCoordinates.coordinates(gqlvObjectStructure.getGqlObjectType(),
gqlvObjectStructure.getMetaField()),
+ FieldCoordinates.coordinates(structure.getGqlObjectType(),
structure.getMetaField()),
(DataFetcher<Object>) environment -> {
return bookmarkService.bookmarkFor(environment.getSource())
.map(bookmark -> new GqlvMeta(bookmark,
bookmarkService, objectManager))
.orElse(null); //TODO: is this correct ?
});
- GraphQLObjectType metaType = gqlvObjectStructure.getMetaType();
- gqlvObjectStructure.getMetaField().getType();
codeRegistryBuilder.dataFetcher(
- FieldCoordinates.coordinates(metaType,
GqlvObjectStructure.Fields.id),
+ FieldCoordinates.coordinates(structure.getMetaType(),
GqlvObjectStructure.Fields.id),
(DataFetcher<Object>) environment -> {
GqlvMeta gqlvMeta = environment.getSource();
return gqlvMeta.id();
});
codeRegistryBuilder.dataFetcher(
-
FieldCoordinates.coordinates(gqlvObjectStructure.getMetaType(),
GqlvObjectStructure.Fields.logicalTypeName),
+ FieldCoordinates.coordinates(structure.getMetaType(),
GqlvObjectStructure.Fields.logicalTypeName),
(DataFetcher<Object>) environment -> {
GqlvMeta gqlvMeta = environment.getSource();
return gqlvMeta.logicalTypeName();
});
- if (gqlvObjectStructure.getBeanSort() == BeanSort.ENTITY) {
+ if (structure.getBeanSort() == BeanSort.ENTITY) {
codeRegistryBuilder.dataFetcher(
-
FieldCoordinates.coordinates(gqlvObjectStructure.getMetaType(),
GqlvObjectStructure.Fields.version),
+ FieldCoordinates.coordinates(structure.getMetaType(),
GqlvObjectStructure.Fields.version),
(DataFetcher<Object>) environment -> {
GqlvMeta gqlvMeta = environment.getSource();
return gqlvMeta.version();
@@ -71,19 +69,19 @@ public class GqlvObjectBehaviour {
public void createAndRegisterDataFetchersForField() {
- gqlvObjectStructure.getObjectSpec().streamProperties(MixedIn.INCLUDED)
+ structure.getObjectSpec().streamProperties(MixedIn.INCLUDED)
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
}
void createAndRegisterDataFetchersForCollection() {
- gqlvObjectStructure.getObjectSpec().streamCollections(MixedIn.INCLUDED)
+ structure.getObjectSpec().streamCollections(MixedIn.INCLUDED)
.forEach(this::createAndRegisterDataFetcherForObjectAssociation);
}
private void createAndRegisterDataFetcherForObjectAssociation(final
ObjectAssociation otom) {
- final GraphQLObjectType graphQLObjectType =
gqlvObjectStructure.getGqlObjectType();
+ final GraphQLObjectType graphQLObjectType =
structure.getGqlObjectType();
ObjectSpecification fieldObjectSpecification = otom.getElementType();
BeanSort beanSort = fieldObjectSpecification.getBeanSort();
@@ -152,7 +150,7 @@ public class GqlvObjectBehaviour {
final Set<GraphQLType> graphQLObjectTypes) {
//TODO: this is not going to work, because we need to dynamically add
fields
- String mutatorsTypeName =
gqlvObjectStructure.getLogicalTypeNameSanitized() + "__DomainObject_mutators";
+ String mutatorsTypeName = structure.getLogicalTypeNameSanitized() +
"__DomainObject_mutators";
GraphQLObjectType.Builder mutatorsTypeBuilder =
newObject().name(mutatorsTypeName);
GraphQLObjectType mutatorsType = mutatorsTypeBuilder.build();
graphQLObjectTypes.add(mutatorsType);
diff --git
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
new file mode 100644
index 0000000000..2cf79f14a7
--- /dev/null
+++
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvServiceBehaviour.java
@@ -0,0 +1,10 @@
+package org.apache.causeway.viewer.graphql.viewer.source;
+
+import lombok.RequiredArgsConstructor;
+
+@RequiredArgsConstructor
+public class GqlvServiceBehaviour {
+
+ private final GqlvServiceStructure structure;
+
+}
diff --git
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
similarity index 53%
rename from
incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
rename to
incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
index 7ac8b4b26e..d09c3a4398 100644
---
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/integration/GqlvTopLevelQueryBehaviour.java
+++
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/GqlvTopLevelQueryBehaviour.java
@@ -1,30 +1,32 @@
-package org.apache.causeway.viewer.graphql.viewer.integration;
+package org.apache.causeway.viewer.graphql.viewer.source;
import graphql.schema.DataFetcher;
import graphql.schema.GraphQLCodeRegistry;
import org.apache.causeway.applib.services.registry.ServiceRegistry;
-import
org.apache.causeway.viewer.graphql.viewer.source.GqlvTopLevelQueryStructure;
import static graphql.schema.FieldCoordinates.coordinates;
public class GqlvTopLevelQueryBehaviour {
- private final GqlvTopLevelQueryStructure topLevelQueryStructure;
+ private final GqlvTopLevelQueryStructure structure;
+ private final GraphQLCodeRegistry.Builder codeRegistryBuilder;
private final ServiceRegistry serviceRegistry;
public GqlvTopLevelQueryBehaviour(
- final GqlvTopLevelQueryStructure topLevelQueryStructure,
+ final GqlvTopLevelQueryStructure structure,
+ final GraphQLCodeRegistry.Builder codeRegistryBuilder,
final ServiceRegistry serviceRegistry) {
- this.topLevelQueryStructure = topLevelQueryStructure;
+ this.structure = structure;
+ this.codeRegistryBuilder = codeRegistryBuilder;
this.serviceRegistry = serviceRegistry;
}
- public void addFetchersTo(GraphQLCodeRegistry.Builder codeRegistryBuilder)
{
+ public void addFetchers() {
codeRegistryBuilder
.dataFetcher(
- coordinates(topLevelQueryStructure.getQueryType(),
topLevelQueryStructure.getNumServicesField()),
+ coordinates(structure.getQueryType(),
structure.getNumServicesField()),
(DataFetcher<Object>) environment ->
this.serviceRegistry.streamRegisteredBeans().count());
-
}
+
}
diff --git
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
index 45b1237325..f6eba0b533 100644
---
a/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
+++
b/incubator/viewers/graphql/viewer/src/main/java/org/apache/causeway/viewer/graphql/viewer/source/QueryFieldFactory.java
@@ -61,102 +61,111 @@ public class QueryFieldFactory {
public void queryFieldFromObjectSpecification(
final ObjectSpecification objectSpec,
- final GqlvTopLevelQueryStructure gqlvTopLevelQueryStructure,
+ final GqlvTopLevelQueryStructure topLevelQueryStructure,
final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
- final GraphQLObjectType.Builder queryBuilder =
gqlvTopLevelQueryStructure.getQueryBuilder();
-
- String logicalTypeNameSanitized = _LTN.sanitized(objectSpec);
-
serviceRegistry.lookupBeanById(objectSpec.getLogicalTypeName())
.ifPresent(service -> {
+ addService(objectSpec, service, topLevelQueryStructure,
codeRegistryBuilder);
+ });
+ }
- List<ObjectAction> objectActionList =
objectSpec.streamRuntimeActions(MixedIn.INCLUDED)
- .map(ObjectAction.class::cast)
- .filter((final ObjectAction x) ->
x.containsFacet(ActionSemanticsFacet.class))
-// .filter(x ->
x.getFacet(ActionSemanticsFacet.class).value() == SemanticsOf.SAFE)
- .collect(Collectors.toList());
+ private void addService(
+ final ObjectSpecification objectSpec,
+ final Object service,
+ final GqlvTopLevelQueryStructure topLevelQueryStructure,
+ final GraphQLCodeRegistry.Builder codeRegistryBuilder) {
- // for now filters when no safe actions
- if (!objectActionList.isEmpty()) {
+ final GraphQLObjectType.Builder queryBuilder =
topLevelQueryStructure.getQueryBuilder();
- val serviceAsGraphQlType =
newObject().name(logicalTypeNameSanitized);
+ List<ObjectAction> objectActionList =
objectSpec.streamRuntimeActions(MixedIn.INCLUDED)
+ .map(ObjectAction.class::cast)
+ .filter((final ObjectAction x) ->
x.containsFacet(ActionSemanticsFacet.class))
+// .filter(x ->
x.getFacet(ActionSemanticsFacet.class).value() == SemanticsOf.SAFE)
+ .collect(Collectors.toList());
- objectActionList
- .forEach(objectAction -> {
- String fieldName = objectAction.getId();
+ // for now filters when no safe actions
+ if (!objectActionList.isEmpty()) {
- GraphQLFieldDefinition.Builder builder =
newFieldDefinition()
- .name(fieldName)
- .type((GraphQLOutputType)
TypeMapper.typeForObjectAction(objectAction));
- if (objectAction.getParameters().isNotEmpty()) {
- builder.arguments(objectAction.getParameters().stream()
- .map(objectActionParameter ->
GraphQLArgument.newArgument()
- .name(objectActionParameter.getId())
-
.type(TypeMapper.inputTypeFor(objectActionParameter))
- .build())
- .collect(Collectors.toList()));
- }
- serviceAsGraphQlType
- .field(builder
- .build());
+ val serviceAsGraphQlType =
newObject().name(_LTN.sanitized(objectSpec));
- });
+ objectActionList
+ .forEach(objectAction -> {
+ addAction(objectAction, serviceAsGraphQlType);
+ });
- GraphQLObjectType graphQLObjectType =
serviceAsGraphQlType.build();
+ GraphQLObjectType graphQLObjectType = serviceAsGraphQlType.build();
- objectActionList
- .forEach(objectAction -> {
+ objectActionList
+ .forEach(objectAction -> {
- String fieldName = objectAction.getId();
- codeRegistryBuilder
- .dataFetcher(
- FieldCoordinates.coordinates(graphQLObjectType,
fieldName),
- new DataFetcher<Object>() {
+ String fieldName = objectAction.getId();
+ codeRegistryBuilder
+ .dataFetcher(
+ FieldCoordinates.coordinates(graphQLObjectType, fieldName),
+ new DataFetcher<Object>() {
- @Override
- public Object get(final DataFetchingEnvironment
dataFetchingEnvironment) throws Exception {
+ @Override
+ public Object get(final DataFetchingEnvironment
dataFetchingEnvironment) throws Exception {
- Object domainObjectInstance =
dataFetchingEnvironment.getSource();
+ Object domainObjectInstance =
dataFetchingEnvironment.getSource();
- Class<?> domainObjectInstanceClass =
domainObjectInstance.getClass();
- ObjectSpecification specification =
specificationLoader
-
.loadSpecification(domainObjectInstanceClass);
+ Class<?> domainObjectInstanceClass =
domainObjectInstance.getClass();
+ ObjectSpecification specification =
specificationLoader
+
.loadSpecification(domainObjectInstanceClass);
- ManagedObject owner =
ManagedObject.adaptSingular(specification, domainObjectInstance);
+ ManagedObject owner =
ManagedObject.adaptSingular(specification, domainObjectInstance);
- ActionInteractionHead actionInteractionHead =
objectAction.interactionHead(owner);
+ ActionInteractionHead actionInteractionHead =
objectAction.interactionHead(owner);
- Map<String, Object> arguments =
dataFetchingEnvironment.getArguments();
- Can<ObjectActionParameter> parameters =
objectAction.getParameters();
- Can<ManagedObject> canOfParams = parameters
- .map(oap -> {
- Object argumentValue =
arguments.get(oap.getId());
- return
ManagedObject.adaptParameter(oap, argumentValue);
- });
+ Map<String, Object> arguments =
dataFetchingEnvironment.getArguments();
+ Can<ObjectActionParameter> parameters =
objectAction.getParameters();
+ Can<ManagedObject> canOfParams = parameters
+ .map(oap -> {
+ Object argumentValue =
arguments.get(oap.getId());
+ return
ManagedObject.adaptParameter(oap, argumentValue);
+ });
- ManagedObject managedObject = objectAction
- .execute(actionInteractionHead,
canOfParams, InteractionInitiatedBy.USER);
+ ManagedObject managedObject = objectAction
+ .execute(actionInteractionHead,
canOfParams, InteractionInitiatedBy.USER);
- return managedObject.getPojo();
- }
+ return managedObject.getPojo();
+ }
- });
+ });
- });
+ });
- queryBuilder.field(newFieldDefinition()
- .name(logicalTypeNameSanitized)
+ queryBuilder.field(newFieldDefinition()
+ .name(_LTN.sanitized(objectSpec))
+ .type(serviceAsGraphQlType)
+ .build());
+ codeRegistryBuilder
+ .dataFetcher(
+ FieldCoordinates.coordinates("Query", newFieldDefinition()
+ .name(_LTN.sanitized(objectSpec))
.type(serviceAsGraphQlType)
+ .build().getName()),
+ (DataFetcher<Object>) environment -> service);
+ }
+ }
+
+ private static void addAction(ObjectAction objectAction,
GraphQLObjectType.Builder serviceAsGraphQlType) {
+ String fieldName = objectAction.getId();
+
+ GraphQLFieldDefinition.Builder builder = newFieldDefinition()
+ .name(fieldName)
+ .type((GraphQLOutputType)
TypeMapper.typeForObjectAction(objectAction));
+ if (objectAction.getParameters().isNotEmpty()) {
+ builder.arguments(objectAction.getParameters().stream()
+ .map(objectActionParameter -> GraphQLArgument.newArgument()
+ .name(objectActionParameter.getId())
+
.type(TypeMapper.inputTypeFor(objectActionParameter))
+ .build())
+ .collect(Collectors.toList()));
+ }
+ serviceAsGraphQlType
+ .field(builder
.build());
- codeRegistryBuilder
- .dataFetcher(
- FieldCoordinates.coordinates("Query",
newFieldDefinition()
- .name(logicalTypeNameSanitized)
- .type(serviceAsGraphQlType)
- .build().getName()),
- (DataFetcher<Object>) environment -> service);
- }
- });
}
}