You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2022/01/23 14:34:26 UTC
[isis] branch ISIS-2947 updated: ISIS-2947: surfaces a field on top-level 'Query' for all `@DomainService`'s.
This is an automated email from the ASF dual-hosted git repository.
danhaywood pushed a commit to branch ISIS-2947
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/ISIS-2947 by this push:
new 4648468 ISIS-2947: surfaces a field on top-level 'Query' for all `@DomainService`'s.
4648468 is described below
commit 4648468c5464396b5757561ed8db7865b05ab31c
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Sun Jan 23 14:34:04 2022 +0000
ISIS-2947: surfaces a field on top-level 'Query' for all `@DomainService`'s.
---
.../load/ObjectLoader_builtinHandlers.java | 6 +-
.../specloader/SpecificationCacheDefault.java | 6 +-
.../metamodel/specloader/SpecificationLoader.java | 3 +-
.../specloader/SpecificationLoaderDefault.java | 3 +-
.../MetaModelVisitingValidatorAbstract.java | 10 ++-
.../viewer/source/GraphQlSourceForIsis.java | 79 ++++++++++++++++++----
6 files changed, 86 insertions(+), 21 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
index c6db42f..e13b578 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/objectmanager/load/ObjectLoader_builtinHandlers.java
@@ -97,15 +97,15 @@ final class ObjectLoader_builtinHandlers {
public ManagedObject handle(final ObjectLoader.Request objectLoadRequest) {
val spec = objectLoadRequest.getObjectSpecification();
- val beanName = spec.getLogicalTypeName();
+ val logicalTypeName = spec.getLogicalTypeName();
val servicePojo = metaModelContext.getServiceRegistry()
- .lookupRegisteredBeanById(beanName)
+ .lookupRegisteredBeanById(logicalTypeName)
.map(_ManagedBeanAdapter::getInstance)
.flatMap(Can::getFirst)
.orElseThrow(()->_Exceptions.noSuchElement(
"loader: %s loading beanName %s",
- this.getClass().getName(), beanName));
+ this.getClass().getName(), logicalTypeName));
return ManagedObject.of(spec, servicePojo);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
index 0df304f..5b6033e 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationCacheDefault.java
@@ -18,6 +18,7 @@
*/
package org.apache.isis.core.metamodel.specloader;
+import java.util.Comparator;
import java.util.Map;
import java.util.Optional;
import java.util.function.Consumer;
@@ -25,6 +26,7 @@ import java.util.function.Function;
import org.springframework.lang.Nullable;
+import org.apache.isis.applib.id.HasLogicalType;
import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.commons.internal.collections.snapshot._VersionedList;
@@ -100,7 +102,9 @@ class SpecificationCacheDefault<T extends ObjectSpecification> implements Specif
if(shouldRunConcurrent) {
vList.forEachParallel(onSpec);
} else {
- vList.forEach(onSpec);
+ vList
+ .stream().sorted(Comparator.comparing(HasLogicalType::getLogicalTypeName))
+ .forEach(onSpec);
}
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
index fec274a..fa657a2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java
@@ -107,7 +107,7 @@ public interface SpecificationLoader {
*
* @param action
*/
- void forEach(Consumer<ObjectSpecification> onSpec);
+ void forEach(Consumer<ObjectSpecification> onSpec, final boolean shouldRunConcurrent);
void reloadSpecification(Class<?> domainType);
@@ -261,4 +261,5 @@ public interface SpecificationLoader {
featureIdentifier));
}
+ boolean isMetamodelFullyIntrospected();
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
index 9863227..d41a73b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderDefault.java
@@ -445,8 +445,7 @@ public class SpecificationLoaderDefault implements SpecificationLoader {
}
@Override
- public void forEach(final Consumer<ObjectSpecification> onSpec) {
- val shouldRunConcurrent = isisConfiguration.getCore().getMetaModel().getValidator().isParallelize();
+ public void forEach(final Consumer<ObjectSpecification> onSpec, final boolean shouldRunConcurrent) {
cache.forEach(onSpec, shouldRunConcurrent);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java
index cfe8c39..266b678 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelVisitingValidatorAbstract.java
@@ -18,8 +18,11 @@
*/
package org.apache.isis.core.metamodel.specloader.validator;
+import org.apache.isis.core.config.IsisConfiguration;
import org.apache.isis.core.metamodel.context.MetaModelContext;
+import lombok.val;
+
public abstract class MetaModelVisitingValidatorAbstract
extends MetaModelValidatorAbstract
implements MetaModelVisitingValidator {
@@ -35,8 +38,11 @@ implements MetaModelVisitingValidator {
return;
}
- super.getMetaModelContext().getSpecificationLoader()
- .forEach(this::validate);
+ val shouldRunConcurrent =
+ getMetaModelContext().getConfiguration().getCore().getMetaModel().getValidator().isParallelize();
+
+ getMetaModelContext().getSpecificationLoader()
+ .forEach(this::validate, shouldRunConcurrent);
summarize();
diff --git a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java
index 82cd012..d0a0f49 100644
--- a/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java
+++ b/incubator/viewers/graphql/viewer/src/main/java/org/apache/isis/viewer/graphql/viewer/source/GraphQlSourceForIsis.java
@@ -1,18 +1,20 @@
package org.apache.isis.viewer.graphql.viewer.source;
-import java.util.concurrent.CountDownLatch;
-
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.stereotype.Service;
+import org.apache.isis.applib.annotation.SemanticsOf;
import org.apache.isis.applib.services.registry.ServiceRegistry;
import org.apache.isis.core.config.IsisConfiguration;
import org.apache.isis.core.config.environment.IsisSystemEnvironment;
import org.apache.isis.core.config.metamodel.specloader.IntrospectionMode;
-import org.apache.isis.core.metamodel.specloader.SpecificationLoaderDefault;
+import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFacet;
+import org.apache.isis.core.metamodel.spec.feature.MixedIn;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
import lombok.RequiredArgsConstructor;
import lombok.val;
@@ -21,25 +23,25 @@ import graphql.GraphQL;
import graphql.Scalars;
import graphql.execution.instrumentation.tracing.TracingInstrumentation;
import graphql.schema.DataFetcher;
+import graphql.schema.FieldCoordinates;
import graphql.schema.GraphQLCodeRegistry;
-import graphql.schema.GraphQLFieldDefinition;
import graphql.schema.GraphQLObjectType;
import graphql.schema.GraphQLSchema;
import static graphql.schema.FieldCoordinates.coordinates;
+import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition;
+import static graphql.schema.GraphQLObjectType.newObject;
@Service()
@RequiredArgsConstructor(onConstructor_ = {@Inject})
public class GraphQlSourceForIsis implements GraphQlSource {
private final ServiceRegistry serviceRegistry;
- private final SpecificationLoaderDefault specificationLoader;
+ private final SpecificationLoader specificationLoader;
private final IsisConfiguration isisConfiguration;
private final IsisSystemEnvironment isisSystemEnvironment;
private final ExecutionStrategyResolvingWithinInteraction executionStrategy;
- private final CountDownLatch countDownLatch = new CountDownLatch(1);
-
@PostConstruct
public void init() {
boolean fullyIntrospect = IntrospectionMode.isFullIntrospect(isisConfiguration, isisSystemEnvironment);
@@ -51,7 +53,7 @@ public class GraphQlSourceForIsis implements GraphQlSource {
@Override
public GraphQL graphQl() {
return GraphQL.newGraphQL(schema())
- .instrumentation(new TracingInstrumentation())
+ // .instrumentation(new TracingInstrumentation())
.queryExecutionStrategy(executionStrategy)
.build();
}
@@ -95,20 +97,73 @@ public class GraphQlSourceForIsis implements GraphQlSource {
// (DataFetcher<Object>) environment -> leaseRepository.numLeases)
// .build();
+ val queryBuilder = newObject().name("Query");
+ val codeRegistryBuilder = GraphQLCodeRegistry.newCodeRegistry();
+
+ specificationLoader.forEach(objectSpecification -> {
+
+ val logicalTypeName = objectSpecification.getLogicalTypeName();
+ val correspondingClass = objectSpecification.getCorrespondingClass();
+ switch (objectSpecification.getBeanSort()) {
+ case VIEW_MODEL: // @DomainObject(nature=VIEW_MODEL)
+ // TODO
+ break;
+ case ENTITY: // @DomainObject(nature=ENTITY)
+ // TODO
+ break;
+ case MANAGED_BEAN_CONTRIBUTING: //@DomainService
+
+ serviceRegistry.lookupBeanById(logicalTypeName).ifPresent(service -> {
+
+ String logicalTypeNameSanitized = logicalTypeName.replace('.', '_');
+
+ // as a first pass, expose a single "property" of the service, which is just a count of how
+ // many safe actions there are
+ val serviceAsGraphQlType = newObject().name(logicalTypeNameSanitized)
+ .field(newFieldDefinition()
+ .name("numSafeActions")
+ .type(Scalars.GraphQLInt)
+ .build()).build();
+ codeRegistryBuilder.dataFetcher(
+ FieldCoordinates.coordinates(serviceAsGraphQlType, "numSafeActions"),
+ (DataFetcher<Object>) environment -> objectSpecification.streamRuntimeActions(MixedIn.INCLUDED)
+ .map(ObjectAction.class::cast)
+ .filter((ObjectAction x) -> x.containsFacet(ActionSemanticsFacet.class))
+ .map(x -> x.getFacet(ActionSemanticsFacet.class))
+ .map(x -> x.value() == SemanticsOf.SAFE)
+ .count());
+
+ // make the service accessible from the top-level Query
+ queryBuilder.field(newFieldDefinition().name(logicalTypeNameSanitized).type(serviceAsGraphQlType).build());
+ codeRegistryBuilder.dataFetcher(FieldCoordinates.coordinates("Query", newFieldDefinition().name(logicalTypeNameSanitized).type(serviceAsGraphQlType).build().getName()), (DataFetcher<Object>) environment -> service);
+ });
+ break;
+
+ case MANAGED_BEAN_NOT_CONTRIBUTING: // a @Service or @Component ... ignore
+ case MIXIN:
+ case VALUE:
+ case COLLECTION:
+ case ABSTRACT:
+ case VETOED:
+ case UNKNOWN:
+ break;
+ }
+ }, false);
+
// type Query {
// numServices: Int
// }
- val query_numServices = GraphQLFieldDefinition.newFieldDefinition()
+ val query_numServices = newFieldDefinition()
.name("numServices")
.type(Scalars.GraphQLInt)
.build();
- GraphQLObjectType query = GraphQLObjectType.newObject()
- .name("Query")
+
+ GraphQLObjectType query = queryBuilder
.field(query_numServices)
.build();
- val codeRegistry = GraphQLCodeRegistry.newCodeRegistry()
+ val codeRegistry = codeRegistryBuilder
.dataFetcher(coordinates(query.getName(), query_numServices.getName()),
(DataFetcher<Object>) environment -> this.serviceRegistry.streamRegisteredBeans().count())
.build();