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 2018/01/24 15:15:44 UTC

[isis] branch maint-1.16.1 updated (e21fef1 -> b6bb1c7)

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

danhaywood pushed a change to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git.


    from e21fef1  Merge branch 'ISIS-1743' into maint-1.16.1
     new a56f19d  ISIS-1848: ensures that FreeStandingList does not incorrectly return java.lang.Object's specId, and adds new metamodel validator to detect this situation in future.
     new 128e144  ISIS-1837: adds metamodel validator to check "module extent".
     new b6bb1c7  Merge branch 'ISIS-1848' into maint-1.16.1

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../guides/rgcfg/_rgcfg_configuring-core.adoc      |  15 ++
 .../objectspecid/ObjectSpecIdFacetAbstract.java    |   9 +-
 ...java => ObjectSpecIdFacetOnStandaloneList.java} |  10 +-
 .../core/metamodel/spec/ObjectSpecification.java   |  61 +++++---
 .../metamodel/specloader/SpecificationLoader.java  |  13 ++
 .../specimpl/ObjectSpecificationAbstract.java      |  18 +--
 .../ObjectSpecificationOnStandaloneList.java       |   4 +
 .../MetaModelValidatorToCheckModuleExtent.java     | 153 +++++++++++++++++++++
 ...taModelValidatorToCheckObjectSpecIdsUnique.java |  95 +++++++++++++
 .../isis/progmodels/dflt/JavaReflectorHelper.java  |   2 +-
 .../SpecificationLoaderTestAbstract.java           |   2 +-
 .../PersistenceSessionFactoryMetamodelRefiner.java |   4 +
 12 files changed, 346 insertions(+), 40 deletions(-)
 copy core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/{ObjectSpecIdFacetDerivedFromClassName.java => ObjectSpecIdFacetOnStandaloneList.java} (73%)
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckModuleExtent.java
 create mode 100644 core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckObjectSpecIdsUnique.java

-- 
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.

[isis] 01/03: ISIS-1848: ensures that FreeStandingList does not incorrectly return java.lang.Object's specId, and adds new metamodel validator to detect this situation in future.

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git

commit a56f19dad5a628d059fd561c076aa3f5b6edca41
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Jan 24 13:51:05 2018 +0000

    ISIS-1848: ensures that FreeStandingList does not incorrectly return java.lang.Object's specId, and adds new metamodel validator to detect this situation in future.
---
 .../guides/rgcfg/_rgcfg_configuring-core.adoc      |  7 ++
 .../objectspecid/ObjectSpecIdFacetAbstract.java    |  9 +-
 .../ObjectSpecIdFacetOnStandaloneList.java}        | 30 ++-----
 .../core/metamodel/spec/ObjectSpecification.java   | 61 +++++++++-----
 .../metamodel/specloader/SpecificationLoader.java  |  9 +-
 .../specimpl/ObjectSpecificationAbstract.java      | 18 ++--
 .../ObjectSpecificationOnStandaloneList.java       |  4 +
 ...taModelValidatorToCheckObjectSpecIdsUnique.java | 95 ++++++++++++++++++++++
 .../isis/progmodels/dflt/JavaReflectorHelper.java  |  2 +-
 .../SpecificationLoaderTestAbstract.java           |  2 +-
 .../PersistenceSessionFactoryMetamodelRefiner.java |  2 +
 11 files changed, 179 insertions(+), 60 deletions(-)

diff --git a/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc b/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
index 36606b9..d7b5ba3 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
@@ -328,6 +328,13 @@ If not, then a metamodel validation error will be triggered, meaning the app won
 See also `isis.reflector.facets.ignoreDeprecated`.
 
 |`isis.reflector.validator.` +
+`ensureUniqueObjectTypes`
+|`true`,`false` +
+(`true`)
+|Whether to ensure that all classes in the metamodel map to a different object type (typically either as explicitly specified using `@DomainObject(objectType=...)`, or their class name as a fallback).  +
+
+
+|`isis.reflector.validator.` +
 `explicitObjectType`
 |`true`,`false` +
 (`false`)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java
index 89fda4a..03ac05d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java
@@ -41,8 +41,15 @@ public abstract class ObjectSpecIdFacetAbstract extends
             final String value,
             final FacetHolder holder,
             final Derivation derivation) {
+        this(ObjectSpecId.of(value), holder, derivation);
+    }
+
+    protected ObjectSpecIdFacetAbstract(
+            final ObjectSpecId value,
+            final FacetHolder holder,
+            final Derivation derivation) {
         super(ObjectSpecIdFacetAbstract.type(), holder, derivation);
-        this.value = ObjectSpecId.of(value);
+        this.value = value;
     }
 
     public ObjectSpecId value() {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetOnStandaloneList.java
similarity index 54%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java
copy to core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetOnStandaloneList.java
index 89fda4a..680eec9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/ObjectSpecIdFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetOnStandaloneList.java
@@ -17,35 +17,15 @@
  *  under the License.
  */
 
-package org.apache.isis.core.metamodel.facets.object.objectspecid;
+package org.apache.isis.core.metamodel.facets.object.objectspecid.classname;
 
-import org.apache.isis.core.metamodel.facetapi.Facet;
-import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacetAbstract;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 
-public abstract class ObjectSpecIdFacetAbstract extends
-        FacetAbstract implements ObjectSpecIdFacet {
+public class ObjectSpecIdFacetOnStandaloneList extends ObjectSpecIdFacetAbstract {
 
-    public static Class<? extends Facet> type() {
-        return ObjectSpecIdFacet.class;
-    }
-
-    private final ObjectSpecId value;
-
-    public ObjectSpecIdFacetAbstract(final String value, final FacetHolder holder) {
-        this(value, holder, Derivation.NOT_DERIVED);
-    }
-    
-    public ObjectSpecIdFacetAbstract(
-            final String value,
-            final FacetHolder holder,
-            final Derivation derivation) {
-        super(ObjectSpecIdFacetAbstract.type(), holder, derivation);
-        this.value = ObjectSpecId.of(value);
-    }
-
-    public ObjectSpecId value() {
-        return value;
+    public ObjectSpecIdFacetOnStandaloneList(final ObjectSpecId value, final FacetHolder holder) {
+        super(value, holder, Derivation.NOT_DERIVED);
     }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
index 29e6bb7..f1674ca 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
@@ -23,8 +23,11 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
+import javax.annotation.Nullable;
+
 import com.google.common.base.Function;
 
+import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.ObjectType;
 import org.apache.isis.core.commons.authentication.AuthenticationSession;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
@@ -67,24 +70,42 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
 
     public final static List<ObjectSpecification> EMPTY_LIST = Collections.emptyList();
 
-    public final static Function<ObjectSpecification, String> FUNCTION_FULLY_QUALIFIED_CLASS_NAME = new Function<ObjectSpecification, String>() {
-        @Override
-        public String apply(final ObjectSpecification from) {
-            return from.getFullIdentifier();
-        }
-    };
-    public final static Comparator<ObjectSpecification> COMPARATOR_FULLY_QUALIFIED_CLASS_NAME = new Comparator<ObjectSpecification>() {
-        @Override
-        public int compare(final ObjectSpecification o1, final ObjectSpecification o2) {
-            return o1.getFullIdentifier().compareTo(o2.getFullIdentifier());
-        }
-    };
-    public final static Comparator<ObjectSpecification> COMPARATOR_SHORT_IDENTIFIER_IGNORE_CASE = new Comparator<ObjectSpecification>() {
-        @Override
-        public int compare(final ObjectSpecification s1, final ObjectSpecification s2) {
-            return s1.getShortIdentifier().compareToIgnoreCase(s2.getShortIdentifier());
-        }
-    };
+    @Deprecated
+    public final static Function<ObjectSpecification, String> FUNCTION_FULLY_QUALIFIED_CLASS_NAME = Functions.FULL_IDENTIFIER;
+
+    @Deprecated
+    public final static Comparator<ObjectSpecification> COMPARATOR_FULLY_QUALIFIED_CLASS_NAME = Comparators.FULLY_QUALIFIED_CLASS_NAME;
+
+    @Deprecated
+    public final static Comparator<ObjectSpecification> COMPARATOR_SHORT_IDENTIFIER_IGNORE_CASE = Comparators.SHORT_IDENTIFIER_IGNORE_CASE;
+
+    class Comparators{
+        private Comparators(){}
+        public final static Comparator<ObjectSpecification> FULLY_QUALIFIED_CLASS_NAME = new Comparator<ObjectSpecification>() {
+            @Override
+            public int compare(final ObjectSpecification o1, final ObjectSpecification o2) {
+                return o1.getFullIdentifier().compareTo(o2.getFullIdentifier());
+            }
+        };
+        public final static Comparator<ObjectSpecification> SHORT_IDENTIFIER_IGNORE_CASE = new Comparator<ObjectSpecification>() {
+            @Override
+            public int compare(final ObjectSpecification s1, final ObjectSpecification s2) {
+                return s1.getShortIdentifier().compareToIgnoreCase(s2.getShortIdentifier());
+            }
+        };
+    }
+    class Functions {
+
+        private Functions(){}
+
+        public static final Function<ObjectSpecification, String> FULL_IDENTIFIER = new Function<ObjectSpecification, String>() {
+            @Override
+            public String apply(final ObjectSpecification objectSpecification) {
+                return objectSpecification.getFullIdentifier();
+            }
+        };
+
+    }
 
     /**
      * @return
@@ -95,8 +116,8 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
      * Returns the (unique) spec Id, as per the {@link ObjectSpecIdFacet}.
      * 
      * <p>
-     * This will typically be the value of the {@link ObjectType} annotation (or equivalent);
-     * if non has been specified then will default to the fully qualified class name (with
+     * This will typically be the value of the {@link DomainObject#objectType()} annotation attribute.
+     * If none has been specified then will default to the fully qualified class name (with
      * {@link ClassSubstitutor class name substituted} if necessary to allow for runtime bytecode enhancement.
      * 
      * <p>
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 f4a30ff..5dca06a 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
@@ -34,6 +34,7 @@ import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.NatureOfService;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.core.commons.components.ApplicationScopedComponent;
+import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.commons.ensure.Assert;
 import org.apache.isis.core.commons.exceptions.IsisException;
 import org.apache.isis.core.commons.lang.ClassUtil;
@@ -91,6 +92,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
     private final ProgrammingModel programmingModel;
     private final FacetProcessor facetProcessor;
 
+    private final IsisConfiguration configuration;
     private final ServicesInjector servicesInjector;
 
     private final MetaModelValidator metaModelValidator;
@@ -98,11 +100,14 @@ public class SpecificationLoader implements ApplicationScopedComponent {
     private final List<LayoutMetadataReader> layoutMetadataReaders;
 
     public SpecificationLoader(
+            final IsisConfiguration configuration,
             final ProgrammingModel programmingModel,
             final MetaModelValidator metaModelValidator,
             final List<LayoutMetadataReader> layoutMetadataReaders,
             final ServicesInjector servicesInjector) {
 
+        this.configuration = configuration;
+
         this.servicesInjector = servicesInjector;
         this.programmingModel = programmingModel;
         this.metaModelValidator = metaModelValidator;
@@ -533,5 +538,7 @@ public class SpecificationLoader implements ApplicationScopedComponent {
 
     //endregion
 
-
+    public IsisConfiguration getConfiguration() {
+        return configuration;
+    }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index cfa0dd0..cedeffe 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -164,7 +164,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
     private final Identifier identifier;
     private final boolean isAbstract;
     // derived lazily, cached since immutable
-    private ObjectSpecId specId;
+    protected ObjectSpecId specId;
 
     private ObjectSpecification superclassSpec;
 
@@ -214,9 +214,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if(facet == null) {
                 throw new IllegalStateException("could not find an ObjectSpecIdFacet for " + this.getFullIdentifier());
             }
-            if(facet != null) {
-                specId = facet.value();
-            }
+            specId = facet.value();
         }
         return specId;
     }
@@ -517,12 +515,10 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
     @Override
     public <Q extends Facet> Q getFacet(final Class<Q> facetType) {
         final Q facet = super.getFacet(facetType);
-        Q noopFacet = null;
         if (isNotANoopFacet(facet)) {
             return facet;
-        } else {
-            noopFacet = facet;
         }
+        Q noopFacet = facet; // might be null
         if (interfaces() != null) {
             final List<ObjectSpecification> interfaces = interfaces();
             for (int i = 0; i < interfaces.size(); i++) {
@@ -536,10 +532,9 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
                 final Q interfaceFacet = interfaceSpec.getFacet(facetType);
                 if (isNotANoopFacet(interfaceFacet)) {
                     return interfaceFacet;
-                } else {
-                    if (noopFacet == null) {
-                        noopFacet = interfaceFacet;
-                    }
+                }
+                if (noopFacet == null) {
+                    noopFacet = interfaceFacet; // might be null
                 }
             }
         }
@@ -550,6 +545,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             if (isNotANoopFacet(superClassFacet)) {
                 return superClassFacet;
             }
+            // TODO: should we perhaps default the noopFacet here as we do in the previous two cases?
         }
         return noopFacet;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
index 2234bb4..c429804 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java
@@ -24,9 +24,11 @@ import java.util.List;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacetDefaultToObject;
+import org.apache.isis.core.metamodel.facets.object.objectspecid.classname.ObjectSpecIdFacetOnStandaloneList;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.FreeStandingList;
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
 import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
@@ -49,6 +51,7 @@ public class ObjectSpecificationOnStandaloneList extends ObjectSpecificationAbst
             final ServicesInjector servicesInjector,
             final FacetProcessor facetProcessor) {
         super(FreeStandingList.class, NAME, servicesInjector, facetProcessor);
+        this.specId = new ObjectSpecId(getCorrespondingClass().getName());
     }
 
     //endregion
@@ -67,6 +70,7 @@ public class ObjectSpecificationOnStandaloneList extends ObjectSpecificationAbst
         FacetUtil.addFacet(new NamedFacetOnStandaloneList(NAME, this));
         FacetUtil.addFacet(new PluralFacetOnStandaloneList(NAME, this));
         FacetUtil.addFacet(new DescribedAsFacetOnStandaloneList(DESCRIBED_AS, this));
+         FacetUtil.addFacet(new ObjectSpecIdFacetOnStandaloneList(specId, this));
         // don't install anything for NotPersistableFacet
     }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckObjectSpecIdsUnique.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckObjectSpecIdsUnique.java
new file mode 100644
index 0000000..a5374a4
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckObjectSpecIdsUnique.java
@@ -0,0 +1,95 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.metamodel.specloader.validator;
+
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecId;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class MetaModelValidatorToCheckObjectSpecIdsUnique extends MetaModelValidatorComposite {
+
+    public static final String ISIS_REFLECTOR_ENSURE_UNIQUE_OBJECT_IDS_KEY = "isis.reflector.validator.ensureUniqueObjectTypes";
+    public static final boolean ISIS_REFLECTOR_ENSURE_UNIQUE_OBJECT_IDS_DEFAULT = true;
+
+    public MetaModelValidatorToCheckObjectSpecIdsUnique() {
+        addValidatorToEnsureUniqueObjectIds();
+    }
+
+    @Override
+    public void validate(final ValidationFailures validationFailures) {
+        boolean check = specificationLoader.getConfiguration()
+                            .getBoolean(ISIS_REFLECTOR_ENSURE_UNIQUE_OBJECT_IDS_KEY,
+                                        ISIS_REFLECTOR_ENSURE_UNIQUE_OBJECT_IDS_DEFAULT);
+        if(!check) {
+            return;
+        }
+        super.validate(validationFailures);
+    }
+
+    private void addValidatorToEnsureUniqueObjectIds() {
+
+        final Map<ObjectSpecId, List<ObjectSpecification>> specsById = Maps.newHashMap();
+
+        MetaModelValidatorVisiting.SummarizingVisitor ensureUniqueObjectIds = new MetaModelValidatorVisiting.SummarizingVisitor(){
+
+            @Override
+            public boolean visit(ObjectSpecification objSpec, ValidationFailures validationFailures) {
+                ObjectSpecId specId = objSpec.getSpecId();
+                List<ObjectSpecification> objectSpecifications = specsById.get(specId);
+                if(objectSpecifications == null) {
+                    objectSpecifications = Lists.newArrayList();
+                    specsById.put(specId, objectSpecifications);
+                }
+                objectSpecifications.add(objSpec);
+                return true;
+            }
+
+            @Override
+            public void summarize(final ValidationFailures validationFailures) {
+                for (final ObjectSpecId specId : specsById.keySet()) {
+                    final List<ObjectSpecification> specList = specsById.get(specId);
+                    int numSpecs = specList.size();
+                    if(numSpecs > 1) {
+                        String csv = asCsv(specList);
+                        validationFailures.add(
+                                "Object type '%s' mapped to multiple classes: %s", specId.asString(), csv);
+                    }
+                }
+            }
+
+            private String asCsv(final List<ObjectSpecification> specList) {
+                return Joiner.on(",").join(
+                        FluentIterable.from(specList)
+                              .transform(ObjectSpecification.Functions.FULL_IDENTIFIER)
+                              .toList());
+            }
+
+        };
+
+
+        add(new MetaModelValidatorVisiting(ensureUniqueObjectIds));
+    }
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/JavaReflectorHelper.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/JavaReflectorHelper.java
index 898bc03..ee0b8ce 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/JavaReflectorHelper.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/JavaReflectorHelper.java
@@ -60,7 +60,7 @@ public final class JavaReflectorHelper  {
             programmingModel.refineMetaModelValidator(metaModelValidator, configuration);
         }
 
-        return new SpecificationLoader(programmingModel, metaModelValidator, layoutMetadataReaders, servicesInjector);
+        return new SpecificationLoader(configuration, programmingModel, metaModelValidator, layoutMetadataReaders, servicesInjector);
     }
 
 }
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
index 8f4a51c..8e386f2 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/SpecificationLoaderTestAbstract.java
@@ -108,7 +108,7 @@ public abstract class SpecificationLoaderTestAbstract {
 
         final SpecificationLoader specificationLoader =
                 new SpecificationLoader(
-                        new ProgrammingModelFacetsJava5(stubConfiguration),
+                        stubConfiguration, new ProgrammingModelFacetsJava5(stubConfiguration),
                         new MetaModelValidatorDefault(), Lists.<LayoutMetadataReader>newArrayList(
                                 new LayoutMetadataReaderFromJson()), stubServicesInjector);
 
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
index 3933a98..aa3396a 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
@@ -22,6 +22,7 @@ import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorToCheckObjectSpecIdsUnique;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.auditable.AuditableAnnotationInJdoApplibFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.auditable.AuditableMarkerInterfaceInJdoApplibFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.datastoreidentity.JdoDatastoreIdentityAnnotationFacetFactory;
@@ -67,5 +68,6 @@ public class PersistenceSessionFactoryMetamodelRefiner implements MetaModelRefin
             MetaModelValidatorComposite metaModelValidator,
             IsisConfiguration configuration) {
         metaModelValidator.add(new JdoMetaModelValidator());
+        metaModelValidator.add(new MetaModelValidatorToCheckObjectSpecIdsUnique());
     }
 }

-- 
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.

[isis] 03/03: Merge branch 'ISIS-1848' into maint-1.16.1

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git

commit b6bb1c77d4240840ee2db354767ba61ed3d0b916
Merge: e21fef1 128e144
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Jan 24 15:13:45 2018 +0000

    Merge branch 'ISIS-1848' into maint-1.16.1

 .../guides/rgcfg/_rgcfg_configuring-core.adoc      |  15 ++
 .../objectspecid/ObjectSpecIdFacetAbstract.java    |   9 +-
 .../ObjectSpecIdFacetOnStandaloneList.java}        |  30 +---
 .../core/metamodel/spec/ObjectSpecification.java   |  61 +++++---
 .../metamodel/specloader/SpecificationLoader.java  |  13 ++
 .../specimpl/ObjectSpecificationAbstract.java      |  18 +--
 .../ObjectSpecificationOnStandaloneList.java       |   4 +
 .../MetaModelValidatorToCheckModuleExtent.java     | 153 +++++++++++++++++++++
 ...taModelValidatorToCheckObjectSpecIdsUnique.java |  95 +++++++++++++
 .../isis/progmodels/dflt/JavaReflectorHelper.java  |   2 +-
 .../SpecificationLoaderTestAbstract.java           |   2 +-
 .../PersistenceSessionFactoryMetamodelRefiner.java |   4 +
 12 files changed, 347 insertions(+), 59 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.

[isis] 02/03: ISIS-1837: adds metamodel validator to check "module extent".

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch maint-1.16.1
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 128e14497c347c35adc501f0d8ff07eb7e2604a8
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Jan 24 15:12:01 2018 +0000

    ISIS-1837: adds metamodel validator to check "module extent".
---
 .../guides/rgcfg/_rgcfg_configuring-core.adoc      |  10 +-
 .../metamodel/specloader/SpecificationLoader.java  |   6 +
 .../MetaModelValidatorToCheckModuleExtent.java     | 153 +++++++++++++++++++++
 .../PersistenceSessionFactoryMetamodelRefiner.java |   2 +
 4 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc b/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
index d7b5ba3..13714e6 100644
--- a/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/rgcfg/_rgcfg_configuring-core.adoc
@@ -328,10 +328,18 @@ If not, then a metamodel validation error will be triggered, meaning the app won
 See also `isis.reflector.facets.ignoreDeprecated`.
 
 |`isis.reflector.validator.` +
+`checkModuleExtent`
+|`true`,`false` +
+(`true`)
+|Whether to check that all domain objects discovered reside under the top-level module of the app manifest.
+
+Note that the application must be bootstrapped using an `AppManifest2`.
+
+|`isis.reflector.validator.` +
 `ensureUniqueObjectTypes`
 |`true`,`false` +
 (`true`)
-|Whether to ensure that all classes in the metamodel map to a different object type (typically either as explicitly specified using `@DomainObject(objectType=...)`, or their class name as a fallback).  +
+|Whether to ensure that all classes in the metamodel map to a different object type (typically either as explicitly specified using `@DomainObject(objectType=...)`, or their class name as a fallback).
 
 
 |`isis.reflector.validator.` +
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 5dca06a..c397341 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
@@ -538,7 +538,13 @@ public class SpecificationLoader implements ApplicationScopedComponent {
 
     //endregion
 
+    @Programmatic
     public IsisConfiguration getConfiguration() {
         return configuration;
     }
+
+    @Programmatic
+    public ServicesInjector getServicesInjector() {
+        return servicesInjector;
+    }
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckModuleExtent.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckModuleExtent.java
new file mode 100644
index 0000000..f41e16a
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorToCheckModuleExtent.java
@@ -0,0 +1,153 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.core.metamodel.specloader.validator;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.AppManifest;
+import org.apache.isis.applib.AppManifest2;
+import org.apache.isis.applib.Module;
+import org.apache.isis.applib.services.metamodel.MetaModelService4;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class MetaModelValidatorToCheckModuleExtent extends MetaModelValidatorComposite {
+
+    private static final String ISIS_REFLECTOR_CHECK_MODULE_EXTENT_KEY = "isis.reflector.validator.checkModuleExtent";
+    private static final boolean ISIS_REFLECTOR_CHECK_MODULE_EXTENT_DEFAULT = true;
+
+    public MetaModelValidatorToCheckModuleExtent() {
+        addValidatorToCheckModuleExtent();
+    }
+
+    @Override
+    public void validate(final ValidationFailures validationFailures) {
+        boolean check = specificationLoader.getConfiguration()
+                            .getBoolean(ISIS_REFLECTOR_CHECK_MODULE_EXTENT_KEY,
+                                    ISIS_REFLECTOR_CHECK_MODULE_EXTENT_DEFAULT);
+        if(!check) {
+            return;
+        }
+
+        AppManifest2 appManifest = specificationLoader.getServicesInjector()
+                .lookupService(MetaModelService4.class).getAppManifest2();
+        if(appManifest == null) {
+            return;
+        }
+
+        super.validate(validationFailures);
+    }
+
+    private void addValidatorToCheckModuleExtent() {
+
+        final Map<String, List<String>> domainObjectClassNamesByPackage = Maps.newTreeMap();
+
+        MetaModelValidatorVisiting.SummarizingVisitor visitor = new MetaModelValidatorVisiting.SummarizingVisitor(){
+
+            @Override
+            public boolean visit(ObjectSpecification objSpec, ValidationFailures validationFailures) {
+                Class<?> correspondingClass = objSpec.getCorrespondingClass();
+                if(correspondingClass == null) {
+                    return true;
+                }
+                Package aPackage = correspondingClass.getPackage();
+                if(aPackage == null) {
+                    return true;
+                }
+                final String packageName = aPackage.getName();
+
+                if (objSpec.isValue() || objSpec.isAbstract() || objSpec.isMixin() ||
+                        objSpec.isParentedOrFreeCollection() ||
+                        objSpec.getFullIdentifier().startsWith("java") ||
+                        objSpec.getFullIdentifier().startsWith("org.joda") ||
+                        objSpec.getFullIdentifier().startsWith("org.apache.isis")) {
+                    // ignore
+                } else {
+                    List<String> classNames = domainObjectClassNamesByPackage.get(packageName);
+                    if (classNames == null) {
+                        classNames = Lists.newArrayList();
+                        domainObjectClassNamesByPackage.put(packageName, classNames);
+                    }
+                    classNames.add(objSpec.getFullIdentifier());
+                }
+                return true;
+            }
+
+            @Override
+            public void summarize(final ValidationFailures validationFailures) {
+
+                AppManifest2 appManifest = specificationLoader.getServicesInjector()
+                        .lookupService(MetaModelService4.class).getAppManifest2();
+                if(appManifest == null) {
+                    return;
+                }
+                Module topLevelModule = appManifest.getModule();
+                if(topLevelModule == null) {
+                    // shouldn't happen
+                    return;
+                }
+
+                ImmutableList<String> modulePackageNames = modulePackageNamesFrom(appManifest);
+
+                final Set<String> domainObjectPackageNames = domainObjectClassNamesByPackage.keySet();
+                for (final String pkg : domainObjectPackageNames) {
+                    List<String> domainObjectClassNames = domainObjectClassNamesByPackage.get(pkg);
+                    boolean withinSomeModule = isWithinSomeModule(modulePackageNames, pkg);
+                    if(!withinSomeModule) {
+                        String csv = Joiner.on(",").join(domainObjectClassNames);
+                        validationFailures.add(
+                                "Domain objects discovered in package '%s' are not in the set of modules obtained from "
+                                + "the AppManifest's top-level module '%s'.  Classes are: %s",
+                                pkg, topLevelModule.getClass().getName(), csv);
+                    }
+                }
+            }
+
+            private ImmutableList<String> modulePackageNamesFrom(final AppManifest appManifest) {
+                List<Class<?>> modules = appManifest.getModules();
+                return FluentIterable.from(modules)
+                        .transform(new Function<Class<?>, String>() {
+                            @Override
+                            public String apply(final Class<?> aClass) {
+                                return aClass.getPackage().getName();
+                            }
+                        }).toList();
+            }
+
+            private boolean isWithinSomeModule(final ImmutableList<String> modulePackageNames, final String pkg) {
+                for (final String modulePackageName : modulePackageNames) {
+                    if(pkg.startsWith(modulePackageName)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        };
+
+        add(new MetaModelValidatorVisiting(visitor));
+    }
+}
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
index aa3396a..8ae7ac6 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/system/persistence/PersistenceSessionFactoryMetamodelRefiner.java
@@ -22,6 +22,7 @@ import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorToCheckModuleExtent;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorToCheckObjectSpecIdsUnique;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.auditable.AuditableAnnotationInJdoApplibFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.auditable.AuditableMarkerInterfaceInJdoApplibFacetFactory;
@@ -69,5 +70,6 @@ public class PersistenceSessionFactoryMetamodelRefiner implements MetaModelRefin
             IsisConfiguration configuration) {
         metaModelValidator.add(new JdoMetaModelValidator());
         metaModelValidator.add(new MetaModelValidatorToCheckObjectSpecIdsUnique());
+        metaModelValidator.add(new MetaModelValidatorToCheckModuleExtent());
     }
 }

-- 
To stop receiving notification emails like this one, please contact
danhaywood@apache.org.