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 2021/07/22 06:40:00 UTC

[isis] 01/01: ISIS-2813: adds TableColumnOrderServiceUsingTxtFile

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

danhaywood pushed a commit to branch ISIS-2813
in repository https://gitbox.apache.org/repos/asf/isis.git

commit f6cbb92770652502dad09bcf5aea945633dc2b9a
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Thu Jul 22 07:39:33 2021 +0100

    ISIS-2813: adds TableColumnOrderServiceUsingTxtFile
    
    with unit test and docs
---
 .../modules/applib-classes/pages/layout.adoc       |   1 +
 .../applib-classes/pages/layout/column-order.adoc  |  70 ++++++++
 .../org/apache/isis/applib/annotation/Where.java   |  29 +++-
 .../core/metamodel/IsisModuleCoreMetamodel.java    |   7 +-
 .../TableColumnOrderServiceUsingTxtFile.java       | 188 +++++++++++++++++++++
 .../tablecol/Customer#orders.columnOrder.txt       |   5 +
 .../services/tablecol/Order.columnOrder.txt        |   5 +
 .../TableColumnOrderServiceUsingTxtFile_Test.java  |  73 ++++++++
 ...thenticationConverterOfOAuth2UserPrincipal.java |  15 +-
 .../entity/icontitle/EntityIconAndTitlePanel.java  |   8 +-
 10 files changed, 376 insertions(+), 25 deletions(-)

diff --git a/antora/components/refguide/modules/applib-classes/pages/layout.adoc b/antora/components/refguide/modules/applib-classes/pages/layout.adoc
index 53deec6..e442801 100644
--- a/antora/components/refguide/modules/applib-classes/pages/layout.adoc
+++ b/antora/components/refguide/modules/applib-classes/pages/layout.adoc
@@ -5,3 +5,4 @@
 
 include::layout/object-layout.adoc[leveloffset=+1]
 include::layout/menubars.adoc[leveloffset=+1]
+include::layout/column-order.adoc[leveloffset=+1]
diff --git a/antora/components/refguide/modules/applib-classes/pages/layout/column-order.adoc b/antora/components/refguide/modules/applib-classes/pages/layout/column-order.adoc
new file mode 100644
index 0000000..1446eef
--- /dev/null
+++ b/antora/components/refguide/modules/applib-classes/pages/layout/column-order.adoc
@@ -0,0 +1,70 @@
+[#column-order]
+= Column Order
+
+:Notice: 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 ag [...]
+:page-partial:
+
+
+The xref:refguide:applib:index/services/tablecol/TableColumnOrderService.adoc[TableColumnOrderService] SPI allows applications to define the order in which property columns appear in tables, for both parented and standalone collections.
+
+Although this is an SPI, the framework also provides an out-of-the-box implementation that uses simple text files to specify the column order.
+These simple files can be reloaded dynamically during prototyping, so make it easy to change the order of columns (or hide columns completely).
+
+== Parented Collections
+
+For parented collections, the file should be called `ParentedClass#collectionId.columnOrder.txt`.
+
+For example, suppose that `Customer` has an `orders` collection consisting of ``Order``s, where the default ordering of properties (from the xref:refguide:applib:index/annotation/PropertyLayout.adoc#sequence[@PropertyLayout#sequence] annotation) is (say) "orderNum", "orderStatus", "orderDate", "orderAmount".
+
+This order can be changed using this file:
+
+[source,text]
+.Customer#orders.columnOrder.txt
+----
+orderNum
+orderDate
+orderStatus
+----
+
+=== Commented out and unknown properties
+
+Note also that the following would return the same result:
+
+[source,text]
+.Customer#orders.columnOrder.txt
+----
+orderNum
+#orderAmount
+orderDate
+orderStatus
+nonsense
+----
+
+Here the "orderAmount" is commented out and so is excluded because the line is not an exact match.
+The same is true for "nonsense"; it doesn't match any of the original properties of the `Order` class.
+
+
+== Standalone Collections
+
+For parented collections, the file should be called `Class.columnOrder.txt`.
+
+For example, suppose that the `Order` entity is returned from various repository queries as a standalone collection, where (as in the example above) the default ordering of properties (from the xref:refguide:applib:index/annotation/PropertyLayout.adoc#sequence[@PropertyLayout#sequence] annotation) is (say) "orderNum", "orderStatus", "orderDate", "orderAmount".
+
+This order can be changed using this file:
+
+[source,text]
+.Order.columnOrder.txt
+----
+orderNum
+orderDate
+orderStatus
+----
+
+== Customising the Implementation
+
+The above behaviour is provided by the xref:refguide:core:index/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.adoc[TableColumnOrderServiceUsingTxtFile] implementation of the xref:refguide:applib:index/services/tablecol/TableColumnOrderService.adoc[TableColumnOrderService] SPI.
+
+If necessary, the class can be subclassed to change the convention for searching for class files; just make sure that the subclass has an earlier `Precedence` than the framework so that it is picked up first.
+
+You could of course also use it as the inspiration of your own more sophisticated implementation.
+
diff --git a/api/applib/src/main/java/org/apache/isis/applib/annotation/Where.java b/api/applib/src/main/java/org/apache/isis/applib/annotation/Where.java
index 3db35c9..25632c7 100644
--- a/api/applib/src/main/java/org/apache/isis/applib/annotation/Where.java
+++ b/api/applib/src/main/java/org/apache/isis/applib/annotation/Where.java
@@ -91,29 +91,32 @@ public enum Where {
     OBJECT_FORMS,
 
     /**
-     * The member should be disabled/hidden when displayed as a column of a table
-     * within parent object's collection, and references that parent.
-     *
-     * <p>
-     * For most (all?) viewers, this will have meaning only if applied to a property member.
+     * The (property) member should be hidden when displayed as a column of a table
+     * within parent object's collection, and when it references that parent.
      */
     REFERENCES_PARENT,
 
     /**
-     * The member should be disabled/hidden when displayed as a column of a table within
+     * The member should be hidden when displayed as a column of a table within
      * a parent object's collection.
      *
      * <p>
-     * For most (all?) viewers, this will have meaning only if applied to a property member.
+     * An alternative to using annotations is using to use file based layout, which can be reloaded dynamically.
+     * One implementation that supports this is <code>TableColumnOrderServiceUsingTxtFile</code> service, that reads
+     * from files named <i>ParentClass#collectionId.columnOrder.txt</i>.
+     * </p>
      */
     PARENTED_TABLES ,
 
     /**
-     * The member should be disabled/hidden when displayed as a column of a table showing a standalone list
+     * The member should be hidden when displayed as a column of a table showing a standalone list
      * of objects, for example as returned by a repository query.
      *
      * <p>
-     * For most (all?) viewers, this will have meaning only if applied to a property member.
+     * An alternative to using annotations is using to use file based layout, which can be reloaded dynamically.
+     * One implementation that supports this is <code>TableColumnOrderServiceUsingTxtFile</code> service, that reads
+     * from files named <i>ClassName.columnOrder.txt</i>.
+     * </p>
      */
     STANDALONE_TABLES,
 
@@ -123,6 +126,14 @@ public enum Where {
      *
      * <p>
      * This combines {@link #PARENTED_TABLES} and {@link #STANDALONE_TABLES}.
+     * </p>
+     *
+     * <p>
+     * An alternative to using annotations is using to use file based layout, which can be reloaded dynamically.
+     * One implementation that supports this is <code>TableColumnOrderServiceUsingTxtFile</code> service, that reads
+     * from files named <i>ParentClass#collectionId.columnOrder.txt</i> (parented collections) and
+     * <i>ClassName.columnOrder.txt</i> (standalone collections).
+     * </p>
      */
     ALL_TABLES {
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
index da7b045..f6ab39a 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/IsisModuleCoreMetamodel.java
@@ -18,9 +18,6 @@
  */
 package org.apache.isis.core.metamodel;
 
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-
 import org.apache.isis.applib.IsisModuleApplib;
 import org.apache.isis.core.config.IsisModuleCoreConfig;
 import org.apache.isis.core.metamodel.context.MetaModelContexts;
@@ -46,6 +43,7 @@ import org.apache.isis.core.metamodel.services.layout.LayoutServiceDefault;
 import org.apache.isis.core.metamodel.services.metamodel.MetaModelServiceDefault;
 import org.apache.isis.core.metamodel.services.registry.ServiceRegistryDefault;
 import org.apache.isis.core.metamodel.services.tablecol.TableColumnOrderServiceDefault;
+import org.apache.isis.core.metamodel.services.tablecol.TableColumnOrderServiceUsingTxtFile;
 import org.apache.isis.core.metamodel.services.title.TitleServiceDefault;
 import org.apache.isis.core.metamodel.specloader.ProgrammingModelServiceDefault;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoaderDefault;
@@ -54,6 +52,8 @@ import org.apache.isis.core.metamodel.valuetypes.ValueTypeProviderForBuiltin;
 import org.apache.isis.core.metamodel.valuetypes.ValueTypeProviderForCollections;
 import org.apache.isis.core.metamodel.valuetypes.ValueTypeRegistry;
 import org.apache.isis.core.security.IsisModuleCoreSecurity;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
 
 @Configuration
 @Import({
@@ -91,6 +91,7 @@ import org.apache.isis.core.security.IsisModuleCoreSecurity;
         ProgrammingModelServiceDefault.class,
         ServiceRegistryDefault.class,
         TableColumnOrderServiceDefault.class,
+        TableColumnOrderServiceUsingTxtFile.class,
         TitleServiceDefault.class,
         SpecificationLoaderDefault.class,
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
new file mode 100644
index 0000000..9459f3e
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile.java
@@ -0,0 +1,188 @@
+/*
+ *  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.services.tablecol;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import javax.annotation.Priority;
+import javax.inject.Named;
+
+import org.apache.isis.applib.annotation.PriorityPrecedence;
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.applib.services.tablecol.TableColumnOrderService;
+import org.apache.isis.commons.internal.resources._Resources;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Service;
+
+import lombok.extern.log4j.Log4j2;
+import lombok.val;
+
+/**
+ * Provides a simple mechanism to order the columns of both parented and standalone collections by reading a flat
+ * file containing the list of the properties in the desired order, one propertyId per line.
+ *
+ * <p>
+ * The files are located relative to the class itself.  For parented collections, the file is named
+ * <i>ParentClassName#collectionId.columnOrder.txt</i>, while for standalone collections, the file is named
+ * <i>ClassName.columnOrder.txt</i>.
+ * </p>
+ *
+ * <p>
+ * Any properties omitted from the file will not be shown as columns of the table.  The propertyId must also
+ * be an exact match, so can be ignored by commenting out, eg with &quot;#&quot;.
+ * </p>
+ *
+ * <p>
+ *     Also note that properties that have been explicitly hidden from tables using
+ *     {@link PropertyLayout#hidden() @PropertyLayout#hidden} are never shown, irrespective of whether they are listed
+ *     in the files.  You may therefore prefer to <i>not</i> hide properties with annotations, and then rely solely
+ *     on these external <i>columnOrder.txt</i> files.  This has the further benefit that files can be modified at
+ *     runtime and will be automatically picked up without requiring a restart of the application.
+ * </p>
+ *
+ * @since 1.x {@index}
+ */
+@Service
+@Named("isis.metamodel.TableColumnOrderServiceUsingTxtFile")
+@Priority(PriorityPrecedence.LATE - 100) // before Default
+@Qualifier("UsingFiles")
+@Log4j2
+public class TableColumnOrderServiceUsingTxtFile implements TableColumnOrderService {
+
+    static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
+    /**
+     * Reads propertyIds of the collection from a file named <i>ClassName#collectionId.columnOrder.txt</i>. relative
+     * to the class itself.
+     *
+     * <p>
+     * Additional files can be provided by overriding {@link #addResourceNames(Class, String, List)}.
+     * </p>
+     */
+    @Override
+    public List<String> orderParented(
+            final Object domainObject,
+            final String collectionId,
+            final Class<?> collectionType,
+            final List<String> propertyIds) {
+
+        val domainClass = domainObject.getClass();
+        val resourceNames = buildResourceNames(domainClass, collectionId);
+        val contentsIfAny = tryLoad(domainClass, resourceNames);
+        if(!contentsIfAny.isPresent()) {
+            return null;
+        }
+        val s = contentsIfAny.get();
+        return Arrays.stream(s.split(LINE_SEPARATOR))
+                .filter(propertyIds::contains)
+                .collect(Collectors.toList());
+    }
+
+    private List<String> buildResourceNames(Class<?> domainClass, String collectionId) {
+        val resourceNames = new ArrayList<String>();
+        addResourceNames(domainClass, collectionId, resourceNames);
+        return resourceNames;
+    }
+
+    /**
+     * Builds the list of file names to be read from.
+     *
+     * <p>
+     * The default implementation provides only a single file name, <i>ClassName#collectionId.columnOrder.txt</i>.
+     * </p>
+     *
+     * @param domainClass  - the class with the parent collection
+     * @param collectionId - the id of the collection
+     * @param addTo        - to be added to
+     */
+    protected void addResourceNames(
+            final Class<?> domainClass,
+            final String collectionId,
+            final List<String> addTo) {
+        addTo.add(String.format("%s#%s.columnOrder.txt", domainClass.getSimpleName(), collectionId));
+    }
+
+    private static Optional<String> tryLoad(Class<?> domainClass, List<String> resourceNames) {
+        for (String resourceName : resourceNames) {
+            try {
+                final String contents = _Resources.loadAsStringUtf8(domainClass, resourceName);
+                if (contents != null) {
+                    return Optional.of(contents);
+                }
+            } catch (Exception ignore) {
+                // in most cases there won't be a file to load, so we just continue.
+                // not an error condition, but we'll log it at lowest (trace) level.
+                if (log.isTraceEnabled()) {
+                    log.trace("No resource file '{}' relative to {}", resourceName, domainClass.getName());
+                }
+            }
+        }
+        return Optional.empty();
+    }
+
+    /**
+     * Reads propertyIds of the standalone collection from a file named <i>ClassName.columnOrder.txt</i>, relative
+     * to the class itself.
+     *
+     * <p>
+     * Additional files can be provided by overriding {@link #addResourceNames(Class, List)}.
+     * </p>
+     */
+    @Override
+    public List<String> orderStandalone(
+            final Class<?> domainClass,
+            final List<String> propertyIds) {
+        val resourceNames = buildResourceNames(domainClass);
+        val contentsIfAny = tryLoad(domainClass, resourceNames);
+        if(!contentsIfAny.isPresent()) {
+            return null;
+        }
+        val s = contentsIfAny.get();
+        return Arrays.stream(s.split(LINE_SEPARATOR))
+                .filter(propertyIds::contains)
+                .collect(Collectors.toList());
+    }
+
+    private List<String> buildResourceNames(Class<?> domainClass) {
+        val resourceNames = new ArrayList<String>();
+        addResourceNames(domainClass, resourceNames);
+        return resourceNames;
+    }
+
+    /**
+     * Builds the list of file names to be read from.
+     *
+     * <p>
+     * The default implementation provides only a single file name, <i>ClassName#collectionId.columnOrder.txt</i>.
+     * </p>
+     *
+     * @param domainClass - the class in the standalone collection
+     * @param addTo       - to be added to
+     */
+    protected void addResourceNames(
+            final Class<?> domainClass,
+            final List<String> addTo) {
+        addTo.add(String.format("%s.columnOrder.txt", domainClass.getSimpleName()));
+    }
+
+}
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Customer#orders.columnOrder.txt b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Customer#orders.columnOrder.txt
new file mode 100644
index 0000000..969d861
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Customer#orders.columnOrder.txt
@@ -0,0 +1,5 @@
+orderNum
+#orderAmount
+orderDate
+orderStatus
+nonsense
\ No newline at end of file
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Order.columnOrder.txt b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Order.columnOrder.txt
new file mode 100644
index 0000000..969d861
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/Order.columnOrder.txt
@@ -0,0 +1,5 @@
+orderNum
+#orderAmount
+orderDate
+orderStatus
+nonsense
\ No newline at end of file
diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile_Test.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile_Test.java
new file mode 100644
index 0000000..344577a
--- /dev/null
+++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/tablecol/TableColumnOrderServiceUsingTxtFile_Test.java
@@ -0,0 +1,73 @@
+package org.apache.isis.core.metamodel.services.tablecol;
+
+import java.util.Arrays;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import lombok.val;
+import static org.assertj.core.api.Assertions.assertThat;
+
+class TableColumnOrderServiceUsingTxtFile_Test {
+
+    private TableColumnOrderServiceUsingTxtFile service;
+
+    @BeforeEach
+    void setUp() {
+        service = new TableColumnOrderServiceUsingTxtFile();
+    }
+
+    @Nested
+    class orderParented {
+
+        @Test
+        void happy_case() {
+            // when
+            val ordered = service.orderParented(new Customer(), "orders", Order.class,
+                    Arrays.asList("orderNum", "orderStatus", "orderDate", "orderAmount"));
+
+            // then
+            assertThat(ordered).containsExactly("orderNum", "orderDate", "orderStatus");
+        }
+
+        @Test
+        void missing_file() {
+            // when
+            val ordered = service.orderParented(new Customer(), "nonExistent", Order.class,
+                    Arrays.asList("orderNum", "orderStatus", "orderDate", "orderAmount"));
+
+            // then
+            assertThat(ordered).isNull();
+        }
+    }
+
+    @Nested
+    class orderStandalone {
+
+        @Test
+        void happy_case() {
+            // when
+            val ordered = service.orderStandalone(Order.class,
+                    Arrays.asList("orderNum", "orderStatus", "orderDate", "orderAmount"));
+
+            // then
+            assertThat(ordered).containsExactly("orderNum", "orderDate", "orderStatus");
+        }
+
+        @Test
+        void missing_file() {
+            // when
+            val ordered = service.orderStandalone(Order.class,
+                    Arrays.asList("orderNum", "orderStatus", "orderDate", "orderAmount"));
+
+            // then
+            assertThat(ordered).isNull();
+        }
+    }
+
+}
+class Order {
+}
+class Customer {
+}
diff --git a/extensions/security/spring-oauth2/src/main/java/org/apache/isis/extensions/spring/security/oauth2/authconverters/AuthenticationConverterOfOAuth2UserPrincipal.java b/extensions/security/spring-oauth2/src/main/java/org/apache/isis/extensions/spring/security/oauth2/authconverters/AuthenticationConverterOfOAuth2UserPrincipal.java
index c6481ae..4ebf600 100644
--- a/extensions/security/spring-oauth2/src/main/java/org/apache/isis/extensions/spring/security/oauth2/authconverters/AuthenticationConverterOfOAuth2UserPrincipal.java
+++ b/extensions/security/spring-oauth2/src/main/java/org/apache/isis/extensions/spring/security/oauth2/authconverters/AuthenticationConverterOfOAuth2UserPrincipal.java
@@ -3,13 +3,12 @@ package org.apache.isis.extensions.spring.security.oauth2.authconverters;
 import java.net.MalformedURLException;
 import java.net.URL;
 
-import org.springframework.security.core.Authentication;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.stereotype.Component;
-
 import org.apache.isis.applib.annotation.PriorityPrecedence;
 import org.apache.isis.applib.services.user.UserMemento;
 import org.apache.isis.security.spring.authconverters.AuthenticationConverter;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.stereotype.Component;
 
 import lombok.val;
 
@@ -42,11 +41,9 @@ public class AuthenticationConverterOfOAuth2UserPrincipal implements Authenticat
         val principal = authentication.getPrincipal();
         if (principal instanceof OAuth2User) {
             val oAuth2User = (OAuth2User) principal;
-            val username = usernameFrom(oAuth2User);
-            var userMemento = UserMemento.ofNameAndRoleNames(username);
-            userMemento = userMemento.withAvatarUrl(avatarUrlFrom(oAuth2User));
-            userMemento = userMemento.withRealName(realNameFrom(oAuth2User));
-            return userMemento;
+            return UserMemento.ofNameAndRoleNames(usernameFrom(oAuth2User))
+                    .withAvatarUrl(avatarUrlFrom(oAuth2User))
+                    .withRealName(realNameFrom(oAuth2User));
         }
         return null;
     }
diff --git a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
index 6719a51..569558c 100644
--- a/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
+++ b/viewers/wicket/ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/entity/icontitle/EntityIconAndTitlePanel.java
@@ -137,7 +137,7 @@ extends PanelAbstract<ManagedObject, ObjectAdapterModel> {
             }
 
             final String title = determineTitle();
-            this.label = newLabel(ID_ENTITY_TITLE, title);
+            this.label = newLabel(ID_ENTITY_TITLE, titleAbbreviated(title));
             link.addOrReplace(this.label);
 
             String entityTypeName = determineFriendlyType() // from actual underlying model
@@ -205,9 +205,9 @@ extends PanelAbstract<ManagedObject, ObjectAdapterModel> {
     }
 
     private String determineTitle() {
-        val domainObject = getModel().getObject();
-        return domainObject != null
-                ? titleAbbreviated(domainObject.titleString(this::isContextAdapter))
+        val managedObject = getModel().getObject();
+        return managedObject != null
+                ? managedObject.titleString(this::isContextAdapter)
                 : "(no object)";
     }