You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/05/17 09:16:51 UTC

[isis] branch master updated: ISIS-2681: don't use MetaModelService internally for LogicalType resolution

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 20065eb  ISIS-2681: don't use MetaModelService internally for LogicalType resolution
20065eb is described below

commit 20065eb0489caaa80189bf0c715bf34d7f98ba86
Author: ahuber@apache.org <ah...@luna>
AuthorDate: Mon May 17 11:16:35 2021 +0200

    ISIS-2681: don't use MetaModelService internally for LogicalType
    resolution
---
 .../services/metamodel/MetaModelService.java       |  4 +-
 .../DomainObjectAnnotationFacetFactory.java        | 29 ++-----------
 .../objectspecid/ObjectTypeFacetAbstract.java      |  3 +-
 .../specloader/LogicalTypeResolverDefault.java     | 48 ++++++++--------------
 .../runtimeservices/jaxb/JaxbServiceDefault.java   | 14 +++----
 .../TableColumnVisibilityServiceForSecman.java     | 10 ++---
 6 files changed, 37 insertions(+), 71 deletions(-)

diff --git a/api/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService.java b/api/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService.java
index 1e0fae5..ca8b540 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/services/metamodel/MetaModelService.java
@@ -43,7 +43,9 @@ public interface MetaModelService {
     /**
      * Provides a lookup by objectType of a domain class' object type, as defined by
      * {@link DomainObject#objectType()} (or any other mechanism that corresponds to Isis'
-     * <code>ObjectTypeFacet</code>).
+     * <code>ObjectTypeFacet</code>). Will return an empty result if there is no
+     * such non-abstract class registered.
+     * (interfaces and abstract types are never added to the lookup table).
      */
     Optional<LogicalType> lookupLogicalTypeByName(final String objectType);
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
index 054bf58..a864ee9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
@@ -496,17 +496,15 @@ implements
                     @Override
                     public void validate(ObjectSpecification objSpec) {
 
-                        // Allow members of a type hierarchy including interfaces to share the same
-                        // @DomainObject(objectType=...)
+                        // @DomainObject(objectType=...) must be unique among non-abstract types
                         // Eg. having an ApplicationUser interface and a concrete ApplicationUser (JDO)
                         // that have the same @DomainObject(objectType=...) should be allowed.
-                        // The only constraint that applies, is that there cannot be multiple bookmark-able
+                        // A hard constraint that applies, is that there cannot be multiple bookmark-able
                         // types that share the same @DomainObject(objectType=...).
                         // This must be guaranteed by MM validation.
                         // - see also LogicalTypeResolver.register(...)
 
-                        if(objSpec.isManagedBean()
-                                || objSpec.isAbstract()) {
+                        if(objSpec.isAbstract()) {
                             return;
                         }
                         collidingSpecsByLogicalTypeName.putElement(objSpec.getLogicalTypeName(), objSpec);
@@ -535,27 +533,8 @@ implements
                         collidingSpecsByLogicalTypeName.clear();
                     }
 
-                    // detect whether specs (of concrete type) belong to more than one type hierarchy
                     private boolean isObjectTypeCollision(final List<ObjectSpecification> specs) {
-                        if(specs.size()<=1) {
-                            return false;
-                        }
-                        // algorithm: check all non-first against the first
-
-                        val first = specs.get(0);
-
-                        val shareSameTypeHierarchy = specs.stream()
-                                .skip(1)
-                                .allMatch(next->shareSameTypeHierarchy(first, next));
-
-                        return !shareSameTypeHierarchy;
-                    }
-
-                    private boolean shareSameTypeHierarchy(
-                            final @NonNull ObjectSpecification  a, final @NonNull ObjectSpecification b) {
-                        return a.equals(b)
-                                || a.getCorrespondingClass().isAssignableFrom(b.getCorrespondingClass())
-                                || b.getCorrespondingClass().isAssignableFrom(a.getCorrespondingClass());
+                        return specs.size()>1;
                     }
 
                     private String asCsv(final List<ObjectSpecification> specList) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectTypeFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectTypeFacetAbstract.java
index b3f97fe..9f0dd27 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectTypeFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectTypeFacetAbstract.java
@@ -57,6 +57,7 @@ implements ObjectTypeFacet {
     @Override
     public void appendAttributesTo(final Map<String, Object> attributeMap) {
         super.appendAttributesTo(attributeMap);
-        attributeMap.put("logicalType", logicalType.getLogicalTypeName());
+        attributeMap.put("logicalTypeName", logicalType.getLogicalTypeName());
+        attributeMap.put("logicalTypeCorrespondingClass", logicalType.getCorrespondingClass().getName());
     }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/LogicalTypeResolverDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/LogicalTypeResolverDefault.java
index 7e70f0e..2bb67e1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/LogicalTypeResolverDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/LogicalTypeResolverDefault.java
@@ -53,7 +53,23 @@ class LogicalTypeResolverDefault implements LogicalTypeResolver {
         if(!spec.isAbstract()
                 && hasUsableObjectTypeFacet(spec)) {
 
-            logicalTypeByName.merge(spec.getLogicalTypeName(), spec.getLogicalType(), this::mostSpecializedOfConcrete);
+            val key = spec.getLogicalTypeName();
+
+            val previousMapping = logicalTypeByName.put(key, spec.getLogicalType());
+
+            if(previousMapping!=null) {
+
+                val msg = String.format("Overriding existing mapping\n"
+                        + "%s -> %s,\n"
+                        + "with\n "
+                        + "%s -> %s\n "
+                        + "This will result in the meta-model validation to fail.",
+                        key, previousMapping.getCorrespondingClass(),
+                        key, spec.getCorrespondingClass());
+
+                log.warn(msg);
+
+            }
         }
     }
 
@@ -65,34 +81,4 @@ class LogicalTypeResolverDefault implements LogicalTypeResolver {
         return spec.containsNonFallbackFacet(ObjectTypeFacet.class);
     }
 
-    private LogicalType mostSpecializedOfConcrete(final @NonNull LogicalType a, final @NonNull LogicalType b) {
-        if(a.equals(b)) {
-            return a;
-        }
-        if(a.getCorrespondingClass().isAssignableFrom(b.getCorrespondingClass())) {
-            return b;
-        }
-        if(b.getCorrespondingClass().isAssignableFrom(a.getCorrespondingClass())) {
-            return a;
-        }
-
-        val key = a.getLogicalTypeName();
-
-        val msg = String.format("Failed to register mapping\n"
-                + "%s -> %s,\n"
-                + "because there was already a mapping\n "
-                + "%s -> %s.\n"
-                + "Meta-model validation should detect this and fail, if not - that's a bug.",
-                key,
-                b.getCorrespondingClass(),
-                key,
-                a.getCorrespondingClass());
-
-        log.warn(msg);
-
-        // do not fail fast, but clear the entry and let MM validation fail later on
-        return null;
-    }
-
-
 }
diff --git a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/jaxb/JaxbServiceDefault.java b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/jaxb/JaxbServiceDefault.java
index 5837e6d..5775bff 100644
--- a/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/jaxb/JaxbServiceDefault.java
+++ b/core/runtimeservices/src/main/java/org/apache/isis/core/runtimeservices/jaxb/JaxbServiceDefault.java
@@ -22,7 +22,6 @@ import java.util.Map;
 
 import javax.inject.Inject;
 import javax.inject.Named;
-import javax.inject.Provider;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.JAXBException;
 import javax.xml.bind.Marshaller;
@@ -36,13 +35,13 @@ import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
 import org.apache.isis.applib.domain.DomainObjectList;
-import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.jaxb.PersistentEntitiesAdapter;
 import org.apache.isis.applib.jaxb.PersistentEntityAdapter;
 import org.apache.isis.applib.services.inject.ServiceInjector;
 import org.apache.isis.applib.services.jaxb.JaxbService.Simple;
-import org.apache.isis.applib.services.metamodel.MetaModelService;
 import org.apache.isis.commons.internal.resources._Xml;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
 import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
@@ -58,8 +57,7 @@ import lombok.val;
 public class JaxbServiceDefault extends Simple {
 
     private final ServiceInjector serviceInjector;
-    /*circular dependency, so use provider*/
-    private final Provider<MetaModelService> metaModelServiceProvider;
+    private final SpecificationLoader specificationLoader;
 
     @Override @SneakyThrows
     protected JAXBContext jaxbContextForObject(final @NonNull Object domainObject) {
@@ -67,9 +65,9 @@ public class JaxbServiceDefault extends Simple {
             val domainClass = domainObject.getClass();
             val domainObjectList = (DomainObjectList) domainObject;
             try {
-                val elementType = metaModelServiceProvider.get()
-                        .lookupLogicalTypeByName(domainObjectList.getElementObjectType())
-                        .map(LogicalType::getCorrespondingClass)
+                val elementType = specificationLoader
+                        .specForLogicalTypeName(domainObjectList.getElementObjectType())
+                        .map(ObjectSpecification::getCorrespondingClass)
                         .orElse(null);
                 if (elementType!=null
                         && elementType.getAnnotation(XmlJavaTypeAdapter.class) == null) {
diff --git a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/spiimpl/TableColumnVisibilityServiceForSecman.java b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/spiimpl/TableColumnVisibilityServiceForSecman.java
index 3b0597e..9443584 100644
--- a/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/spiimpl/TableColumnVisibilityServiceForSecman.java
+++ b/extensions/security/secman/model/src/main/java/org/apache/isis/extensions/secman/model/spiimpl/TableColumnVisibilityServiceForSecman.java
@@ -8,10 +8,10 @@ import org.springframework.core.annotation.Order;
 import org.springframework.stereotype.Service;
 
 import org.apache.isis.applib.annotation.OrderPrecedence;
-import org.apache.isis.applib.id.LogicalType;
 import org.apache.isis.applib.services.appfeat.ApplicationFeatureId;
-import org.apache.isis.applib.services.metamodel.MetaModelService;
 import org.apache.isis.applib.services.tablecol.TableColumnVisibilityService;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.extensions.secman.api.permission.dom.ApplicationPermissionMode;
 import org.apache.isis.extensions.secman.api.user.menu.MeService;
 
@@ -26,15 +26,15 @@ import lombok.val;
 public class TableColumnVisibilityServiceForSecman implements TableColumnVisibilityService {
 
     final MeService meService;
-    final MetaModelService metaModelService;
+    final SpecificationLoader specificationLoader;
 
     @Override
     public boolean hides(Class<?> elementType, String memberId) {
         val me = meService.me();
         val permissionSet = me.getPermissionSet();
 
-        final boolean granted = metaModelService.lookupLogicalTypeByClass(elementType)
-            .map(LogicalType::getLogicalTypeName)
+        final boolean granted = specificationLoader.specForType(elementType)
+            .map(ObjectSpecification::getLogicalTypeName)
             .map(objectType->{
                 val featureId = ApplicationFeatureId.newMember(objectType, memberId);
                 return permissionSet.evaluate(featureId, ApplicationPermissionMode.VIEWING).isGranted();