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 2017/02/13 18:05:02 UTC

isis git commit: ISIS-1581: adds metamodel validator that ObjectSpecIdFacet is provided explicitly.

Repository: isis
Updated Branches:
  refs/heads/maint-1.14.0 fcd772ff3 -> a00f0c082


ISIS-1581: adds metamodel validator that ObjectSpecIdFacet is provided explicitly.

This is disabled by default, can be enabled using configuration property.


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/a00f0c08
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/a00f0c08
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/a00f0c08

Branch: refs/heads/maint-1.14.0
Commit: a00f0c08299cb0c5d85ec017086a431bec939fd3
Parents: fcd772f
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Mon Feb 13 18:04:53 2017 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Mon Feb 13 18:04:53 2017 +0000

----------------------------------------------------------------------
 .../guides/_rgcfg_configuring-core.adoc         | 13 +++++
 .../DomainObjectAnnotationFacetFactory.java     |  9 +---
 ...tSpecIdFacetDerivedFromClassNameFactory.java | 54 +++++++++++++++++++-
 .../metamodel/spec/ObjectSpecification.java     |  3 ++
 .../specimpl/ObjectSpecificationAbstract.java   | 11 ++++
 .../testspec/ObjectSpecificationStub.java       | 12 ++++-
 .../application/manifest/isis.properties        |  7 +++
 .../modules/simple/dom/impl/SimpleObject.java   |  7 +--
 8 files changed, 101 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/adocs/documentation/src/main/asciidoc/guides/_rgcfg_configuring-core.adoc
----------------------------------------------------------------------
diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgcfg_configuring-core.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgcfg_configuring-core.adoc
index c5fa844..7b5088a 100644
--- a/adocs/documentation/src/main/asciidoc/guides/_rgcfg_configuring-core.adoc
+++ b/adocs/documentation/src/main/asciidoc/guides/_rgcfg_configuring-core.adoc
@@ -510,6 +510,19 @@ See also `isis.reflector.facets.ignoreDeprecated`.
 Only "SELECT" queries are validated; "UPDATE" queries etc are simply ignored.
 
 |`isis.reflector.validator.` +
+`explicitObjectType`
+|`true`,`false` +
+(`false`)
+| (`1.14.0-SNAPSHOT`) Whether to check that the class has an object type explicitly specified somehow.
+
+The object type is used by the framework as an alias for the object's concrete class; it is one part of the object's OID and can be seen in the URLs of the xref:ugvw.adoc#[Wicket viewer] and xref:ugvro.adoc#[Restful Objects viewer], and is encoded in the ``Bookmark``s returned by the xref:rgsvc.adoc#_rgsvc_api_BookmarkService[`BookmarkService`].
+In this was it may also be persisted, for example in polymorphic associations or command or auditing tables.
+
+If the object type is not specified explicitly, then this can cause data migration issues if the class is subsequently refactored (eg renamed, or moved to a different package).
+
+This configuration property can be used to enforce a rule that the object type must always be specified (for persistent entities and view models).
+
+|`isis.reflector.validator.` +
 `jdoqlVariablesClause`
 |`true`,`false` +
 (`true`)

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java
----------------------------------------------------------------------
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 5910b4a..588e9eb 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
@@ -521,7 +521,7 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract
             @Override
             public boolean visit(final ObjectSpecification thisSpec, final ValidationFailures validationFailures) {
 
-                if(!isEntityOrViewModel(thisSpec)) {
+                if(!thisSpec.isPersistenceCapableOrViewModel()) {
                     return true;
                 }
 
@@ -533,7 +533,7 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract
                         continue;
                     }
 
-                    if(!isEntityOrViewModel(otherSpec)) {
+                    if(!otherSpec.isPersistenceCapableOrViewModel()) {
                         continue;
                     }
 
@@ -556,11 +556,6 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract
                 return true;
             }
 
-            public boolean isEntityOrViewModel(final ObjectSpecification thisSpec) {
-                ViewModelFacet facet = thisSpec.getFacet(ViewModelFacet.class);
-                JdoPersistenceCapableFacet facet1 = thisSpec.getFacet(JdoPersistenceCapableFacet.class);
-                return facet != null || facet1 != null;
-            }
         }));
 
         metaModelValidator.add(publishedObjectValidator);

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
index 477887d..04b6890 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/objectspecid/classname/ObjectSpecIdFacetDerivedFromClassNameFactory.java
@@ -19,14 +19,27 @@
 
 package org.apache.isis.core.metamodel.facets.object.objectspecid.classname;
 
+import org.apache.isis.core.commons.config.IsisConfiguration;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facetapi.MetaModelValidatorRefiner;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 import org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidator;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+
+public class ObjectSpecIdFacetDerivedFromClassNameFactory extends FacetFactoryAbstract implements
+        MetaModelValidatorRefiner {
+
+    public static final String ISIS_REFLECTOR_VALIDATOR_EXPLICIT_OBJECT_TYPE_KEY =
+            "isis.reflector.validator.explicitObjectType";
+    public static final boolean ISIS_REFLECTOR_VALIDATOR_EXPLICIT_OBJECT_TYPE_DEFAULT = false;
 
-public class ObjectSpecIdFacetDerivedFromClassNameFactory extends FacetFactoryAbstract {
 
     private final ClassSubstitutor classSubstitutor = new ClassSubstitutor();
 
@@ -46,4 +59,43 @@ public class ObjectSpecIdFacetDerivedFromClassNameFactory extends FacetFactoryAb
         FacetUtil.addFacet(new ObjectSpecIdFacetDerivedFromClassName(substitutedClass.getCanonicalName(), facetHolder));
     }
 
+    @Override
+    public void refineMetaModelValidator(final MetaModelValidatorComposite metaModelValidator, final IsisConfiguration configuration) {
+
+        final boolean doCheck = configuration.getBoolean(
+                ISIS_REFLECTOR_VALIDATOR_EXPLICIT_OBJECT_TYPE_KEY,
+                ISIS_REFLECTOR_VALIDATOR_EXPLICIT_OBJECT_TYPE_DEFAULT);
+
+        if(!doCheck) {
+            return;
+        }
+
+        final MetaModelValidator validator = new MetaModelValidatorVisiting(
+                new MetaModelValidatorVisiting.Visitor() {
+                    @Override
+                    public boolean visit(
+                            final ObjectSpecification objectSpec,
+                            final ValidationFailures validationFailures) {
+                        validate(objectSpec, validationFailures);
+                        return true;
+                    }
+
+                    private void validate(
+                            final ObjectSpecification objectSpec,
+                            final ValidationFailures validationFailures) {
+                        if(!objectSpec.isPersistenceCapable()) {
+                            return;
+                        }
+                        ObjectSpecIdFacet objectSpecIdFacet = objectSpec.getFacet(ObjectSpecIdFacet.class);
+                        if(objectSpecIdFacet instanceof ObjectSpecIdFacetDerivedFromClassName) {
+                            validationFailures.add(
+                                    "The object type must be specified explicitly, none was found for class: '%s'.  "
+                                    + "Defaulting the object type from the package/class/package name can lead to data migration issues for apps deployed to production (if the class is subsequently refactored).  Use @Discriminator, @DomainObject(objectType=...) or @PersistenceCapable(schema=...) to specify explicitly.",
+                                    objectSpec.getFullIdentifier());
+                        }
+                    }
+                });
+        metaModelValidator.add(validator);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/core/metamodel/src/main/java/org/apache/isis/core/metamodel/spec/ObjectSpecification.java
----------------------------------------------------------------------
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 8491662..29e6bb7 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
@@ -358,4 +358,7 @@ public interface ObjectSpecification extends Specification, ObjectActionContaine
     boolean isMixin();
     boolean isViewModelCloneable(ObjectAdapter targetAdapter);
     boolean isWizard();
+
+    boolean isPersistenceCapable();
+    boolean isPersistenceCapableOrViewModel();
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
----------------------------------------------------------------------
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 015e27c..ddc0ffb 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
@@ -97,6 +97,7 @@ import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
 import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.metamodel.specloader.facetprocessor.FacetProcessor;
+import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableFacet;
 
 public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implements ObjectSpecification {
 
@@ -1252,6 +1253,16 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         return isValue() || isParented();
     }
 
+    @Override
+    public boolean isPersistenceCapable() {
+        return containsFacet(JdoPersistenceCapableFacet.class);
+    }
+
+    @Override
+    public boolean isPersistenceCapableOrViewModel() {
+        return isViewModel() || isPersistenceCapable();
+    }
+
 
     //endregion
 

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
index 0ce141b..6316439 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/testspec/ObjectSpecificationStub.java
@@ -40,8 +40,8 @@ import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet;
 import org.apache.isis.core.metamodel.facets.object.objectspecid.ObjectSpecIdFacet;
 import org.apache.isis.core.metamodel.interactions.ObjectTitleContext;
 import org.apache.isis.core.metamodel.interactions.ObjectValidityContext;
-import org.apache.isis.core.metamodel.services.configinternal.ConfigurationServiceInternal;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
+import org.apache.isis.core.metamodel.services.configinternal.ConfigurationServiceInternal;
 import org.apache.isis.core.metamodel.spec.ActionType;
 import org.apache.isis.core.metamodel.spec.ObjectSpecId;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
@@ -410,11 +410,19 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
         return false;
     }
 
+    @Override
+    public boolean isPersistenceCapable() {
+        return false;
+    }
+
+    @Override
+    public boolean isPersistenceCapableOrViewModel() {
+        return false;
+    }
 
     @Override
     public String toString() {
         return getFullIdentifier();
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/example/application/simpleapp/application/src/main/resources/domainapp/application/manifest/isis.properties
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/application/src/main/resources/domainapp/application/manifest/isis.properties b/example/application/simpleapp/application/src/main/resources/domainapp/application/manifest/isis.properties
index 96acf75..3129af0 100644
--- a/example/application/simpleapp/application/src/main/resources/domainapp/application/manifest/isis.properties
+++ b/example/application/simpleapp/application/src/main/resources/domainapp/application/manifest/isis.properties
@@ -67,6 +67,13 @@ isis.reflector.validator.noParamsOnly=true
 
 
 #
+# Whether to require the object type to be specified explicitly for entities.
+# If not specified, defaults to false
+#
+isis.reflector.validator.explicitObjectType=true
+
+
+#
 # Whether to ignore or honour (at least some of the) deprecated annotations/method prefixes.
 # If not specified, default is to honour
 #

http://git-wip-us.apache.org/repos/asf/isis/blob/a00f0c08/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
----------------------------------------------------------------------
diff --git a/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java b/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
index 22f099f..a5bb120 100644
--- a/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
+++ b/example/application/simpleapp/module-simple/src/main/java/domainapp/modules/simple/dom/impl/SimpleObject.java
@@ -40,8 +40,7 @@ import lombok.Setter;
 
 @javax.jdo.annotations.PersistenceCapable(
         identityType=IdentityType.DATASTORE,
-        schema = "simple",
-        table = "SimpleObject"
+        schema = "simple"
 )
 @javax.jdo.annotations.DatastoreIdentity(
         strategy=javax.jdo.annotations.IdGeneratorStrategy.IDENTITY,
@@ -57,9 +56,7 @@ import lombok.Setter;
                         + "WHERE name.indexOf(:name) >= 0 ")
 })
 @javax.jdo.annotations.Unique(name="SimpleObject_name_UNQ", members = {"name"})
-@DomainObject(
-        objectType = "simple.SimpleObject"
-)
+@DomainObject() // objectType inferred from @PersistenceCapable#schema
 public class SimpleObject implements Comparable<SimpleObject> {
 
     public SimpleObject(final String name) {