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 2013/10/17 16:01:16 UTC

[2/3] git commit: ISIS-566: JdoVersionFacet and enforce @Version

ISIS-566: JdoVersionFacet and enforce @Version

... can only have @Version on one class in hierarchy.

also:
- some minor improvements to tests of the discriminator facet factory


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

Branch: refs/heads/master
Commit: 7e1a5202097cd754a37a89a80656aaa377f22286
Parents: bf51ee7
Author: Dan Haywood <da...@apache.org>
Authored: Thu Oct 17 14:53:40 2013 +0100
Committer: Dan Haywood <da...@apache.org>
Committed: Thu Oct 17 14:53:40 2013 +0100

----------------------------------------------------------------------
 ...ataNucleusPersistenceMechanismInstaller.java |   2 +
 .../persistence/FrameworkSynchronizer.java      |   3 +-
 .../object/discriminator/package-info.java      |   5 -
 ...ersistenceCapableAnnotationFacetFactory.java |   1 -
 .../JdoVersionAnnotationFacetFactory.java       |  91 ++++++++
 .../facets/object/version/JdoVersionFacet.java  |  25 ++
 .../version/JdoVersionFacetFromAnnotation.java  |  30 +++
 .../facets/object/version/package-info.java     |  17 ++
 ...DiscriminatorAnnotationFacetFactoryTest.java |  20 +-
 .../JdoVersionAnnotationFacetFactoryTest.java   |  89 +++++++
 ...otationFacetFactoryTest_refineMetaModel.java | 230 +++++++++++++++++++
 .../isis/core/metamodel/facets/Annotations.java |  14 ++
 12 files changed, 516 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
index 7b952e2..ab83a5e 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/DataNucleusPersistenceMechanismInstaller.java
@@ -49,6 +49,7 @@ import org.apache.isis.objectstore.jdo.metamodel.facets.object.discriminator.Jdo
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.embeddedonly.JdoEmbeddedOnlyAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.persistencecapable.JdoPersistenceCapableAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.object.query.JdoQueryAnnotationFacetFactory;
+import org.apache.isis.objectstore.jdo.metamodel.facets.object.version.JdoVersionAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.prop.column.BigDecimalDerivedFromJdoColumnAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.prop.column.MandatoryFromJdoColumnAnnotationFacetFactory;
 import org.apache.isis.objectstore.jdo.metamodel.facets.prop.column.MaxLengthDerivedFromJdoColumnAnnotationFacetFactory;
@@ -192,6 +193,7 @@ public class DataNucleusPersistenceMechanismInstaller extends PersistenceMechani
         programmingModel.addFactory(JdoPrimaryKeyAnnotationFacetFactory.class);
         programmingModel.addFactory(JdoNotPersistentAnnotationFacetFactory.class);
         programmingModel.addFactory(JdoDiscriminatorAnnotationFacetFactory.class);
+        programmingModel.addFactory(JdoVersionAnnotationFacetFactory.class);
         
         programmingModel.addFactory(JdoQueryAnnotationFacetFactory.class);
         

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
index 29bb192..5ba8ba9 100644
--- a/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
+++ b/component/objectstore/jdo/jdo-datanucleus/src/main/java/org/apache/isis/objectstore/jdo/datanucleus/persistence/FrameworkSynchronizer.java
@@ -69,7 +69,8 @@ public class FrameworkSynchronizer {
         withLogging(pojo, new Runnable() {
             @Override
             public void run() {
-                final Version datastoreVersion = getVersionIfAny(pojo);
+                final PersistenceCapable pc = pojo;
+                final Version datastoreVersion = getVersionIfAny(pc);
                 
                 final RootOid originalOid ;
                 ObjectAdapter originalAdapter = getAdapterManager().getAdapterFor(pojo);

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/package-info.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/package-info.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/package-info.java
index ec9f227..09f9828 100644
--- a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/package-info.java
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/package-info.java
@@ -14,9 +14,4 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/**
- * 
- *
- * @version $Rev$ $Date$
- */
 package org.apache.isis.objectstore.jdo.metamodel.facets.object.discriminator;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/persistencecapable/JdoPersistenceCapableAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/persistencecapable/JdoPersistenceCapableAnnotationFacetFactory.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/persistencecapable/JdoPersistenceCapableAnnotationFacetFactory.java
index 5a9d636..1bb3b10 100644
--- a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/persistencecapable/JdoPersistenceCapableAnnotationFacetFactory.java
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/persistencecapable/JdoPersistenceCapableAnnotationFacetFactory.java
@@ -24,7 +24,6 @@ import javax.jdo.annotations.PersistenceCapable;
 
 import com.google.common.base.Strings;
 
-import org.apache.isis.core.commons.lang.StringExtensions;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.Annotations;

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactory.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactory.java
new file mode 100644
index 0000000..9fdbd95
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactory.java
@@ -0,0 +1,91 @@
+/*
+ *  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.objectstore.jdo.metamodel.facets.object.version;
+
+import javax.jdo.annotations.Version;
+
+import org.apache.isis.core.commons.config.IsisConfiguration;
+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.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+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.MetaModelValidatorVisiting.Visitor;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+
+public class JdoVersionAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner {
+
+    public JdoVersionAnnotationFacetFactory() {
+        super(FeatureType.OBJECTS_ONLY);
+    }
+
+    @Override
+    public void process(ProcessClassContext processClassContext) {
+        // deliberately do NOT search superclasses/superinterfaces
+        final Class<?> cls = processClassContext.getCls();
+        final Version annotation = Annotations.getDeclaredAnnotation(cls, Version.class);
+        if (annotation == null) {
+            return;
+        }
+        FacetUtil.addFacet(new JdoVersionFacetFromAnnotation(processClassContext.getFacetHolder()));
+    }
+
+
+    @Override
+    public void refineMetaModelValidator(final MetaModelValidatorComposite metaModelValidator, IsisConfiguration configuration) {
+        metaModelValidator.add(new MetaModelValidatorVisiting(newValidatorVisitor()));
+    }
+
+    Visitor newValidatorVisitor() {
+        return new MetaModelValidatorVisiting.Visitor() {
+
+            @Override
+            public boolean visit(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                validate(objectSpec, validationFailures);
+                return true;
+            }
+
+            private void validate(ObjectSpecification objectSpec, ValidationFailures validationFailures) {
+                if(!declaresVersionAnnotation(objectSpec)) {
+                    return;
+                }
+                
+                ObjectSpecification superclassSpec = objectSpec.superclass();
+                while(superclassSpec != null) {
+                    if(declaresVersionAnnotation(superclassSpec)) {
+                        validationFailures.add("Cannot have @Version annotated on subclass and any of its supertypes; "
+                                + "subclass: %s, superclass: %s", objectSpec.getFullIdentifier(), superclassSpec.getFullIdentifier() );
+                        return;
+                    }
+                    superclassSpec = superclassSpec.superclass();
+                }
+            }
+
+            private boolean declaresVersionAnnotation(ObjectSpecification objectSpec) {
+                return Annotations.getDeclaredAnnotation(objectSpec.getCorrespondingClass(), Version.class)!=null;
+            }                
+        };
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacet.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacet.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacet.java
new file mode 100644
index 0000000..af6e343
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacet.java
@@ -0,0 +1,25 @@
+/*
+ *  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.objectstore.jdo.metamodel.facets.object.version;
+
+import org.apache.isis.core.metamodel.facets.MarkerFacet;
+
+public interface JdoVersionFacet extends MarkerFacet {
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacetFromAnnotation.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacetFromAnnotation.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacetFromAnnotation.java
new file mode 100644
index 0000000..c0e63a5
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionFacetFromAnnotation.java
@@ -0,0 +1,30 @@
+/*
+ *  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.objectstore.jdo.metamodel.facets.object.version;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.MarkerFacetAbstract;
+
+public class JdoVersionFacetFromAnnotation extends MarkerFacetAbstract implements JdoVersionFacet {
+
+    public JdoVersionFacetFromAnnotation(FacetHolder holder) {
+        super(JdoVersionFacet.class, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/package-info.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/package-info.java b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/package-info.java
new file mode 100644
index 0000000..483ca06
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/package-info.java
@@ -0,0 +1,17 @@
+/**
+ *  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.objectstore.jdo.metamodel.facets.object.version;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/GivenJdoDiscriminatorAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/GivenJdoDiscriminatorAnnotationFacetFactoryTest.java b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/GivenJdoDiscriminatorAnnotationFacetFactoryTest.java
index b5553eb..62991a6 100644
--- a/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/GivenJdoDiscriminatorAnnotationFacetFactoryTest.java
+++ b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/discriminator/GivenJdoDiscriminatorAnnotationFacetFactoryTest.java
@@ -51,10 +51,10 @@ public class GivenJdoDiscriminatorAnnotationFacetFactoryTest extends AbstractFac
 
     public void testFeatureTypes() {
         final List<FeatureType> featureTypes = facetFactory.getFeatureTypes();
-        Assert.assertTrue(contains(featureTypes, FeatureType.OBJECT));
+        assertTrue(contains(featureTypes, FeatureType.OBJECT));
         assertFalse(contains(featureTypes, FeatureType.PROPERTY));
         assertFalse(contains(featureTypes, FeatureType.COLLECTION));
-        Assert.assertFalse(contains(featureTypes, FeatureType.ACTION));
+        assertFalse(contains(featureTypes, FeatureType.ACTION));
         assertFalse(contains(featureTypes, FeatureType.ACTION_PARAMETER));
     }
 
@@ -65,11 +65,23 @@ public class GivenJdoDiscriminatorAnnotationFacetFactoryTest extends AbstractFac
 
         facetFactory.process(new FacetFactory.ProcessClassContext(Customer.class, methodRemover, facetHolder));
 
-        final Facet facet = facetHolder.getFacet(ObjectSpecIdFacet.class);
+        final Facet facet = facetHolder.getFacet(JdoDiscriminatorFacet.class);
         assertNotNull(facet);
-        Assert.assertTrue(facet instanceof ObjectSpecIdFacetInferredFromJdoDiscriminatorValueAnnotation);
+        assertTrue(facet instanceof JdoDiscriminatorFacetDefault);
     }
 
+    public void testObjectSpecIdAnnotationPickedUpOnClass() {
+        @Discriminator("CUS")
+        class Customer {
+        }
+        
+        facetFactory.process(new FacetFactory.ProcessClassContext(Customer.class, methodRemover, facetHolder));
+        
+        final Facet facet = facetHolder.getFacet(ObjectSpecIdFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof ObjectSpecIdFacetInferredFromJdoDiscriminatorValueAnnotation);
+    }
+    
     public void testIfNoEntityAnnotationThenNoFacet() {
 
         class Customer {

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest.java b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest.java
new file mode 100644
index 0000000..330c8cc
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest.java
@@ -0,0 +1,89 @@
+/*
+ *  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.objectstore.jdo.metamodel.facets.object.version;
+
+import java.util.List;
+
+import javax.jdo.annotations.PersistenceCapable;
+import javax.jdo.annotations.Version;
+
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.progmodel.facets.AbstractFacetFactoryTest;
+
+public class JdoVersionAnnotationFacetFactoryTest extends AbstractFacetFactoryTest {
+
+    private JdoVersionAnnotationFacetFactory facetFactory;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        facetFactory = new JdoVersionAnnotationFacetFactory();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        facetFactory = null;
+        super.tearDown();
+    }
+
+    public void testFeatureTypes() {
+        final List<FeatureType> featureTypes = facetFactory.getFeatureTypes();
+        assertTrue(contains(featureTypes, FeatureType.OBJECT));
+        assertFalse(contains(featureTypes, FeatureType.PROPERTY));
+        assertFalse(contains(featureTypes, FeatureType.COLLECTION));
+        assertFalse(contains(featureTypes, FeatureType.ACTION));
+        assertFalse(contains(featureTypes, FeatureType.ACTION_PARAMETER));
+    }
+
+    public void testVersionAnnotationPickedUpOnClass() {
+        @Version
+        class Customer {
+        }
+
+        facetFactory.process(new FacetFactory.ProcessClassContext(Customer.class, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(JdoVersionFacet.class);
+        assertNotNull(facet);
+        assertTrue(facet instanceof JdoVersionFacetFromAnnotation);
+    }
+
+    public void testIfNoAnnotationThenNoFacet() {
+
+        class Customer {
+        }
+
+        facetFactory.process(new FacetFactory.ProcessClassContext(Customer.class, methodRemover, facetHolder));
+
+        final Facet facet = facetHolder.getFacet(JdoVersionFacet.class);
+        assertNull(facet);
+    }
+
+    public void testNoMethodsRemoved() {
+        @PersistenceCapable
+        class Customer {
+        }
+
+        facetFactory.process(new FacetFactory.ProcessClassContext(Customer.class, methodRemover, facetHolder));
+
+        assertNoMethodsRemoved();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest_refineMetaModel.java
----------------------------------------------------------------------
diff --git a/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest_refineMetaModel.java b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest_refineMetaModel.java
new file mode 100644
index 0000000..9fc8f48
--- /dev/null
+++ b/component/objectstore/jdo/jdo-metamodel/src/test/java/org/apache/isis/objectstore/jdo/metamodel/facets/object/version/JdoVersionAnnotationFacetFactoryTest_refineMetaModel.java
@@ -0,0 +1,230 @@
+/*
+ *  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.objectstore.jdo.metamodel.facets.object.version;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import javax.jdo.annotations.Version;
+
+import org.jmock.Expectations;
+import org.jmock.Sequence;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting.Visitor;
+import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2;
+import org.apache.isis.core.unittestsupport.jmocking.JUnitRuleMockery2.Mode;
+
+public class JdoVersionAnnotationFacetFactoryTest_refineMetaModel {
+
+    @Rule
+    public JUnitRuleMockery2 context = JUnitRuleMockery2.createFor(Mode.INTERFACES_AND_CLASSES);
+
+    private ObjectSpecification mockChildType;
+    private ObjectSpecification mockParentType;
+    private ObjectSpecification mockGrandParentType;
+
+    private Visitor newValidatorVisitor;
+    private ValidationFailures validationFailures;
+
+    private Sequence sequence;
+    
+    @Before
+    public void setUp() throws Exception {
+        mockChildType = context.mock(ObjectSpecification.class, "mockChildtype");
+        mockParentType = context.mock(ObjectSpecification.class, "mockParenttype");
+        mockGrandParentType = context.mock(ObjectSpecification.class, "mockGrandParenttype");
+        
+        sequence = context.sequence("inorder");
+        
+        validationFailures = new ValidationFailures();
+        newValidatorVisitor = new JdoVersionAnnotationFacetFactory().newValidatorVisitor();
+    }
+    
+    @Test
+    public void whenNoFacet() {
+        
+        class Child {}
+        
+        context.checking(new Expectations() {
+            {
+                oneOf(mockChildType).getCorrespondingClass();
+                will(returnValue(Child.class));
+            }
+        });
+        
+        newValidatorVisitor.visit(mockChildType, validationFailures);
+        
+        assertThat(validationFailures.getNumberOfMessages(), is(0));
+    }
+    
+    @Test
+    public void whenHasFacetNoSuperType() {
+
+        @Version
+        class Child {}
+
+        context.checking(new Expectations() {
+            {
+                oneOf(mockChildType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Child.class));
+                
+                oneOf(mockChildType).superclass();
+                inSequence(sequence);
+                will(returnValue(null));
+            }
+        });
+        
+        newValidatorVisitor.visit(mockChildType, validationFailures);
+        
+        assertThat(validationFailures.getNumberOfMessages(), is(0));
+    }
+    
+    @Test
+    public void whenHasFacetWithSuperTypeHasNoFacet() {
+        
+        class Parent {}
+
+        @Version
+        class Child extends Parent {}
+
+        context.checking(new Expectations() {
+            {
+                oneOf(mockChildType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Child.class));
+                
+                oneOf(mockChildType).superclass();
+                inSequence(sequence);
+                will(returnValue(mockParentType));
+                
+                oneOf(mockParentType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Parent.class));
+                
+                oneOf(mockParentType).superclass();
+                inSequence(sequence);
+                will(returnValue(null));
+            }
+        });
+        
+        newValidatorVisitor.visit(mockChildType, validationFailures);
+        
+        assertThat(validationFailures.getNumberOfMessages(), is(0));
+    }
+
+
+    @Test
+    public void whenHasFacetWithParentTypeHasFacet() {
+        
+        @Version
+        class Parent {}
+
+        @Version
+        class Child extends Parent {}
+
+        context.checking(new Expectations() {
+            {
+                oneOf(mockChildType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Child.class));
+                
+                oneOf(mockChildType).superclass();
+                inSequence(sequence);
+                will(returnValue(mockParentType));
+                
+                oneOf(mockParentType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Parent.class));
+                
+                oneOf(mockChildType).getFullIdentifier();
+                inSequence(sequence);
+                will(returnValue("mockChildType"));
+                
+                oneOf(mockParentType).getFullIdentifier();
+                inSequence(sequence);
+                will(returnValue("mockParentType"));
+                
+            }
+        });
+        
+        newValidatorVisitor.visit(mockChildType, validationFailures);
+        
+        assertThat(validationFailures.getNumberOfMessages(), is(1));
+        assertThat(validationFailures.getMessages().iterator().next(), is("Cannot have @Version annotated on subclass and any of its supertypes; subclass: mockChildType, superclass: mockParentType"));
+    }
+
+
+    @Test
+    public void whenHasFacetWithGrandParentTypeHasFacet() {
+        
+        @Version
+        class GrandParent {}
+        
+        class Parent extends GrandParent {}
+
+        @Version
+        class Child extends Parent {}
+
+        
+        context.checking(new Expectations() {
+            {
+                oneOf(mockChildType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Child.class));
+                
+                oneOf(mockChildType).superclass();
+                inSequence(sequence);
+                will(returnValue(mockParentType));
+                
+                oneOf(mockParentType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(Parent.class));
+                
+                oneOf(mockParentType).superclass();
+                inSequence(sequence);
+                will(returnValue(mockGrandParentType));
+                
+                oneOf(mockGrandParentType).getCorrespondingClass();
+                inSequence(sequence);
+                will(returnValue(GrandParent.class));
+                
+                oneOf(mockChildType).getFullIdentifier();
+                inSequence(sequence);
+                will(returnValue("mockChildType"));
+                
+                oneOf(mockGrandParentType).getFullIdentifier();
+                inSequence(sequence);
+                will(returnValue("mockGrandParentType"));
+                
+            }
+        });
+        
+        newValidatorVisitor.visit(mockChildType, validationFailures);
+        
+        assertThat(validationFailures.getNumberOfMessages(), is(1));
+        assertThat(validationFailures.getMessages().iterator().next(), is("Cannot have @Version annotated on subclass and any of its supertypes; subclass: mockChildType, superclass: mockGrandParentType"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7e1a5202/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
index 5126fb4..49f6c02 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/Annotations.java
@@ -34,6 +34,20 @@ public final class Annotations  {
         return cls.equals(String.class);
     }
 
+    @SuppressWarnings("unchecked")
+    public static <T extends Annotation> T getDeclaredAnnotation(Class<?> cls, Class<T> annotationClass) {
+        final Annotation[] declaredAnnotations = cls.getDeclaredAnnotations();
+        if(declaredAnnotations == null) {
+            return null;
+        }
+        for (Annotation annotation : declaredAnnotations) {
+            if(annotationClass.isAssignableFrom(annotation.getClass())) {
+                return (T) annotation;
+            }
+        }
+        return null;
+    }
+
     /**
      * Searches for annotation on provided class, and if not found for the
      * superclass.