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 2016/06/14 06:23:26 UTC

[5/5] isis git commit: ISIS-1418: allows @Nullable to be annotated on either properties or parameters.

ISIS-1418: allows @Nullable to be annotated on either properties or parameters.

The appropriate facet is installed, and a MetaModelValidator is used to check that there are no conflicting annotations (ie @Mandatory vs @Nullable vs @Optional vs @Property#optionality or @Parameter#optionality).


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

Branch: refs/heads/ISIS-1427
Commit: 7dd5042d117cbd55a6af3ba52c0f0a4c9ce27bb4
Parents: bd447a2
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Tue Jun 14 07:15:44 2016 +0100
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Tue Jun 14 07:15:44 2016 +0100

----------------------------------------------------------------------
 .../isis/core/commons/lang/ArrayExtensions.java |  8 +--
 .../isis/core/metamodel/facets/Annotations.java |  1 +
 .../ParameterAnnotationFacetFactory.java        | 34 +++++++---
 ...InvertedByNullableAnnotationOnParameter.java | 53 ++++++++++++++++
 .../PropertyAnnotationFacetFactory.java         | 43 +++++++++----
 ...tInvertedByNullableAnnotationOnProperty.java | 55 ++++++++++++++++
 .../validator/MetaModelValidatorAbstract.java   |  2 -
 ...ModelValidatorForConflictingOptionality.java | 66 ++++++++++++++++++++
 ...toryFromJdoColumnAnnotationFacetFactory.java |  2 +-
 9 files changed, 239 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
index dfc692d..f4b611c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
@@ -123,10 +123,10 @@ public final class ArrayExtensions {
         return list;
     }
 
-    public static <T> T coalesce(final T... strings) {
-        for (final T str : strings) {
-            if (str != null) {
-                return str;
+    public static <T> T coalesce(final T... objects) {
+        for (final T object : objects) {
+            if (object != null) {
+                return object;
             }
         }
         return null;

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/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 aa17a4c..f1e2d40 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
@@ -280,6 +280,7 @@ public final class Annotations  {
                     Collection.class,
                     CollectionLayout.class,
                     MemberOrder.class,
+                    javax.annotation.Nullable.class,
                     Title.class,
                     javax.jdo.annotations.Column.class
             )

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/ParameterAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/ParameterAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/ParameterAnnotationFacetFactory.java
index 4518e94..a54bd02 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/ParameterAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/ParameterAnnotationFacetFactory.java
@@ -22,6 +22,8 @@ package org.apache.isis.core.metamodel.facets.param.parameter;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 
+import javax.annotation.Nullable;
+
 import org.apache.isis.applib.annotation.MaxLength;
 import org.apache.isis.applib.annotation.MustSatisfy;
 import org.apache.isis.applib.annotation.Optional;
@@ -35,9 +37,11 @@ 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.facets.FacetedMethodParameter;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.regex.RegExFacet;
 import org.apache.isis.core.metamodel.facets.objectvalue.regex.TitleFacetFormattedByRegex;
 import org.apache.isis.core.metamodel.facets.param.parameter.mandatory.MandatoryFacetForParameterAnnotation;
+import org.apache.isis.core.metamodel.facets.param.parameter.mandatory.MandatoryFacetInvertedByNullableAnnotationOnParameter;
 import org.apache.isis.core.metamodel.facets.param.parameter.mandatory.MandatoryFacetInvertedByOptionalAnnotationOnParameter;
 import org.apache.isis.core.metamodel.facets.param.parameter.maxlen.MaxLengthFacetForMaxLengthAnnotationOnParameter;
 import org.apache.isis.core.metamodel.facets.param.parameter.maxlen.MaxLengthFacetForParameterAnnotation;
@@ -47,6 +51,7 @@ import org.apache.isis.core.metamodel.facets.param.parameter.regex.RegExFacetFor
 import org.apache.isis.core.metamodel.facets.param.parameter.regex.RegExFacetFromRegExAnnotationOnParameter;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForConflictingOptionality;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForDeprecatedAnnotation;
 
 public class ParameterAnnotationFacetFactory extends FacetFactoryAbstract implements MetaModelValidatorRefiner {
@@ -55,6 +60,7 @@ public class ParameterAnnotationFacetFactory extends FacetFactoryAbstract implem
     private final MetaModelValidatorForDeprecatedAnnotation mustSatisfyValidator = new MetaModelValidatorForDeprecatedAnnotation(MustSatisfy.class);
     private final MetaModelValidatorForDeprecatedAnnotation regexValidator = new MetaModelValidatorForDeprecatedAnnotation(RegEx.class);
     private final MetaModelValidatorForDeprecatedAnnotation optionalValidator = new MetaModelValidatorForDeprecatedAnnotation(Optional.class);
+    private final MetaModelValidatorForConflictingOptionality conflictingOptionalityValidator = new MetaModelValidatorForConflictingOptionality();
 
     public ParameterAnnotationFacetFactory() {
         super(FeatureType.PARAMETERS_ONLY);
@@ -177,9 +183,21 @@ public class ParameterAnnotationFacetFactory extends FacetFactoryAbstract implem
             final Class<?> parameterType = parameterTypes[paramNum];
             if (parameterAnnotation instanceof Optional) {
                 final Optional annotation = (Optional) parameterAnnotation;
-                final Facet facet = MandatoryFacetInvertedByOptionalAnnotationOnParameter.create(annotation, parameterType, holder);
-                FacetUtil.addFacet(optionalValidator.flagIfPresent(facet, processParameterContext));
-                return;
+                FacetUtil.addFacet(optionalValidator.flagIfPresent(
+                        MandatoryFacetInvertedByOptionalAnnotationOnParameter.create(
+                                annotation, parameterType, holder), processParameterContext));
+            }
+        }
+
+        for (final Annotation parameterAnnotation : parameterAnnotations) {
+            final Class<?> parameterType = parameterTypes[paramNum];
+            if (parameterAnnotation instanceof javax.annotation.Nullable) {
+                final Nullable annotation = (Nullable) parameterAnnotation;
+                final MandatoryFacet facet =
+                        MandatoryFacetInvertedByNullableAnnotationOnParameter.create(annotation, parameterType, holder);
+                FacetUtil.addFacet(facet);
+                conflictingOptionalityValidator.flagIfConflict(
+                        facet, "Conflicting @Nullable with other optionality annotation");
             }
         }
 
@@ -187,9 +205,11 @@ public class ParameterAnnotationFacetFactory extends FacetFactoryAbstract implem
             if (parameterAnnotation instanceof Parameter) {
                 final Parameter parameter = (Parameter) parameterAnnotation;
                 final Class<?> parameterType = parameterTypes[paramNum];
-                FacetUtil.addFacet(
-                        MandatoryFacetForParameterAnnotation.create(parameter, parameterType, holder));
-                return;
+                final MandatoryFacet facet =
+                        MandatoryFacetForParameterAnnotation.create(parameter, parameterType, holder);
+                FacetUtil.addFacet(facet);
+                conflictingOptionalityValidator.flagIfConflict(
+                        facet, "Conflicting @Parameter#optionality with other optionality annotation");
             }
         }
     }
@@ -200,9 +220,9 @@ public class ParameterAnnotationFacetFactory extends FacetFactoryAbstract implem
         metaModelValidator.add(mustSatisfyValidator);
         metaModelValidator.add(regexValidator);
         metaModelValidator.add(optionalValidator);
+        metaModelValidator.add(conflictingOptionalityValidator);
     }
 
-
     @Override
     public void setServicesInjector(final ServicesInjector servicesInjector) {
         super.setServicesInjector(servicesInjector);

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/mandatory/MandatoryFacetInvertedByNullableAnnotationOnParameter.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/mandatory/MandatoryFacetInvertedByNullableAnnotationOnParameter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/mandatory/MandatoryFacetInvertedByNullableAnnotationOnParameter.java
new file mode 100644
index 0000000..a1dc49d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/param/parameter/mandatory/MandatoryFacetInvertedByNullableAnnotationOnParameter.java
@@ -0,0 +1,53 @@
+/*
+ *  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.facets.param.parameter.mandatory;
+
+import javax.annotation.Nullable;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.FacetedMethodParameter;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacetAbstract;
+
+/**
+ * Derived by presence of an {@link Nullable} annotation on parameter.
+ * 
+ * <p>
+ * This implementation indicates that the {@link FacetHolder} is <i>not</i>
+ * mandatory, as per {@link #isInvertedSemantics()}.
+ */
+public class MandatoryFacetInvertedByNullableAnnotationOnParameter extends MandatoryFacetAbstract {
+
+    public static MandatoryFacet create(final Nullable annotation, final Class<?> parameterType, final FacetedMethodParameter holder) {
+        if(annotation == null) {
+            return null;
+        }
+        if(parameterType.isPrimitive()) {
+            return null;
+        }
+        return new MandatoryFacetInvertedByNullableAnnotationOnParameter(holder);
+    }
+
+    private MandatoryFacetInvertedByNullableAnnotationOnParameter(final FacetHolder holder) {
+        super(holder, Semantics.OPTIONAL);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/PropertyAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/PropertyAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/PropertyAnnotationFacetFactory.java
index 76f1f32..82989f4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/PropertyAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/PropertyAnnotationFacetFactory.java
@@ -21,6 +21,8 @@ package org.apache.isis.core.metamodel.facets.properties.property;
 
 import java.lang.reflect.Method;
 
+import javax.annotation.Nullable;
+
 import org.apache.isis.applib.annotation.Disabled;
 import org.apache.isis.applib.annotation.Hidden;
 import org.apache.isis.applib.annotation.Mandatory;
@@ -60,6 +62,7 @@ import org.apache.isis.core.metamodel.facets.properties.property.hidden.HiddenFa
 import org.apache.isis.core.metamodel.facets.properties.property.hidden.HiddenFacetForPropertyAnnotation;
 import org.apache.isis.core.metamodel.facets.properties.property.mandatory.MandatoryFacetForMandatoryAnnotationOnProperty;
 import org.apache.isis.core.metamodel.facets.properties.property.mandatory.MandatoryFacetForPropertyAnnotation;
+import org.apache.isis.core.metamodel.facets.properties.property.mandatory.MandatoryFacetInvertedByNullableAnnotationOnProperty;
 import org.apache.isis.core.metamodel.facets.properties.property.mandatory.MandatoryFacetInvertedByOptionalAnnotationOnProperty;
 import org.apache.isis.core.metamodel.facets.properties.property.maxlength.MaxLengthFacetForMaxLengthAnnotationOnProperty;
 import org.apache.isis.core.metamodel.facets.properties.property.maxlength.MaxLengthFacetForPropertyAnnotation;
@@ -87,6 +90,7 @@ import org.apache.isis.core.metamodel.facets.properties.update.clear.PropertyCle
 import org.apache.isis.core.metamodel.facets.properties.update.modify.PropertySetterFacet;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite;
+import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForConflictingOptionality;
 import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForDeprecatedAnnotation;
 import org.apache.isis.core.metamodel.util.EventUtil;
 
@@ -102,6 +106,8 @@ public class PropertyAnnotationFacetFactory extends FacetFactoryAbstract impleme
     private final MetaModelValidatorForDeprecatedAnnotation maxLengthValidator = new MetaModelValidatorForDeprecatedAnnotation(MaxLength.class);
     private final MetaModelValidatorForDeprecatedAnnotation mustSatisfyValidator = new MetaModelValidatorForDeprecatedAnnotation(MustSatisfy.class);
     private final MetaModelValidatorForDeprecatedAnnotation notPersistedValidator = new MetaModelValidatorForDeprecatedAnnotation(NotPersisted.class);
+    private final MetaModelValidatorForConflictingOptionality conflictingOptionalityValidator = new MetaModelValidatorForConflictingOptionality();
+
 
     public PropertyAnnotationFacetFactory() {
         super(FeatureType.PROPERTIES_AND_ACTIONS);
@@ -386,23 +392,37 @@ public class PropertyAnnotationFacetFactory extends FacetFactoryAbstract impleme
 
         final FacetHolder holder = processMethodContext.getFacetHolder();
 
-        // check for deprecated @Optional first
+        // check for deprecated @Optional
         final Optional optionalAnnotation = Annotations.getAnnotation(method, Optional.class);
-        MandatoryFacet facet = optionalValidator.flagIfPresent(MandatoryFacetInvertedByOptionalAnnotationOnProperty.create(optionalAnnotation, method, holder), processMethodContext);
+        FacetUtil.addFacet(
+                optionalValidator.flagIfPresent(
+                    MandatoryFacetInvertedByOptionalAnnotationOnProperty.create(optionalAnnotation, method, holder),
+                    processMethodContext));
 
-        // else check for deprecated @Mandatory first
+        // check for deprecated @Mandatory
         final Mandatory mandatoryAnnotation = Annotations.getAnnotation(method, Mandatory.class);
-        if(facet == null) {
-            facet = mandatoryValidator.flagIfPresent(MandatoryFacetForMandatoryAnnotationOnProperty.create(mandatoryAnnotation, holder), processMethodContext);
-        }
+        final MandatoryFacet facet =
+                mandatoryValidator.flagIfPresent(
+                    MandatoryFacetForMandatoryAnnotationOnProperty.create(mandatoryAnnotation, holder),
+                    processMethodContext);
+        FacetUtil.addFacet(facet);
+        conflictingOptionalityValidator.flagIfConflict(
+                facet, "Conflicting @Mandatory with other optionality annotation");
+
+        // else check for @Nullable
+        final Nullable nullableAnnotation = Annotations.getAnnotation(method, Nullable.class);
+        final MandatoryFacet facet2 =
+                MandatoryFacetInvertedByNullableAnnotationOnProperty.create(nullableAnnotation, method, holder);
+        FacetUtil.addFacet(facet2);
+        conflictingOptionalityValidator.flagIfConflict(
+                    facet2, "Conflicting @Nullable with other optionality annotation");
 
         // else search for @Property(optional=...)
         final Property property = Annotations.getAnnotation(method, Property.class);
-        if(facet == null) {
-            facet = MandatoryFacetForPropertyAnnotation.create(property, method, holder);
-        }
-
-        FacetUtil.addFacet(facet);
+        final MandatoryFacet facet3 = MandatoryFacetForPropertyAnnotation.create(property, method, holder);
+        FacetUtil.addFacet(facet3);
+        conflictingOptionalityValidator.flagIfConflict(
+                    facet3, "Conflicting Property#optionality with other optionality annotation");
     }
 
     void processRegEx(final ProcessMethodContext processMethodContext) {
@@ -444,6 +464,7 @@ public class PropertyAnnotationFacetFactory extends FacetFactoryAbstract impleme
         metaModelValidator.add(maxLengthValidator);
         metaModelValidator.add(mustSatisfyValidator);
         metaModelValidator.add(notPersistedValidator);
+        metaModelValidator.add(conflictingOptionalityValidator);
     }
 
     // //////////////////////////////////////

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/mandatory/MandatoryFacetInvertedByNullableAnnotationOnProperty.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/mandatory/MandatoryFacetInvertedByNullableAnnotationOnProperty.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/mandatory/MandatoryFacetInvertedByNullableAnnotationOnProperty.java
new file mode 100644
index 0000000..dbac2d5
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/properties/property/mandatory/MandatoryFacetInvertedByNullableAnnotationOnProperty.java
@@ -0,0 +1,55 @@
+/*
+ *  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.facets.properties.property.mandatory;
+
+import java.lang.reflect.Method;
+
+import javax.annotation.Nullable;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacetAbstract;
+
+/**
+ * Derived by presence of an {@link Nullable} annotation.
+ * 
+ * <p>
+ * This implementation indicates that the {@link FacetHolder} is <i>not</i>
+ * mandatory, as per {@link #isInvertedSemantics()}.
+ */
+public class MandatoryFacetInvertedByNullableAnnotationOnProperty extends MandatoryFacetAbstract {
+
+    public MandatoryFacetInvertedByNullableAnnotationOnProperty(final FacetHolder holder) {
+        super(holder, Semantics.OPTIONAL);
+    }
+
+    public static MandatoryFacet create(final Nullable annotation, Method method, final FacetHolder holder) {
+
+        if(annotation == null) {
+            return null;
+        }
+
+        final Class<?> returnType = method.getReturnType();
+        if (returnType.isPrimitive()) {
+            return null;
+        }
+        return new MandatoryFacetInvertedByNullableAnnotationOnProperty(holder);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorAbstract.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorAbstract.java
index bde6490..9e492c9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorAbstract.java
@@ -33,6 +33,4 @@ public abstract class MetaModelValidatorAbstract implements MetaModelValidator {
     @Override
     public void shutdown() {
     }
-
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorForConflictingOptionality.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorForConflictingOptionality.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorForConflictingOptionality.java
new file mode 100644
index 0000000..514d1ea
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/validator/MetaModelValidatorForConflictingOptionality.java
@@ -0,0 +1,66 @@
+/*
+ *  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 org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacet;
+import org.apache.isis.core.metamodel.facets.objectvalue.mandatory.MandatoryFacetDefault;
+
+public class MetaModelValidatorForConflictingOptionality extends MetaModelValidatorAbstract {
+
+    private final ValidationFailures failures = new ValidationFailures();
+
+    public MetaModelValidatorForConflictingOptionality() {
+    }
+
+    @Override
+    public void validate(final ValidationFailures validationFailures) {
+        validationFailures.addAll(failures);
+    }
+
+    private Facet addFailure(final Facet facet, final String message) {
+        if(facet != null) {
+            failures.add(message + ": " + ((IdentifiedHolder) facet.getFacetHolder()).getIdentifier().toFullIdentityString());
+        }
+        return facet;
+    }
+
+    public Facet flagIfConflict(final MandatoryFacet facet, final String message) {
+        if(conflictingOptionality(facet)) {
+            addFailure(facet, message);
+        }
+        return facet;
+    }
+
+    private static boolean conflictingOptionality(final MandatoryFacet facet) {
+        if (facet == null) {
+            return false;
+        }
+        final MandatoryFacet underlyingFacet = (MandatoryFacet) facet.getUnderlyingFacet();
+        if(underlyingFacet instanceof MandatoryFacetDefault) {
+            return false;
+        }
+        final boolean conflicting =
+                underlyingFacet != null && facet.isInvertedSemantics() != underlyingFacet.isInvertedSemantics();
+        return conflicting;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/7dd5042d/core/metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
index 9cd9173..89332b0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/objectstore/jdo/metamodel/facets/prop/column/MandatoryFromJdoColumnAnnotationFacetFactory.java
@@ -113,7 +113,7 @@ public class MandatoryFromJdoColumnAnnotationFacetFactory extends FacetFactoryAb
             // per JDO spec
             return returnType != null && returnType.isPrimitive();
         } else {
-            return "false".equalsIgnoreCase(allowsNull.trim());
+            return !"true".equalsIgnoreCase(allowsNull.trim()); // if mis-spelt, then DN assumes is not-nullable
         }
     }