You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2021/09/02 16:00:09 UTC

[isis] 02/02: ISIS-2774: more rigorous TitleFacet validation/ conflict detection

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

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 9766d0f4f89234172d4f9215ae80030cc34cfcbd
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Sep 2 17:59:56 2021 +0200

    ISIS-2774: more rigorous TitleFacet validation/ conflict detection
---
 .../facets/object/title/TitleFacetAbstract.java    |  32 +++++
 .../annotation/TitleAnnotationFacetFactory.java    | 117 +++++++++++-------
 .../annotation/TitleFacetViaTitleAnnotation.java   | 136 ++++++++++++---------
 .../TitleAnnotationFacetFactoryTest.java           |   6 +-
 .../TitleFacetViaTitleAnnotationTest.java          |  24 ++--
 .../promptStyle/ActionLayoutPromptStyleVm.java     |   2 +-
 6 files changed, 200 insertions(+), 117 deletions(-)

diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/TitleFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/TitleFacetAbstract.java
index a43df42..9e766d7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/TitleFacetAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/TitleFacetAbstract.java
@@ -19,9 +19,15 @@
 
 package org.apache.isis.core.metamodel.facets.object.title;
 
+import java.util.Objects;
+
 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.ImperativeFacet;
+
+import lombok.NonNull;
+import lombok.val;
 
 public abstract class TitleFacetAbstract
 extends FacetAbstract
@@ -39,4 +45,30 @@ implements TitleFacet {
         super(type(), holder, precedence);
     }
 
+    @Override
+    public boolean semanticEquals(final @NonNull Facet other) {
+
+        // equality by facet-type and java-methods
+
+        if(!this.facetType().equals(other.facetType())) {
+            return false;
+        }
+
+        val otherFacet = (TitleFacet)other;
+
+        if(Objects.equals(this, otherFacet)) {
+            return true;
+        }
+
+        if(this instanceof ImperativeFacet
+                && otherFacet instanceof ImperativeFacet) {
+
+            return ((ImperativeFacet)this)
+                    .getMethods()
+                    .equals(((ImperativeFacet)otherFacet).getMethods());
+        }
+
+        return false;
+    }
+
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
index dc74a6f..6e614e8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleAnnotationFacetFactory.java
@@ -26,33 +26,25 @@ import java.util.stream.Collectors;
 
 import javax.inject.Inject;
 
-import org.apache.isis.applib.annotation.Introspection.IntrospectionPolicy;
 import org.apache.isis.applib.annotation.Title;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
-import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.core.metamodel.context.MetaModelContext;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
-import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facetapi.MetaModelRefiner;
 import org.apache.isis.core.metamodel.facets.Annotations;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.fallback.FallbackFacetFactory;
+import org.apache.isis.core.metamodel.facets.object.title.TitleFacet;
 import org.apache.isis.core.metamodel.facets.object.title.methods.TitleFacetViaMethodsFactory;
-import org.apache.isis.core.metamodel.methods.MethodFinderOptions;
-import org.apache.isis.core.metamodel.methods.MethodFinderUtils;
-import org.apache.isis.core.metamodel.methods.MethodLiteralConstants;
 import org.apache.isis.core.metamodel.progmodel.ProgrammingModel;
-import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract;
 import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
 
 public class TitleAnnotationFacetFactory
 extends FacetFactoryAbstract
 implements MetaModelRefiner {
 
-    private static final String TITLE_METHOD_NAME = "title";
-
     @Inject
     public TitleAnnotationFacetFactory(final MetaModelContext mmc) {
         super(mmc, FeatureType.OBJECTS_ONLY);
@@ -67,15 +59,17 @@ implements MetaModelRefiner {
         final Class<?> cls = processClassContext.getCls();
         final FacetHolder facetHolder = processClassContext.getFacetHolder();
 
-        final List<Annotations.Evaluator<Title>> evaluators = Annotations.getEvaluators(cls, Title.class);
+        final var evaluators = Annotations.getEvaluators(cls, Title.class);
         if (evaluators.isEmpty()) {
             return;
         }
 
         sort(evaluators);
-        final List<TitleFacetViaTitleAnnotation.TitleComponent> titleComponents =
-                _Lists.map(evaluators, TitleFacetViaTitleAnnotation.TitleComponent.FROM_EVALUATORS);
-        FacetUtil.addFacet(new TitleFacetViaTitleAnnotation(titleComponents, facetHolder));
+        final var titleComponents =
+                Can.ofCollection(evaluators)
+                .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
+
+        addFacet(new TitleFacetViaTitleAnnotation(titleComponents, facetHolder));
     }
 
     public static void sort(final List<Annotations.Evaluator<Title>> evaluators) {
@@ -159,49 +153,84 @@ implements MetaModelRefiner {
     @Override
     public void refineProgrammingModel(final ProgrammingModel programmingModel) {
 
-        programmingModel.addVisitingValidatorSkipManagedBeans(_objectSpec -> {
+        programmingModel.addVisitingValidatorSkipManagedBeans(objectSpec -> {
 
-            final var objectSpec = (ObjectSpecificationAbstract)_objectSpec;
-            final var cls = objectSpec.getCorrespondingClass();
-            final var introspectionPolicy = objectSpec.getIntrospectionPolicy();
+//            final var objectSpec = (ObjectSpecificationAbstract)_objectSpec;
+//            final var cls = objectSpec.getCorrespondingClass();
+//            final var introspectionPolicy = objectSpec.getIntrospectionPolicy();
 
-            final var titleMethod = MethodFinderUtils.findMethod(
-                    MethodFinderOptions.objectSupport(introspectionPolicy),
-                    cls, TITLE_METHOD_NAME, String.class, null);
-            if (titleMethod == null) {
-                return;
-            }
+            final var titleFacetTopRank =
+                objectSpec
+                .getFacetRanking(TitleFacet.class)
+                .map(facetRanking->facetRanking.getTopRank(TitleFacet.class))
+                .orElse(Can.empty())
+                .unique(TitleFacet::semanticEquals);
 
-            // determine if cls contains an @Title annotated method, not inherited from superclass
-            final ObjectSpecification superSpec = objectSpec.superclass();
-            if (superSpec == null) {
-                return;
-            }
+            // top-rank if present must not be ambiguous
+            if(titleFacetTopRank.isCardinalityMultiple()) {
 
-            final var superIntrospectionPolicy = ((ObjectSpecificationAbstract)superSpec).getIntrospectionPolicy();
-            final var superCls = superSpec.getCorrespondingClass();
+                final var conflictingFeatures =
+                        titleFacetTopRank
+                        .map(TitleFacet::getClass)
+                        .map(Class::getSimpleName)
+                        .toList();
 
-            if (countMethodsWithTitleAnnotation(introspectionPolicy, cls)
-                    > countMethodsWithTitleAnnotation(superIntrospectionPolicy, superCls)) {
                 ValidationFailure.raiseFormatted(
                         objectSpec,
                         "%s: conflict for determining a strategy for retrieval of title for class, "
-                        + "contains a method '%s' and an annotation '@%s'",
+                        + "conflicting title facets %s",
                         objectSpec.getFeatureIdentifier().getClassName(),
-                        TITLE_METHOD_NAME,
-                        Title.class.getName());
+                        conflictingFeatures.toString());
+
             }
 
+
+
+//
+//            final var titleMethod = MethodFinderUtils.findMethod(
+//                    MethodFinderOptions.objectSupport(introspectionPolicy),
+//                    cls, TITLE_METHOD_NAME, String.class, null);
+//            if (titleMethod == null) {
+//                return;
+//            }
+//
+//            // determine if cls contains an @Title annotated method, not inherited from superclass
+//            final ObjectSpecification superSpec = objectSpec.superclass();
+//            if (superSpec == null) {
+//                return;
+//            }
+//
+//            final var superIntrospectionPolicy = ((ObjectSpecificationAbstract)superSpec).getIntrospectionPolicy();
+//            final var superCls = superSpec.getCorrespondingClass();
+//
+//            //FIXME[ISIS-2774] also count declared fields that are @Title annotated
+//            if (countMethodsWithTitleAnnotation(introspectionPolicy, cls)
+//                    > 1L
+//                    //countMethodsWithTitleAnnotation(superIntrospectionPolicy, superCls)
+//                    ) {
+//                ValidationFailure.raiseFormatted(
+//                        objectSpec,
+//                        "%s: conflict for determining a strategy for retrieval of title for class, "
+//                        + "contains a method '%s' and an annotation '@%s' on a different members",
+//                        objectSpec.getFeatureIdentifier().getClassName(),
+//                        TITLE_METHOD_NAME,
+//                        Title.class.getName());
+//            }
+
         });
     }
 
-    private static long countMethodsWithTitleAnnotation(
-            final IntrospectionPolicy introspectionPolicy,
-            final Class<?> cls) {
-        return MethodFinderUtils.streamMethodsWithAnnotation(
-                MethodFinderOptions.objectSupport(introspectionPolicy), cls, Title.class)
-                .filter(method->!method.getName().equals(MethodLiteralConstants.TITLE))
-                .count();
-    }
+//    private static long countMethodsWithTitleAnnotation(
+//            final IntrospectionPolicy introspectionPolicy,
+//            final Class<?> cls) {
+//        return MethodFinderUtils.streamMethodsWithAnnotation(
+//                MethodFinderOptions.objectSupport(introspectionPolicy), cls, Title.class)
+//                // don't count methods that identify as title() methods
+//                .filter(method->
+//                        !
+//                        (method.getName().equals(MethodLiteralConstants.TITLE)
+//                                && method.getParameterCount() == 0))
+//                .count();
+//    }
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
index 151df37..d6fcdbb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/title/annotation/TitleFacetViaTitleAnnotation.java
@@ -19,85 +19,60 @@
 
 package org.apache.isis.core.metamodel.facets.object.title.annotation;
 
+import java.lang.reflect.Method;
 import java.util.List;
 import java.util.function.BiConsumer;
-import java.util.function.Function;
 import java.util.function.Predicate;
 
 import org.apache.isis.applib.annotation.Title;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.commons.internal.base._Strings;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.functions._Predicates;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.Annotations;
+import org.apache.isis.core.metamodel.facets.Annotations.MethodEvaluator;
+import org.apache.isis.core.metamodel.facets.ImperativeFacet;
 import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 
+import lombok.Getter;
+import lombok.NonNull;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
 @Log4j2
 public class TitleFacetViaTitleAnnotation
-extends TitleFacetAbstract {
+extends TitleFacetAbstract
+implements ImperativeFacet {
 
-    private final List<TitleComponent> components;
+    @Getter private final Can<TitleComponent> components;
 
-    public static class TitleComponent {
-        public static final Function<Annotations.Evaluator<Title>, TitleComponent> FROM_EVALUATORS =
-                titleEvaluator -> TitleComponent.of(titleEvaluator);
-
-                private final String prepend;
-                private final String append;
-                private final Annotations.Evaluator<Title> titleEvaluator;
-                private final int abbreviateTo;
-
-                private TitleComponent(final String prepend, final String append, final Annotations.Evaluator<Title> titleEvaluator, final int abbreviateTo) {
-                    super();
-                    this.prepend = prepend;
-                    this.append = append;
-                    this.titleEvaluator = titleEvaluator;
-                    this.abbreviateTo = abbreviateTo;
-                }
-
-                public String getPrepend() {
-                    return prepend;
-                }
-
-                public String getAppend() {
-                    return append;
-                }
-
-                public Annotations.Evaluator<Title> getTitleEvaluator() {
-                    return titleEvaluator;
-                }
+    @Getter(onMethod_ = {@Override}) private final @NonNull Can<Method> methods;
 
-                private static TitleComponent of(final Annotations.Evaluator<Title> titleEvaluator) {
-                    final Title annotation = titleEvaluator.getAnnotation();
-                    final String prepend = annotation != null ? annotation.prepend() : " ";
-                    final String append = annotation != null ? annotation.append() : "";
-                    final int abbreviateTo = annotation != null ? annotation.abbreviatedTo() : Integer.MAX_VALUE;
-                    return new TitleComponent(prepend, append, titleEvaluator, abbreviateTo);
-                }
+    public TitleFacetViaTitleAnnotation(final Can<TitleComponent> components, final FacetHolder holder) {
+        super(holder);
+        this.components = components;
 
-                @Override
-                public String toString() {
-                    final List<String> parts = _Lists.newArrayList();
-                    if(prepend != null && !_Strings.isNullOrEmpty(prepend.trim())) {
-                        parts.add("prepend=" + prepend);
-                    }
-                    if(append != null && !_Strings.isNullOrEmpty(append.trim())) {
-                        parts.add("append=" + append);
-                    }
-                    if(abbreviateTo != Integer.MAX_VALUE) {
-                        parts.add("abbreviateTo=" + abbreviateTo);
-                    }
-                    return String.join(";", parts);
-                }
+        // if there is just a single component and it happens to be a method (not a field)
+        // we can use imperative facet semantics which allows for TitleFacets to be compared by
+        // TitleFacetAbstract#semanticEquals(..) in support of more rigorous MM validation
+        this.methods = components.isCardinalityOne()
+                ? components
+                    .stream()
+                    .map(TitleComponent::getTitleEvaluator)
+                    .filter(MethodEvaluator.class::isInstance)
+                    .map(MethodEvaluator.class::cast)
+                    .map(MethodEvaluator::getMethod)
+                    .findFirst()
+                    .map(ImperativeFacet::singleMethod)
+                    .orElse(Can.empty())
+                : Can.empty();
     }
 
-    public TitleFacetViaTitleAnnotation(final List<TitleComponent> components, final FacetHolder holder) {
-        super(holder);
-        this.components = components;
+    @Override
+    public Intent getIntent(final Method method) {
+        return Intent.UI_HINT;
     }
 
     @Override
@@ -112,10 +87,6 @@ extends TitleFacetAbstract {
         return adapter.titleString();
     }
 
-    public List<TitleComponent> getComponents() {
-        return components;
-    }
-
     private static String abbreviated(final String str, final int maxLength) {
         return str.length() < maxLength ? str : str.substring(0, maxLength - 3) + "...";
     }
@@ -171,8 +142,53 @@ extends TitleFacetAbstract {
     @Override
     public void visitAttributes(final BiConsumer<String, Object> visitor) {
         super.visitAttributes(visitor);
-        if(components != null && !_Strings.isNullOrEmpty(components.toString())) {
+        if(components != null && _Strings.isNotEmpty(components.toString())) {
             visitor.accept("components", components);
         }
     }
+
+    // -- HELPER
+
+    public static class TitleComponent {
+
+        public static TitleComponent of(final Annotations.Evaluator<Title> titleEvaluator) {
+            final Title annotation = titleEvaluator.getAnnotation();
+            final String prepend = annotation != null ? annotation.prepend() : " ";
+            final String append = annotation != null ? annotation.append() : "";
+            final int abbreviateTo = annotation != null ? annotation.abbreviatedTo() : Integer.MAX_VALUE;
+            return new TitleComponent(prepend, append, titleEvaluator, abbreviateTo);
+        }
+
+        @Getter private final String prepend;
+        @Getter private final String append;
+        @Getter private final Annotations.Evaluator<Title> titleEvaluator;
+        private final int abbreviateTo;
+
+        private TitleComponent(
+                final String prepend,
+                final String append,
+                final Annotations.Evaluator<Title> titleEvaluator,
+                final int abbreviateTo) {
+            super();
+            this.prepend = prepend;
+            this.append = append;
+            this.titleEvaluator = titleEvaluator;
+            this.abbreviateTo = abbreviateTo;
+        }
+
+        @Override
+        public String toString() {
+            final List<String> parts = _Lists.newArrayList();
+            if(prepend != null && !_Strings.isNullOrEmpty(prepend.trim())) {
+                parts.add("prepend=" + prepend);
+            }
+            if(append != null && !_Strings.isNullOrEmpty(append.trim())) {
+                parts.add("append=" + append);
+            }
+            if(abbreviateTo != Integer.MAX_VALUE) {
+                parts.add("abbreviateTo=" + abbreviateTo);
+            }
+            return String.join(";", parts);
+        }
+    }
 }
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
index 23e0beb..f614d09 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleAnnotationFacetFactoryTest.java
@@ -86,7 +86,8 @@ extends AbstractFacetFactoryJUnit4TestCase {
 
         final List<Method> titleMethods = Arrays.asList(Customer.class.getMethod("someTitle"));
         for (int i = 0; i < titleMethods.size(); i++) {
-            final Annotations.MethodEvaluator<Title> titleEvaluator = (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().get(i)
+            final Annotations.MethodEvaluator<Title> titleEvaluator =
+                    (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
                     .getTitleEvaluator();
 
             Assert.assertEquals(titleMethods.get(i),
@@ -129,7 +130,8 @@ extends AbstractFacetFactoryJUnit4TestCase {
 
         //final List<TitleComponent> components = titleFacetViaTitleAnnotation.getComponents();
         for (int i = 0; i < titleMethods.size(); i++) {
-            final Annotations.MethodEvaluator<Title> titleEvaluator = (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().get(i)
+            final Annotations.MethodEvaluator<Title> titleEvaluator =
+                    (Annotations.MethodEvaluator<Title>) titleFacetViaTitleAnnotation.getComponents().getElseFail(i)
                     .getTitleEvaluator();
 
             Assert.assertEquals(titleMethods.get(i),
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
index e18dc5b..0bdde4d 100644
--- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/facets/object/ident/title/annotation/TitleFacetViaTitleAnnotationTest.java
@@ -28,8 +28,11 @@ import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
 import org.apache.isis.applib.annotation.Title;
-import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.commons.collections.Can;
 import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2;
 import org.apache.isis.core.internaltestsupport.jmocking.JUnitRuleMockery2.Mode;
 import org.apache.isis.core.metamodel._testing.MetaModelContext_forTesting;
@@ -41,8 +44,7 @@ import org.apache.isis.core.metamodel.facets.object.title.annotation.TitleFacetV
 import org.apache.isis.core.metamodel.objectmanager.ObjectManager;
 import org.apache.isis.core.metamodel.spec.ManagedObject;
 
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
+import lombok.val;
 
 public class TitleFacetViaTitleAnnotationTest {
 
@@ -54,7 +56,7 @@ public class TitleFacetViaTitleAnnotationTest {
     @Mock private ObjectManager mockObjectManager;
 
     protected MetaModelContext metaModelContext;
-    
+
     protected static class DomainObjectWithProblemInItsAnnotatedTitleMethod {
 
         @Title
@@ -98,16 +100,17 @@ public class TitleFacetViaTitleAnnotationTest {
 
         TitleAnnotationFacetFactory.sort(evaluatorList);
 
-        final List<TitleFacetViaTitleAnnotation.TitleComponent> components = _Lists.map(evaluatorList, TitleFacetViaTitleAnnotation.TitleComponent.FROM_EVALUATORS);
+        val components = Can.ofCollection(evaluatorList)
+                .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
         final TitleFacetViaTitleAnnotation facet = new TitleFacetViaTitleAnnotation(components, mockFacetHolder);
         final NormalDomainObject normalPojo = new NormalDomainObject();
         final Sequence sequence = context.sequence("in-title-element-order");
         context.checking(new Expectations() {
             {
-                
+
                 allowing(mockFacetHolder).getMetaModelContext();
                 will(returnValue(metaModelContext));
-                
+
                 allowing(mockManagedObject).getPojo();
                 will(returnValue(normalPojo));
 
@@ -132,15 +135,16 @@ public class TitleFacetViaTitleAnnotationTest {
         final List<Annotations.Evaluator<Title>> evaluators = Annotations
                 .getEvaluators(DomainObjectWithProblemInItsAnnotatedTitleMethod.class, Title.class);
 
-        final List<TitleFacetViaTitleAnnotation.TitleComponent> components = _Lists.map(evaluators, TitleFacetViaTitleAnnotation.TitleComponent.FROM_EVALUATORS);
+        val components = Can.ofCollection(evaluators)
+                .map(TitleFacetViaTitleAnnotation.TitleComponent::of);
         final TitleFacetViaTitleAnnotation facet = new TitleFacetViaTitleAnnotation(components, mockFacetHolder);
         final DomainObjectWithProblemInItsAnnotatedTitleMethod screwedPojo = new DomainObjectWithProblemInItsAnnotatedTitleMethod();
         context.checking(new Expectations() {
             {
-                
+
                 allowing(mockFacetHolder).getMetaModelContext();
                 will(returnValue(metaModelContext));
-                
+
                 allowing(mockManagedObject).getPojo();
                 will(returnValue(screwedPojo));
             }
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/ActionLayout/promptStyle/ActionLayoutPromptStyleVm.java b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/ActionLayout/promptStyle/ActionLayoutPromptStyleVm.java
index 88ceff5..fbb4f87 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/ActionLayout/promptStyle/ActionLayoutPromptStyleVm.java
+++ b/examples/demo/domain/src/main/java/demoapp/dom/domain/actions/ActionLayout/promptStyle/ActionLayoutPromptStyleVm.java
@@ -52,7 +52,7 @@ public class ActionLayoutPromptStyleVm implements HasAsciiDocDescription {
         return "ActionLayout#promptStyle";
     }
 
-    @Title
+    //@Title //TODO is in conflict with the above, which one shall it be?
     @Property(editing = Editing.DISABLED)
     @PropertyLayout(fieldSetId = "general", sequence = "1")
     @XmlElement(required = true)