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 2015/11/13 18:57:19 UTC

[08/11] isis git commit: ISIS-1252: new abstract UiEvent hierarchy, updates to @DomainObjectLayout annotation, support for title facet.

ISIS-1252: new abstract UiEvent hierarchy, updates to @DomainObjectLayout annotation, support for title facet.


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

Branch: refs/heads/master
Commit: ffb62e9a0f4f153fe8c72b0f26da03b7e4269ad9
Parents: b17dc0e
Author: Dan Haywood <da...@haywood-associates.co.uk>
Authored: Fri Nov 13 13:40:09 2015 +0000
Committer: Dan Haywood <da...@haywood-associates.co.uk>
Committed: Fri Nov 13 13:40:09 2015 +0000

----------------------------------------------------------------------
 .../applib/annotation/DomainObjectLayout.java   |  48 ++++++++-
 .../services/eventbus/AbstractUiEvent.java      |  97 +++++++++++++++++
 .../services/eventbus/CssClassFaUiEvent.java    | 108 +++++++++++++++++++
 .../services/eventbus/CssClassUiEvent.java      |  79 ++++++++++++++
 .../applib/services/eventbus/IconUiEvent.java   |  77 +++++++++++++
 .../applib/services/eventbus/TitleUiEvent.java  | 106 ++++++++++++++++++
 .../DomainObjectLayoutFacetFactory.java         |  16 ++-
 ...ObjectLayoutAnnotationUsingTitleUiEvent.java | 108 +++++++++++++++++++
 .../dflt/ProgrammingModelFacetsJava5.java       |   6 +-
 9 files changed, 640 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObjectLayout.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObjectLayout.java b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObjectLayout.java
index d4e8789..535248d 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObjectLayout.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/annotation/DomainObjectLayout.java
@@ -25,6 +25,11 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import org.apache.isis.applib.services.eventbus.CssClassFaUiEvent;
+import org.apache.isis.applib.services.eventbus.CssClassUiEvent;
+import org.apache.isis.applib.services.eventbus.IconUiEvent;
+import org.apache.isis.applib.services.eventbus.TitleUiEvent;
+
 /**
  * Layout hints for domain objects.
  */
@@ -33,6 +38,38 @@ import java.lang.annotation.Target;
 @Retention(RetentionPolicy.RUNTIME)
 public @interface DomainObjectLayout {
 
+
+    /**
+     * Which subclass of {@link TitleUiEvent} should be used to obtain a title.
+     *
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     * </p>
+     */
+    Class<? extends TitleUiEvent<?>> titleUiEvent() default TitleUiEvent.Default.class;
+
+    // //////////////////////////////////////
+
+    /**
+     * Which subclass of {@link IconUiEvent} should be used to obtain an icon.
+     *
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     * </p>
+     */
+    Class<? extends IconUiEvent<?>> iconUiEvent() default IconUiEvent.Default.class;
+
+    // //////////////////////////////////////
+
+    /**
+     * Which subclass of {@link CssClassUiEvent} should be used to obtain a CSS class.
+     *
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     * </p>
+     */
+    Class<? extends CssClassUiEvent<?>> cssClassUiEvent() default CssClassUiEvent.Default.class;
+
     /**
      * Indicates the css class that a domain class (type) should have.
      */
@@ -41,13 +78,20 @@ public @interface DomainObjectLayout {
     // //////////////////////////////////////
 
     /**
+     * Which subclass of {@link CssClassFaUiEvent} should be used to obtain a CSS font-awesome class and position.
+     *
+     * <p>
+     * This subclass must provide a no-arg constructor; the fields are set reflectively.
+     * </p>
+     */
+    Class<? extends CssClassFaUiEvent<?>> cssClassFaUiEvent() default CssClassFaUiEvent.Default.class;
+
+    /**
      * Indicates the <a href="http://fortawesome.github.io/Font-Awesome/">Font Awesome</a> CSS class to decorate an
      * domain object.
      */
     String cssClassFa() default "";
 
-    // //////////////////////////////////////
-
     /**
      * Indicates the position of the <a href="http://fortawesome.github.io/Font-Awesome/">Font Awesome</a>
      * icon. The icon could be rendered on the left or the right of the object's title.

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractUiEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractUiEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractUiEvent.java
new file mode 100644
index 0000000..c0f74af
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/AbstractUiEvent.java
@@ -0,0 +1,97 @@
+/*
+ *  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.applib.services.eventbus;
+
+import java.util.EventObject;
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.apache.isis.applib.util.ObjectContracts;
+
+public abstract class AbstractUiEvent<S> extends EventObject {
+
+    private static final long serialVersionUID = 1L;
+
+    //region > constructors
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public AbstractUiEvent() {
+        this(null);
+    }
+
+    public AbstractUiEvent(final S source) {
+        super(sourceElseDummy(source));
+    }
+
+    private static Object sourceElseDummy(final Object source) {
+        return source != null ? source : new Object();
+    }
+    //endregion
+
+    //region > source
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public S getSource() {
+        return (S)source;
+    }
+
+    /**
+     * Not API, set by the framework if the no-arg constructor is used.
+     */
+    public void setSource(S source) {
+        this.source = source;
+    }
+
+    //endregion
+
+    //region > userData
+    /**
+     * Provides a mechanism to pass data around.
+     */
+    private final Map<Object, Object> userData = Maps.newHashMap();
+
+    /**
+     * Obtain user-data, as set by any other subscribers.
+     */
+    public Object get(Object key) {
+        return userData.get(key);
+    }
+    /**
+     * Set user-data, for the use of other subscribers.
+     */
+    public void put(Object key, Object value) {
+        userData.put(key, value);
+    }
+    //endregion
+
+    //region > toString
+    @Override
+    public String toString() {
+        return ObjectContracts.toString(this, "source");
+    }
+    //endregion
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassFaUiEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassFaUiEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassFaUiEvent.java
new file mode 100644
index 0000000..54cf2b7
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassFaUiEvent.java
@@ -0,0 +1,108 @@
+/*
+ *  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.applib.services.eventbus;
+
+import java.util.EventObject;
+
+import org.apache.isis.applib.annotation.DomainObjectLayout;
+
+/**
+ * Emitted for subscribers to obtain a cssClassFa hint (equivalent to the {@link DomainObjectLayout#cssClassFa()} attribute), providing the CSS class for a font-awesome
+ * icon for this domain object.
+ */
+public abstract class CssClassFaUiEvent<S> extends AbstractUiEvent<S> {
+
+    private static final long serialVersionUID = 1L;
+
+    //region > constructors
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public CssClassFaUiEvent() {
+        this(null);
+    }
+
+    public CssClassFaUiEvent(final S source) {
+        super(source);
+    }
+
+    //endregion
+
+    //region > Default class
+
+    /**
+     * Propagated if no custom subclass was specified using
+     * {@link org.apache.isis.applib.annotation.DomainObjectLayout#iconUiEvent()} annotation attribute.
+     */
+    public static class Default extends CssClassFaUiEvent<Object> {
+        private static final long serialVersionUID = 1L;
+    }
+    //endregion
+
+    //region > cssClassFa
+    private String cssClassFa;
+
+    /**
+     * The CSS class for a font-awesome icon for this domain object, as provided by a subscriber using {@link #setCssClassFa(String)}.
+     */
+    public String getCssClassFa() {
+        return cssClassFa;
+    }
+
+
+    /**
+     * For subscribers to call to provide a CSS class for a font-awesome icon for this object.
+     */
+    public void setCssClassFa(final String cssClass) {
+        this.cssClassFa = cssClass;
+    }
+    //endregion
+
+    //region > cssClassFaPosition
+    private DomainObjectLayout.CssClassFaPosition cssClassFaPosition;
+
+    /**
+     * The {@link DomainObjectLayout.CssClassFaPosition position} as provided by a subscriber using {@link #setCssClassFaPosition(org.apache.isis.applib.annotation.DomainObjectLayout.CssClassFaPosition)}.
+     *
+     * <p>
+     *     This attribute is currently ignored by Isis viewers.
+     * </p>
+     */
+    public DomainObjectLayout.CssClassFaPosition getCssClassFaPosition() {
+        return cssClassFaPosition;
+    }
+
+    /**
+     * For subscribers to call to provide the positioning of the font-awesome icon for this object.
+     *
+     * <p>
+     *     This attribute is currently ignored by Isis viewers.
+     * </p>
+     */
+    public void setCssClassFaPosition(
+            final DomainObjectLayout.CssClassFaPosition cssClassFaPosition) {
+        this.cssClassFaPosition = cssClassFaPosition;
+    }
+    //endregion
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassUiEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassUiEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassUiEvent.java
new file mode 100644
index 0000000..f43c603
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/CssClassUiEvent.java
@@ -0,0 +1,79 @@
+/*
+ *  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.applib.services.eventbus;
+
+import java.util.EventObject;
+
+import org.apache.isis.applib.annotation.DomainObjectLayout;
+
+/**
+ * Emitted for subscribers to obtain a cssClass hint (equivalent to the <tt>cssClass()</tt> supporting method or the {@link DomainObjectLayout#cssClass()} attribute).
+ */
+public abstract class CssClassUiEvent<S> extends AbstractUiEvent<S> {
+
+    private static final long serialVersionUID = 1L;
+
+    //region > constructors
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public CssClassUiEvent() {
+        this(null);
+    }
+
+    public CssClassUiEvent(final S source) {
+        super(source);
+    }
+
+    //endregion
+
+    //region > Default class
+
+    /**
+     * Propagated if no custom subclass was specified using
+     * {@link org.apache.isis.applib.annotation.DomainObjectLayout#iconUiEvent()} annotation attribute.
+     */
+    public static class Default extends CssClassUiEvent<Object> {
+        private static final long serialVersionUID = 1L;
+    }
+    //endregion
+
+    //region > cssClass
+    private String cssClass;
+
+    /**
+     * The CSS class as provided by a subscriber using {@link #setCssClass(String)}.
+     */
+    public String getCssClass() {
+        return cssClass;
+    }
+
+    /**
+     * For subscribers to call to provide a CSS class for this object.
+     */
+    public void setCssClass(final String cssClass) {
+        this.cssClass = cssClass;
+    }
+    //endregion
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/IconUiEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/IconUiEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/IconUiEvent.java
new file mode 100644
index 0000000..5924a95
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/IconUiEvent.java
@@ -0,0 +1,77 @@
+/*
+ *  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.applib.services.eventbus;
+
+import java.util.EventObject;
+
+/**
+ * Emitted for subscribers to obtain a cssClass hint (equivalent to the <tt>iconName()</tt> supporting method).
+ */
+public abstract class IconUiEvent<S> extends AbstractUiEvent<S> {
+
+    private static final long serialVersionUID = 1L;
+
+    //region > constructors
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public IconUiEvent() {
+        this(null);
+    }
+
+    public IconUiEvent(final S source) {
+        super(source);
+    }
+
+    //endregion
+
+    //region > Default class
+
+    /**
+     * Propagated if no custom subclass was specified using
+     * {@link org.apache.isis.applib.annotation.DomainObjectLayout#iconUiEvent()} annotation attribute.
+     */
+    public static class Default extends IconUiEvent<Object> {
+        private static final long serialVersionUID = 1L;
+    }
+    //endregion
+
+    //region > iconName
+    private String iconName;
+
+    /**
+     * The icon name as provided by a subscriber using {@link #setIconName(String)}.
+     */
+    public String getIconName() {
+        return iconName;
+    }
+
+    /**
+     * For subscribers to call to provide an icon name for this object.
+     */
+    public void setIconName(final String iconName) {
+        this.iconName = iconName;
+    }
+    //endregion
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/TitleUiEvent.java
----------------------------------------------------------------------
diff --git a/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/TitleUiEvent.java b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/TitleUiEvent.java
new file mode 100644
index 0000000..181015d
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/services/eventbus/TitleUiEvent.java
@@ -0,0 +1,106 @@
+/*
+ *  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.applib.services.eventbus;
+
+import java.util.EventObject;
+
+import org.apache.isis.applib.services.i18n.TranslatableString;
+
+/**
+ * Emitted for subscribers to obtain a cssClass hint (equivalent to the <tt>title()</tt> supporting method).
+ */
+public abstract class TitleUiEvent<S> extends AbstractUiEvent<S> {
+
+    private static final long serialVersionUID = 1L;
+
+    //region > Default class
+
+    /**
+     * Propagated if no custom subclass was specified using
+     * {@link org.apache.isis.applib.annotation.DomainObjectLayout#titleUiEvent()} annotation attribute.
+     */
+    public static class Default extends TitleUiEvent<Object> {
+        private static final long serialVersionUID = 1L;
+    }
+    //endregion
+
+    //region > constructors
+    /**
+     * If used then the framework will set state via (non-API) setters.
+     *
+     * <p>
+     *     Because the {@link EventObject} superclass prohibits a null source, a dummy value is temporarily used.
+     * </p>
+     */
+    public TitleUiEvent() {
+        this(null);
+    }
+
+    public TitleUiEvent(final S source) {
+        super(source);
+    }
+
+    //endregion
+
+    //region > title
+    private String title;
+
+    /**
+     * The title as provided by a subscriber using {@link #setTitle(String)}.
+     *
+     * <p>
+     *     Note that a {@link #getTranslatedTitle()} will be used in preference, if available.
+     * </p>
+     */
+    public String getTitle() {
+        return title;
+    }
+
+    /**
+     * For subscribers to call to provide a (non-translated) title for this object.
+     */
+    public void setTitle(final String title) {
+        this.title = title;
+    }
+    //endregion
+
+    //region > translatedTitle
+    private TranslatableString translatedTitle;
+
+    /**
+     * The translatable (i18n) title as provided by a subscriber using {@link #setTranslatedTitle(TranslatableString)}.
+     *
+     * <p>
+     *     If a translatable title has been provided then this will be used in preference to any
+     *     {@link #getTitle() non-translatable title}.
+     * </p>
+     */
+    public TranslatableString getTranslatedTitle() {
+        return translatedTitle;
+    }
+
+    /**
+     * For subscribers to call to provide a translatable (i18n) title for this object.
+     */
+    public void setTranslatedTitle(final TranslatableString translatedTitle) {
+        this.translatedTitle = translatedTitle;
+    }
+    //endregion
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/DomainObjectLayoutFacetFactory.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/DomainObjectLayoutFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/DomainObjectLayoutFacetFactory.java
index 8a7c834..088b7b3 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/DomainObjectLayoutFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/DomainObjectLayoutFacetFactory.java
@@ -23,8 +23,11 @@ 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.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjectorAware;
+
+public class DomainObjectLayoutFacetFactory extends FacetFactoryAbstract implements ServicesInjectorAware {
 
-public class DomainObjectLayoutFacetFactory extends FacetFactoryAbstract {
 
     public DomainObjectLayoutFacetFactory() {
         super(FeatureType.OBJECTS_ONLY);
@@ -40,6 +43,10 @@ public class DomainObjectLayoutFacetFactory extends FacetFactoryAbstract {
         final ViewModelLayout viewModelLayout = Annotations.getAnnotation(cls, ViewModelLayout.class);
 
         FacetUtil.addFacet(
+                TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.create(
+                        domainObjectLayout, servicesInjector, facetHolder));
+
+        FacetUtil.addFacet(
                 CssClassFacetForDomainObjectLayoutAnnotation.create(domainObjectLayout, facetHolder));
         FacetUtil.addFacet(
                 CssClassFacetForViewModelLayoutAnnotation.create(viewModelLayout, facetHolder));
@@ -77,4 +84,11 @@ public class DomainObjectLayoutFacetFactory extends FacetFactoryAbstract {
         return;
     }
 
+
+    private ServicesInjector servicesInjector;
+
+    @Override
+    public void setServicesInjector(final ServicesInjector servicesInjector) {
+        this.servicesInjector = servicesInjector;
+    }
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.java
new file mode 100644
index 0000000..55f0b0d
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobjectlayout/TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.java
@@ -0,0 +1,108 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.object.domainobjectlayout;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.isis.applib.NonRecoverableException;
+import org.apache.isis.applib.annotation.DomainObjectLayout;
+import org.apache.isis.applib.profiles.Localization;
+import org.apache.isis.applib.services.eventbus.EventBusService;
+import org.apache.isis.applib.services.eventbus.TitleUiEvent;
+import org.apache.isis.applib.services.i18n.TranslatableString;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.title.TitleFacetAbstract;
+import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+
+public class TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent extends TitleFacetAbstract {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent.class);
+
+    public static Facet create(
+            final DomainObjectLayout domainObjectLayout,
+            final ServicesInjector servicesInjector,
+            final FacetHolder facetHolder) {
+        if(domainObjectLayout == null) {
+            return null;
+        }
+        final Class<? extends TitleUiEvent<?>> titleUiEventClass = domainObjectLayout.titleUiEvent();
+
+        final TranslationService translationService = servicesInjector.lookupService(TranslationService.class);
+        final ObjectSpecification facetHolderAsSpec = (ObjectSpecification) facetHolder; // bit naughty...
+        final String translationContext = facetHolderAsSpec.getCorrespondingClass().getCanonicalName();
+        final EventBusService eventBusService = servicesInjector.lookupService(EventBusService.class);
+
+        return new TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent(
+                titleUiEventClass, translationService, translationContext, eventBusService, facetHolder);
+    }
+
+    private final Class<? extends TitleUiEvent<?>> titleUiEventClass;
+    private final TranslationService translationService;
+    private final String translationContext;
+    private final EventBusService eventBusService;
+
+    public TitleFacetViaDomainObjectLayoutAnnotationUsingTitleUiEvent(
+            final Class<? extends TitleUiEvent<?>> titleUiEventClass,
+            final TranslationService translationService,
+            final String translationContext,
+            final EventBusService eventBusService,
+            final FacetHolder holder) {
+        super(holder);
+        this.titleUiEventClass = titleUiEventClass;
+        this.translationService = translationService;
+        this.translationContext = translationContext;
+        this.eventBusService = eventBusService;
+    }
+
+    @Override
+    public String title(final ObjectAdapter owningAdapter, final Localization localization) {
+
+        final TitleUiEvent<Object> titleUiEvent = newTitleUiEvent(owningAdapter);
+
+        eventBusService.post(titleUiEvent);
+
+        final TranslatableString translatedTitle = titleUiEvent.getTranslatedTitle();
+        if(translatedTitle != null) {
+            return translatedTitle.translate(translationService, translationContext);
+        }
+        final String title = titleUiEvent.getTitle();
+        return title; // could be null
+    }
+
+    private TitleUiEvent<Object> newTitleUiEvent(final ObjectAdapter owningAdapter) {
+        final Object domainObject = owningAdapter.getObject();
+        return newTitleUiEvent(domainObject);
+    }
+
+    private TitleUiEvent<Object> newTitleUiEvent(final Object domainObject) {
+        try {
+            final TitleUiEvent<Object> titleUiEvent = (TitleUiEvent<Object>) titleUiEventClass.newInstance();
+            titleUiEvent.setSource(domainObject);
+            return titleUiEvent;
+        } catch (InstantiationException | IllegalAccessException ex) {
+            throw new NonRecoverableException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/ffb62e9a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
----------------------------------------------------------------------
diff --git a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
index 4b9c4b7..37b50d2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
+++ b/core/metamodel/src/main/java/org/apache/isis/progmodels/dflt/ProgrammingModelFacetsJava5.java
@@ -310,8 +310,6 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(ObjectValidPropertiesFacetImplFactory.class);
         addFactory(PluralFacetStaticMethodFactory.class);
         addFactory(org.apache.isis.core.metamodel.facets.object.named.staticmethod.NamedFacetStaticMethodFactory.class);
-        addFactory(TitleAnnotationFacetFactory.class);
-        addFactory(TitleFacetViaMethodsFactory.class);
 
         addFactory(MemberOrderFacetFactory.class);
         addFactory(ActionOrderFacetAnnotationFactory.class);
@@ -402,6 +400,10 @@ public final class ProgrammingModelFacetsJava5 extends ProgrammingModelAbstract
         addFactory(ActionLayoutFacetFactory.class);
         addFactory(CollectionLayoutFacetFactory.class);
 
+        // must come after DomainObjectLayoutFacetFactory
+        addFactory(TitleAnnotationFacetFactory.class);
+        addFactory(TitleFacetViaMethodsFactory.class);
+
         addFactory(NamedFacetOnTypeAnnotationFactory.class);
         addFactory(NamedFacetOnMemberFactory.class);
         addFactory(NamedFacetOnParameterAnnotationFactory.class);