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 2012/12/05 00:41:10 UTC

[30/52] [partial] ISIS-188: consolidating isis-core

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/disabled/fromimmutable/DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/disabled/fromimmutable/DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/disabled/fromimmutable/DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory.java
new file mode 100644
index 0000000..e01e517
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/disabled/fromimmutable/DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory.java
@@ -0,0 +1,51 @@
+/*
+ *  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.progmodel.facets.properties.disabled.fromimmutable;
+
+import org.apache.isis.core.metamodel.facetapi.FacetUtil;
+import org.apache.isis.core.metamodel.facetapi.FeatureType;
+import org.apache.isis.core.metamodel.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.object.immutable.ImmutableFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+/**
+ * REVIEW: I'm not sure this {@link FacetFactory} actually makes sense. Just
+ * because a type is immutable, doesn't imply that the property can't change the
+ * instance that it refers to?
+ */
+public class DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory extends FacetFactoryAbstract {
+
+    public DisabledFacetForPropertyDerivedFromImmutableTypeFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final ObjectSpecification spec = getSpecificationLoader().loadSpecification(processMethodContext.getMethod().getDeclaringClass());
+        if (spec.containsDoOpFacet(ImmutableFacet.class)) {
+            final ImmutableFacet immutableFacet = spec.getFacet(ImmutableFacet.class);
+            final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
+            FacetUtil.addFacet(new DisabledFacetForPropertyDerivedFromImmutable(immutableFacet, facetHolder));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/MandatoryFacetInvertedByOptionalForProperty.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/MandatoryFacetInvertedByOptionalForProperty.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/MandatoryFacetInvertedByOptionalForProperty.java
new file mode 100644
index 0000000..371b3e5
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/MandatoryFacetInvertedByOptionalForProperty.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.progmodel.facets.properties.mandatory.annotation;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacetAbstract;
+
+/**
+ * Derived by presence of an <tt>@Optional</tt> method.
+ * 
+ * <p>
+ * This implementation indicates that the {@link FacetHolder} is <i>not</i>
+ * mandatory, as per {@link #isInvertedSemantics()}.
+ */
+public class MandatoryFacetInvertedByOptionalForProperty extends MandatoryFacetAbstract {
+
+    public MandatoryFacetInvertedByOptionalForProperty(final FacetHolder holder) {
+        super(holder);
+    }
+
+    /**
+     * Always returns <tt>false</tt>, indicating that the facet holder is in
+     * fact optional.
+     */
+    @Override
+    public boolean isRequiredButNull(final ObjectAdapter adapter) {
+        return false;
+    }
+
+    @Override
+    public boolean isInvertedSemantics() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/OptionalAnnotationForPropertyFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/OptionalAnnotationForPropertyFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/OptionalAnnotationForPropertyFacetFactory.java
new file mode 100644
index 0000000..48e216c
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/annotation/OptionalAnnotationForPropertyFacetFactory.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.progmodel.facets.properties.mandatory.annotation;
+
+import org.apache.isis.applib.annotation.Optional;
+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.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacet;
+
+public class OptionalAnnotationForPropertyFacetFactory extends FacetFactoryAbstract {
+
+    public OptionalAnnotationForPropertyFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Class<?> returnType = processMethodContext.getMethod().getReturnType();
+        if (returnType.isPrimitive()) {
+            return;
+        }
+        if (!Annotations.isAnnotationPresent(processMethodContext.getMethod(), Optional.class)) {
+            return;
+        }
+        final Optional annotation = Annotations.getAnnotation(processMethodContext.getMethod(), Optional.class);
+        FacetUtil.addFacet(create(annotation, processMethodContext.getFacetHolder()));
+    }
+
+    private MandatoryFacet create(final Optional annotation, final FacetHolder holder) {
+        return annotation != null ? new MandatoryFacetInvertedByOptionalForProperty(holder) : null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/dflt/MandatoryDefaultForPropertiesFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/dflt/MandatoryDefaultForPropertiesFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/dflt/MandatoryDefaultForPropertiesFacetFactory.java
new file mode 100644
index 0000000..88ef6a9
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/dflt/MandatoryDefaultForPropertiesFacetFactory.java
@@ -0,0 +1,57 @@
+/*
+ *  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.progmodel.facets.properties.mandatory.dflt;
+
+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.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacet;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacetDefault;
+import org.apache.isis.core.metamodel.specloader.facetprocessor.FacetProcessor;
+
+/**
+ * Simply installs a {@link MandatoryFacetDefault} onto all properties and
+ * parameters.
+ * 
+ * <p>
+ * The idea is that this {@link FacetFactory} is included early on in the
+ * {@link FacetProcessor}, but other {@link MandatoryFacet} implementations
+ * which don't require mandatory semantics will potentially replace these where
+ * the property or parameter is annotated or otherwise indicated as being
+ * optional.
+ */
+public class MandatoryDefaultForPropertiesFacetFactory extends FacetFactoryAbstract {
+
+    public MandatoryDefaultForPropertiesFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        FacetUtil.addFacet(create(processMethodContext.getFacetHolder()));
+    }
+
+    private MandatoryFacet create(final FacetHolder holder) {
+        return new MandatoryFacetDefault(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/MandatoryFacetOptionalViaMethodForProperty.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/MandatoryFacetOptionalViaMethodForProperty.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/MandatoryFacetOptionalViaMethodForProperty.java
new file mode 100644
index 0000000..9159f94
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/MandatoryFacetOptionalViaMethodForProperty.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.progmodel.facets.properties.mandatory.staticmethod;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.mandatory.MandatoryFacetAbstract;
+
+/**
+ * Derived by presence of an <tt>optionalXxx</tt> method.
+ * 
+ * <p>
+ * This implementation indicates that the {@link FacetHolder} is <i>not</i>
+ * mandatory, as per {@link #isInvertedSemantics()}.
+ */
+public class MandatoryFacetOptionalViaMethodForProperty extends MandatoryFacetAbstract {
+
+    public MandatoryFacetOptionalViaMethodForProperty(final FacetHolder holder) {
+        super(holder);
+    }
+
+    /**
+     * Always returns <tt>false</tt>, indicating that the facet holder is in
+     * fact optional.
+     */
+    @Override
+    public boolean isRequiredButNull(final ObjectAdapter adapter) {
+        return false;
+    }
+
+    @Override
+    public boolean isInvertedSemantics() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/PropertyOptionalFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/PropertyOptionalFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/PropertyOptionalFacetFactory.java
new file mode 100644
index 0000000..d77778e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/mandatory/staticmethod/PropertyOptionalFacetFactory.java
@@ -0,0 +1,85 @@
+/*
+ *  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.progmodel.facets.properties.mandatory.staticmethod;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.commons.lang.NameUtils;
+import org.apache.isis.core.metamodel.adapter.util.InvokeUtils;
+import org.apache.isis.core.metamodel.exceptions.MetaModelException;
+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.methodutils.MethodScope;
+import org.apache.isis.core.progmodel.facets.MethodFinderUtils;
+import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
+
+public class PropertyOptionalFacetFactory extends MethodPrefixBasedFacetFactoryAbstract {
+
+    private static final String[] PREFIXES = { MethodPrefixConstants.OPTIONAL_PREFIX };
+
+    public PropertyOptionalFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY, OrphanValidation.VALIDATE, PREFIXES);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        attachMandatoryFacetIfOptionalMethodIsFound(processMethodContext);
+    }
+
+    private static void attachMandatoryFacetIfOptionalMethodIsFound(final ProcessMethodContext processMethodContext) {
+        final Method method = processMethodContext.getMethod();
+
+        final String capitalizedName = NameUtils.javaBaseName(method.getName());
+        final Class<?> returnType = method.getReturnType();
+
+        final Class<?> cls = processMethodContext.getCls();
+        final Method optionalMethod = MethodFinderUtils.findMethod(cls, MethodScope.CLASS, MethodPrefixConstants.OPTIONAL_PREFIX + capitalizedName, boolean.class, NO_PARAMETERS_TYPES);
+        processMethodContext.removeMethod(optionalMethod);
+
+        if (!indicatesOptional(optionalMethod)) {
+            return;
+        }
+        if (returnType.isPrimitive()) {
+            throw new MetaModelException(cls.getName() + "#" + capitalizedName + " cannot be an optional property as it is of a primitive type");
+        }
+        final FacetHolder property = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new MandatoryFacetOptionalViaMethodForProperty(property));
+    }
+
+    private static boolean indicatesOptional(final Method method) {
+        if (method != null) {
+            Boolean optionalMethodReturnValue = null;
+            try {
+                optionalMethodReturnValue = (Boolean) InvokeUtils.invoke(method, new Object[0]);
+            } catch (final ClassCastException ex) {
+                // ignore
+            }
+            if (optionalMethodReturnValue == null) {
+                throw new MetaModelException("method " + method + " should return a boolean");
+            }
+            return optionalMethodReturnValue.booleanValue();
+        }
+        return false;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
new file mode 100644
index 0000000..1b2a84e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaClearMethod.java
@@ -0,0 +1,70 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacetAbstract;
+
+public class PropertyClearFacetViaClearMethod extends PropertyClearFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertyClearFacetViaClearMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return true;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return true;
+    }
+
+    @Override
+    public void clearProperty(final ObjectAdapter owningAdapter) {
+        AdapterInvokeUtils.invoke(method, owningAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
new file mode 100644
index 0000000..9cde05d
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyClearFacetViaSetterMethod.java
@@ -0,0 +1,70 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertyClearFacetAbstract;
+
+public class PropertyClearFacetViaSetterMethod extends PropertyClearFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertyClearFacetViaSetterMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return true;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return true;
+    }
+
+    @Override
+    public void clearProperty(final ObjectAdapter owningAdapter) {
+        AdapterInvokeUtils.invoke(method, owningAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetAbstract.java
new file mode 100644
index 0000000..f436133
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetAbstract.java
@@ -0,0 +1,36 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+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.properties.modify.PropertyInitializationFacet;
+
+public abstract class PropertyInitializationFacetAbstract extends FacetAbstract implements PropertyInitializationFacet {
+
+    public static Class<? extends Facet> type() {
+        return PropertyInitializationFacet.class;
+    }
+
+    public PropertyInitializationFacetAbstract(final FacetHolder holder) {
+        super(type(), holder, Derivation.NOT_DERIVED);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
new file mode 100644
index 0000000..4b86ad8
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyInitializationFacetViaSetterMethod.java
@@ -0,0 +1,69 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+
+public class PropertyInitializationFacetViaSetterMethod extends PropertyInitializationFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertyInitializationFacetViaSetterMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return false;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return false;
+    }
+
+    @Override
+    public void initProperty(final ObjectAdapter owningAdapter, final ObjectAdapter initialAdapter) {
+        AdapterInvokeUtils.invoke(method, owningAdapter, initialAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyModifyFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyModifyFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyModifyFacetFactory.java
new file mode 100644
index 0000000..e952c6e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertyModifyFacetFactory.java
@@ -0,0 +1,67 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.commons.lang.NameUtils;
+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.methodutils.MethodScope;
+import org.apache.isis.core.progmodel.facets.MethodFinderUtils;
+import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
+
+public class PropertyModifyFacetFactory extends MethodPrefixBasedFacetFactoryAbstract {
+
+    private static final String[] PREFIXES = { MethodPrefixConstants.MODIFY_PREFIX };
+
+    public PropertyModifyFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY, OrphanValidation.VALIDATE, PREFIXES);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        attachPropertyModifyFacetIfModifyMethodIsFound(processMethodContext);
+    }
+
+    private void attachPropertyModifyFacetIfModifyMethodIsFound(final ProcessMethodContext processMethodContext) {
+
+        final Method getMethod = processMethodContext.getMethod();
+        final String capitalizedName = NameUtils.javaBaseName(getMethod.getName());
+
+        final Class<?> returnType = getMethod.getReturnType();
+        final Class<?>[] paramTypes = new Class[] { returnType };
+
+        final Class<?> cls = processMethodContext.getCls();
+        final Method modifyMethod = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, MethodPrefixConstants.MODIFY_PREFIX + capitalizedName, void.class, paramTypes);
+
+        if (modifyMethod == null) {
+            return;
+        }
+        processMethodContext.removeMethod(modifyMethod);
+
+        final FacetHolder property = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new PropertySetterFacetViaModifyMethod(modifyMethod, property));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetAndClearFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetAndClearFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetAndClearFacetFactory.java
new file mode 100644
index 0000000..396cbdc
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetAndClearFacetFactory.java
@@ -0,0 +1,113 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.commons.lang.NameUtils;
+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.facets.object.notpersistable.NotPersistableFacet;
+import org.apache.isis.core.metamodel.methodutils.MethodScope;
+import org.apache.isis.core.progmodel.facets.MethodFinderUtils;
+import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
+import org.apache.isis.core.progmodel.facets.members.disabled.DisabledFacet;
+import org.apache.isis.core.progmodel.facets.members.disabled.staticmethod.DisabledFacetAlwaysEverywhere;
+import org.apache.isis.core.progmodel.facets.properties.derived.inferred.NotPersistableFacetInferred;
+
+public class PropertySetAndClearFacetFactory extends MethodPrefixBasedFacetFactoryAbstract {
+
+    private static final String[] PREFIXES = { MethodPrefixConstants.SET_PREFIX, MethodPrefixConstants.CLEAR_PREFIX };
+
+    public PropertySetAndClearFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY, OrphanValidation.VALIDATE, PREFIXES);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        final Method setMethod = attachPropertyModifyFacetIfSetterIsFound(processMethodContext);
+        final Method clearMethod = attachPropertyClearFacetIfClearMethodIsFound(processMethodContext);
+
+        attachPropertyClearFacetUsingSetterIfRequired(processMethodContext, setMethod, clearMethod);
+    }
+
+    /**
+     * Sets up the {@link PropertySetterFacetViaSetterMethod} to invoke the
+     * property's setter if available, but if none then marks the property as
+     * {@link NotPersistableFacet not-persistable} and {@link DisabledFacet
+     * disabled} otherwise.
+     */
+    private static Method attachPropertyModifyFacetIfSetterIsFound(final ProcessMethodContext processMethodContext) {
+
+        final Method getMethod = processMethodContext.getMethod();
+        final String capitalizedName = NameUtils.javaBaseName(getMethod.getName());
+
+        final Class<?> cls = processMethodContext.getCls();
+        final Class<?> returnType = getMethod.getReturnType();
+        final Class<?>[] paramTypes = new Class[] { returnType };
+        final Method setMethod = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, MethodPrefixConstants.SET_PREFIX + capitalizedName, void.class, paramTypes);
+        processMethodContext.removeMethod(setMethod);
+
+        final FacetHolder property = processMethodContext.getFacetHolder();
+        if (setMethod != null) {
+            FacetUtil.addFacet(new PropertySetterFacetViaSetterMethod(setMethod, property));
+            FacetUtil.addFacet(new PropertyInitializationFacetViaSetterMethod(setMethod, property));
+        } else {
+            FacetUtil.addFacet(new NotPersistableFacetInferred(property));
+            FacetUtil.addFacet(new DisabledFacetAlwaysEverywhere(property));
+        }
+
+        return setMethod;
+    }
+
+    private Method attachPropertyClearFacetIfClearMethodIsFound(final ProcessMethodContext processMethodContext) {
+        final Class<?> cls = processMethodContext.getCls();
+        final Method getMethod = processMethodContext.getMethod();
+        final FacetHolder property = processMethodContext.getFacetHolder();
+
+        final String capitalizedName = NameUtils.javaBaseName(getMethod.getName());
+        final Method clearMethod = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, MethodPrefixConstants.CLEAR_PREFIX + capitalizedName, void.class, NO_PARAMETERS_TYPES);
+
+        if (clearMethod == null) {
+            return null;
+        }
+        processMethodContext.removeMethod(clearMethod);
+
+        FacetUtil.addFacet(new PropertyClearFacetViaClearMethod(clearMethod, property));
+
+        return clearMethod;
+    }
+
+    private static void attachPropertyClearFacetUsingSetterIfRequired(final ProcessMethodContext processMethodContext, final Method setMethod, final Method clearMethod) {
+
+        if (clearMethod != null) {
+            return;
+        }
+        if (setMethod == null) {
+            return;
+        }
+        final FacetHolder property = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new PropertyClearFacetViaSetterMethod(setMethod, property));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
new file mode 100644
index 0000000..f37ee09
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaModifyMethod.java
@@ -0,0 +1,70 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacetAbstract;
+
+public class PropertySetterFacetViaModifyMethod extends PropertySetterFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertySetterFacetViaModifyMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return true;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return true;
+    }
+
+    @Override
+    public void setProperty(final ObjectAdapter adapter, final ObjectAdapter valueAdapter) {
+        AdapterInvokeUtils.invoke(method, adapter, valueAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
new file mode 100644
index 0000000..660d241
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/modify/PropertySetterFacetViaSetterMethod.java
@@ -0,0 +1,70 @@
+/*
+ *  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.progmodel.facets.properties.modify;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacetAbstract;
+
+public class PropertySetterFacetViaSetterMethod extends PropertySetterFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertySetterFacetViaSetterMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return true;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return true;
+    }
+
+    @Override
+    public void setProperty(final ObjectAdapter adapter, final ObjectAdapter valueAdapter) {
+        AdapterInvokeUtils.invoke(method, adapter, valueAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineAnnotationOnPropertyFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineAnnotationOnPropertyFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineAnnotationOnPropertyFacetFactory.java
new file mode 100644
index 0000000..a9ac8f0
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineAnnotationOnPropertyFacetFactory.java
@@ -0,0 +1,50 @@
+/*
+ *  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.progmodel.facets.properties.multiline.annotation;
+
+import org.apache.isis.applib.annotation.MultiLine;
+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.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.multiline.MultiLineFacet;
+
+public class MultiLineAnnotationOnPropertyFacetFactory extends FacetFactoryAbstract {
+
+    public MultiLineAnnotationOnPropertyFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Class<?> returnType = processMethodContext.getMethod().getReturnType();
+        if (!Annotations.isString(returnType)) {
+            return;
+        }
+        final MultiLine annotation = Annotations.getAnnotation(processMethodContext.getMethod(), MultiLine.class);
+        FacetUtil.addFacet(create(annotation, processMethodContext.getFacetHolder()));
+    }
+
+    private MultiLineFacet create(final MultiLine annotation, final FacetHolder holder) {
+        return (annotation != null) ? new MultiLineFacetAnnotationOnProperty(annotation.numberOfLines(), annotation.preventWrapping(), holder) : null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineFacetAnnotationOnProperty.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineFacetAnnotationOnProperty.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineFacetAnnotationOnProperty.java
new file mode 100644
index 0000000..712a35f
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/multiline/annotation/MultiLineFacetAnnotationOnProperty.java
@@ -0,0 +1,31 @@
+/*
+ *  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.progmodel.facets.properties.multiline.annotation;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.multiline.MultiLineFacetAbstract;
+
+public class MultiLineFacetAnnotationOnProperty extends MultiLineFacetAbstract {
+
+    public MultiLineFacetAnnotationOnProperty(final int numberOfLines, final boolean preventWrapping, final FacetHolder holder) {
+        super(numberOfLines, preventWrapping, holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedAnnotationForPropertyFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedAnnotationForPropertyFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedAnnotationForPropertyFacetFactory.java
new file mode 100644
index 0000000..06cdf45
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedAnnotationForPropertyFacetFactory.java
@@ -0,0 +1,46 @@
+/*
+ *  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.progmodel.facets.properties.notpersisted.annotation;
+
+import org.apache.isis.applib.annotation.NotPersisted;
+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.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacet;
+
+public class NotPersistedAnnotationForPropertyFacetFactory extends FacetFactoryAbstract {
+
+    public NotPersistedAnnotationForPropertyFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final NotPersisted annotation = Annotations.getAnnotation(processMethodContext.getMethod(), NotPersisted.class);
+        FacetUtil.addFacet(create(annotation, processMethodContext.getFacetHolder()));
+    }
+
+    private NotPersistedFacet create(final NotPersisted annotation, final FacetHolder holder) {
+        return annotation == null ? null : new NotPersistedFacetAnnotationForProperty(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedFacetAnnotationForProperty.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedFacetAnnotationForProperty.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedFacetAnnotationForProperty.java
new file mode 100644
index 0000000..f4716b8
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/notpersisted/annotation/NotPersistedFacetAnnotationForProperty.java
@@ -0,0 +1,31 @@
+/*
+ *  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.progmodel.facets.properties.notpersisted.annotation;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.notpersisted.NotPersistedFacetAbstract;
+
+public class NotPersistedFacetAnnotationForProperty extends NotPersistedFacetAbstract {
+
+    public NotPersistedFacetAnnotationForProperty(final FacetHolder holder) {
+        super(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthAnnotationOnPropertyFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthAnnotationOnPropertyFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthAnnotationOnPropertyFacetFactory.java
new file mode 100644
index 0000000..0b19793
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthAnnotationOnPropertyFacetFactory.java
@@ -0,0 +1,48 @@
+/*
+ *  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.progmodel.facets.properties.typicallen.annotation;
+
+import org.apache.isis.applib.annotation.TypicalLength;
+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.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacet;
+
+public class TypicalLengthAnnotationOnPropertyFacetFactory extends FacetFactoryAbstract {
+
+    public TypicalLengthAnnotationOnPropertyFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final TypicalLength annotation = Annotations.getAnnotation(processMethodContext.getMethod(), TypicalLength.class);
+        final TypicalLengthFacet facet = create(annotation, processMethodContext.getFacetHolder());
+
+        FacetUtil.addFacet(facet);
+    }
+
+    private TypicalLengthFacet create(final TypicalLength annotation, final FacetHolder holder) {
+        return annotation != null ? new TypicalLengthFacetAnnotationOnProperty(annotation.value(), holder) : null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthFacetAnnotationOnProperty.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthFacetAnnotationOnProperty.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthFacetAnnotationOnProperty.java
new file mode 100644
index 0000000..8b6930e
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/annotation/TypicalLengthFacetAnnotationOnProperty.java
@@ -0,0 +1,39 @@
+/*
+ *  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.progmodel.facets.properties.typicallen.annotation;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacetAbstract;
+
+public class TypicalLengthFacetAnnotationOnProperty extends TypicalLengthFacetAbstract {
+
+    private final int value;
+
+    public TypicalLengthFacetAnnotationOnProperty(final int value, final FacetHolder holder) {
+        super(holder, false);
+        this.value = value;
+    }
+
+    @Override
+    public int value() {
+        return value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromType.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromType.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromType.java
new file mode 100644
index 0000000..1635be9
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromType.java
@@ -0,0 +1,42 @@
+/*
+ *  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.progmodel.facets.properties.typicallen.fromtype;
+
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.multiline.MultiLineFacet;
+import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacet;
+import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacetAbstract;
+
+public class TypicalLengthFacetForPropertyDerivedFromType extends TypicalLengthFacetAbstract {
+
+    private final TypicalLengthFacet typicalLengthFacet;
+
+    public TypicalLengthFacetForPropertyDerivedFromType(final TypicalLengthFacet typicalLengthFacet, final FacetHolder holder) {
+        super(holder, true);
+        this.typicalLengthFacet = typicalLengthFacet;
+    }
+
+    @Override
+    public int value() {
+        final MultiLineFacet facet = getFacetHolder().getFacet(MultiLineFacet.class);
+        return facet.numberOfLines() * typicalLengthFacet.value();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory.java
new file mode 100644
index 0000000..b87c0ee
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/typicallen/fromtype/TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory.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.progmodel.facets.properties.typicallen.fromtype;
+
+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.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.facets.FacetedMethod;
+import org.apache.isis.core.metamodel.facets.typicallen.TypicalLengthFacet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory extends FacetFactoryAbstract {
+
+    public TypicalLengthFacetForPropertyDerivedFromTypeFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        final Class<?> type = processMethodContext.getMethod().getReturnType();
+        final FacetedMethod facetHolder = processMethodContext.getFacetHolder();
+        addFacetDerivedFromTypeIfPresent(facetHolder, type);
+    }
+
+    private void addFacetDerivedFromTypeIfPresent(final FacetHolder holder, final Class<?> type) {
+        final TypicalLengthFacet facet = getTypicalLengthFacet(type);
+        if (facet != null) {
+            FacetUtil.addFacet(new TypicalLengthFacetForPropertyDerivedFromType(facet, holder));
+        }
+    }
+
+    private TypicalLengthFacet getTypicalLengthFacet(final Class<?> type) {
+        final ObjectSpecification paramTypeSpec = getSpecificationLoader().loadSpecification(type);
+        return paramTypeSpec.getFacet(TypicalLengthFacet.class);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateDefaultFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateDefaultFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateDefaultFacetFactory.java
new file mode 100644
index 0000000..d373e14
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateDefaultFacetFactory.java
@@ -0,0 +1,58 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+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.facets.FacetFactory;
+import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
+import org.apache.isis.core.metamodel.specloader.facetprocessor.FacetProcessor;
+
+/**
+ * Simply installs a {@link PropertyValidateFacet} onto all properties.
+ * 
+ * <p>
+ * The idea is that this {@link FacetFactory} is included early on in the
+ * {@link FacetProcessor}, but other {@link PropertyValidateFacet}
+ * implementations will potentially replace these where the property is
+ * annotated or otherwise provides a validation mechanism.
+ */
+public class PropertyValidateDefaultFacetFactory extends FacetFactoryAbstract {
+
+    public PropertyValidateDefaultFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+        FacetUtil.addFacet(create(processMethodContext.getFacetHolder()));
+    }
+
+    @Override
+    public void processParams(final ProcessParameterContext processParameterContext) {
+        FacetUtil.addFacet(create(processParameterContext.getFacetHolder()));
+    }
+
+    private PropertyValidateFacet create(final FacetHolder holder) {
+        return new PropertyValidateFacetDefault(holder);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacet.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacet.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacet.java
new file mode 100644
index 0000000..8dffcd2
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacet.java
@@ -0,0 +1,50 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacet;
+import org.apache.isis.core.metamodel.facets.properties.modify.PropertySetterFacetAbstract;
+import org.apache.isis.core.metamodel.interactions.ValidatingInteractionAdvisor;
+
+/**
+ * The mechanism by which the proposed value of a property can be validated,
+ * called immediately before {@link PropertySetterFacetAbstract setting the
+ * value}.
+ * 
+ * <p>
+ * In the standard Apache Isis Programming Model, corresponds to invoking the
+ * <tt>validateXxx</tt> method for a property with an accessor of
+ * <tt>getXxx</tt>.
+ * 
+ * @see PropertySetterFacet
+ */
+
+public interface PropertyValidateFacet extends Facet, ValidatingInteractionAdvisor {
+
+    /**
+     * The reason why the proposed value is invalid.
+     * 
+     * <p>
+     * Should return <tt>null</tt> if the value is in fact valid.
+     */
+    public String invalidReason(ObjectAdapter targetObject, ObjectAdapter proposedValue);
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetAbstract.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetAbstract.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetAbstract.java
new file mode 100644
index 0000000..96ee2d7
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetAbstract.java
@@ -0,0 +1,47 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+import org.apache.isis.applib.events.ValidityEvent;
+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.interactions.PropertyModifyContext;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
+
+public abstract class PropertyValidateFacetAbstract extends FacetAbstract implements PropertyValidateFacet {
+
+    public static Class<? extends Facet> type() {
+        return PropertyValidateFacet.class;
+    }
+
+    public PropertyValidateFacetAbstract(final FacetHolder holder) {
+        super(type(), holder, Derivation.NOT_DERIVED);
+    }
+
+    @Override
+    public String invalidates(final ValidityContext<? extends ValidityEvent> context) {
+        if (!(context instanceof PropertyModifyContext)) {
+            return null;
+        }
+        final PropertyModifyContext propertyModifyContext = (PropertyModifyContext) context;
+        return invalidReason(propertyModifyContext.getTarget(), propertyModifyContext.getProposed());
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetDefault.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetDefault.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetDefault.java
new file mode 100644
index 0000000..fc59e19
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetDefault.java
@@ -0,0 +1,48 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+import org.apache.isis.applib.events.ValidityEvent;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.interactions.ValidityContext;
+
+/**
+ * Non checking property validation facet that provides default behaviour for
+ * all properties.
+ */
+public class PropertyValidateFacetDefault extends FacetAbstract implements PropertyValidateFacet {
+
+    @Override
+    public String invalidates(final ValidityContext<? extends ValidityEvent> ic) {
+        return null;
+    }
+
+    public PropertyValidateFacetDefault(final FacetHolder holder) {
+        super(PropertyValidateFacet.class, holder, Derivation.NOT_DERIVED);
+    }
+
+    @Override
+    public String invalidReason(final ObjectAdapter target, final ObjectAdapter proposedValue) {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetFactory.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetFactory.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetFactory.java
new file mode 100644
index 0000000..562edbb
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetFactory.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.progmodel.facets.properties.validate;
+
+import java.lang.reflect.Method;
+
+import org.apache.isis.core.commons.lang.NameUtils;
+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.methodutils.MethodScope;
+import org.apache.isis.core.progmodel.facets.MethodFinderUtils;
+import org.apache.isis.core.progmodel.facets.MethodPrefixBasedFacetFactoryAbstract;
+import org.apache.isis.core.progmodel.facets.MethodPrefixConstants;
+
+public class PropertyValidateFacetFactory extends MethodPrefixBasedFacetFactoryAbstract {
+
+    private static final String[] PREFIXES = { MethodPrefixConstants.VALIDATE_PREFIX };
+
+    public PropertyValidateFacetFactory() {
+        super(FeatureType.PROPERTIES_ONLY, OrphanValidation.VALIDATE, PREFIXES);
+    }
+
+    @Override
+    public void process(final ProcessMethodContext processMethodContext) {
+
+        attachValidateFacetIfValidateMethodIsFound(processMethodContext);
+    }
+
+    private void attachValidateFacetIfValidateMethodIsFound(final ProcessMethodContext processMethodContext) {
+
+        final Method getMethod = processMethodContext.getMethod();
+        final String capitalizedName = NameUtils.javaBaseName(getMethod.getName());
+
+        final Class<?> returnType = getMethod.getReturnType();
+        final Class<?>[] paramTypes = new Class[] { returnType };
+
+        final Class<?> cls = processMethodContext.getCls();
+        final Method method = MethodFinderUtils.findMethod(cls, MethodScope.OBJECT, MethodPrefixConstants.VALIDATE_PREFIX + capitalizedName, String.class, paramTypes);
+        if (method == null) {
+            return;
+        }
+        processMethodContext.removeMethod(method);
+
+        final FacetHolder property = processMethodContext.getFacetHolder();
+        FacetUtil.addFacet(new PropertyValidateFacetViaMethod(method, property));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetNone.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetNone.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetNone.java
new file mode 100644
index 0000000..19a4c6f
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetNone.java
@@ -0,0 +1,47 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+
+public class PropertyValidateFacetNone extends PropertyValidateFacetAbstract {
+
+    public PropertyValidateFacetNone(final FacetHolder holder) {
+        super(holder);
+    }
+
+    /**
+     * Returns <tt>null</tt>, ie property is valid.
+     * 
+     * <p>
+     * Subclasses should override as required.
+     */
+    @Override
+    public String invalidReason(final ObjectAdapter inObject, final ObjectAdapter value) {
+        return null;
+    }
+
+    @Override
+    public boolean isNoop() {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/e4735c72/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
----------------------------------------------------------------------
diff --git a/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
new file mode 100644
index 0000000..0df3e71
--- /dev/null
+++ b/framework/core/metamodel/src/main/java/org/apache/isis/core/progmodel/facets/properties/validate/PropertyValidateFacetViaMethod.java
@@ -0,0 +1,69 @@
+/*
+ *  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.progmodel.facets.properties.validate;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.adapter.util.AdapterInvokeUtils;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+
+public class PropertyValidateFacetViaMethod extends PropertyValidateFacetAbstract implements ImperativeFacet {
+
+    private final Method method;
+
+    public PropertyValidateFacetViaMethod(final Method method, final FacetHolder holder) {
+        super(holder);
+        this.method = method;
+    }
+
+    /**
+     * Returns a singleton list of the {@link Method} provided in the
+     * constructor.
+     */
+    @Override
+    public List<Method> getMethods() {
+        return Collections.singletonList(method);
+    }
+
+    @Override
+    public boolean impliesResolve() {
+        return true;
+    }
+
+    @Override
+    public boolean impliesObjectChanged() {
+        return false;
+    }
+
+    @Override
+    public String invalidReason(final ObjectAdapter owningAdapter, final ObjectAdapter proposedAdapter) {
+        return (String) AdapterInvokeUtils.invoke(method, owningAdapter, proposedAdapter);
+    }
+
+    @Override
+    protected String toStringValues() {
+        return "method=" + method;
+    }
+
+}