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

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


The following commit(s) were added to refs/heads/master by this push:
     new f29865af1d ISIS-3106: fixes handling of @ActionLayout(position)
f29865af1d is described below

commit f29865af1d4f6c0c28d6e558b0eb1ea2044eefc8
Author: Dan Haywood <[email protected]>
AuthorDate: Tue Aug 2 09:48:01 2022 +0100

    ISIS-3106: fixes handling of @ActionLayout(position)
    
    also adds descriptions for all of the mixins
---
 .../mixins/layout/Object_downloadLayoutXml.java    |   1 +
 .../metamodel/Object_downloadMetamodelXml.java     |   1 +
 .../mixins/metamodel/Object_logicalTypeName.java   |   5 +-
 .../mixins/metamodel/Object_objectIdentifier.java  |   1 +
 .../mixins/metamodel/Object_rebuildMetamodel.java  |   1 +
 .../applib/mixins/rest/Object_openRestApi.java     |   1 +
 .../metamodel/inspect/Object_inspectMetamodel.java |   1 +
 .../grid/bootstrap/GridSystemServiceBootstrap.java |  10 +-
 ...ntegTest.java => Layout_Counter_IntegTest.java} |   5 +-
 .../integtest/Layout_SimpleObject_IntegTest.java   | 190 +++++++++++++++++++++
 .../model/Counter_updateNameUsingMixin.java        |  37 ----
 .../layouts/integtest/model/SimpleObject.java      | 139 +++++++++++++++
 .../integtest/model/SimpleObject.layout.xml        |  47 +++++
 .../layouts/integtest/model/types/Name.java        |  20 +++
 .../layouts/integtest/model/types/Notes.java       |  25 +++
 .../commons/applib/mixins/Object_impersonate.java  |   1 +
 .../applib/mixins/Object_impersonateWithRoles.java |   1 +
 17 files changed, 443 insertions(+), 43 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/layout/Object_downloadLayoutXml.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/layout/Object_downloadLayoutXml.java
index eb7a515092..ca812a3fba 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/layout/Object_downloadLayoutXml.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/layout/Object_downloadLayoutXml.java
@@ -52,6 +52,7 @@ import lombok.val;
 )
 @ActionLayout(
         cssClassFa = "fa-download",
+        describedAs = "Downloads the Xxx.layout.xml layout file 
effective/inferred for this object",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         sequence = "700.1"
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_downloadMetamodelXml.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_downloadMetamodelXml.java
index 00d04b7ff4..d182e3f907 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_downloadMetamodelXml.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_downloadMetamodelXml.java
@@ -58,6 +58,7 @@ import lombok.val;
 )
 @ActionLayout(
         cssClassFa = "fa-download",
+        describedAs = "Downloads a representation of the framework's internal 
metamodel for this object's domain class",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         sequence = "700.2"
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_logicalTypeName.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_logicalTypeName.java
index 2440a8a677..5309b28819 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_logicalTypeName.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_logicalTypeName.java
@@ -36,10 +36,10 @@ import lombok.val;
 
 /**
  * Contributes a property exposing the logical object type of the domain
- * object, typically as specified by {@link DomainObject#logicalTypeName()}.
+ * object, typically as specified by {@link javax.inject.Named}.
  *
  * <p>
- *     The object type is also accessible from the
+ *     The logical type name is also accessible from the
  *     {@link org.apache.isis.applib.services.bookmark.Bookmark} of the
  *     object.
  * </p>
@@ -53,6 +53,7 @@ import lombok.val;
  */
 @Property
 @PropertyLayout(
+        describedAs = "The logical name of this domain class (as used in 
persistence, URLs etc).  Intended to be stable/unchanging across time",
         hidden = Where.ALL_TABLES,
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         sequence = "400.1"
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_objectIdentifier.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_objectIdentifier.java
index 6eb2e9ef7d..2e3435404a 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_objectIdentifier.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_objectIdentifier.java
@@ -52,6 +52,7 @@ import lombok.val;
  */
 @Property
 @PropertyLayout(
+        describedAs = "The identifier of this object instance, unique within 
its domain class.  Combined with the 'logical type name', is a unique 
identifier across all domain classes.",
         hidden = Where.ALL_TABLES,
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         sequence = "400.2"
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_rebuildMetamodel.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_rebuildMetamodel.java
index 37f9b667ea..4de02e5b7f 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_rebuildMetamodel.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/metamodel/Object_rebuildMetamodel.java
@@ -47,6 +47,7 @@ import lombok.RequiredArgsConstructor;
 )
 @ActionLayout(
         cssClassFa = "fa-sync",
+        describedAs = "Rebuilds the framework's internal metamodel of this 
object's domain class",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL,
         sequence = "800.1"
diff --git 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/rest/Object_openRestApi.java
 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/rest/Object_openRestApi.java
index 2889d4aae0..d1b982436b 100644
--- 
a/api/applib/src/main/java/org/apache/isis/applib/mixins/rest/Object_openRestApi.java
+++ 
b/api/applib/src/main/java/org/apache/isis/applib/mixins/rest/Object_openRestApi.java
@@ -50,6 +50,7 @@ import lombok.val;
 )
 @ActionLayout(
         cssClassFa = "fa-external-link-alt",
+        describedAs = "Opens up a view of this object as represented in the 
(Restful Objects) REST API",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         sequence = "750.1"
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/inspect/Object_inspectMetamodel.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/inspect/Object_inspectMetamodel.java
index a4ef6ad266..76fdef7eac 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/inspect/Object_inspectMetamodel.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/inspect/Object_inspectMetamodel.java
@@ -52,6 +52,7 @@ import lombok.val;
 )
 @ActionLayout(
         cssClassFa = "fa-sitemap",
+        describedAs = "Open up a view of the metamodel of this object's domain 
class",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         sequence = "700.2.1"
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap/GridSystemServiceBootstrap.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap/GridSystemServiceBootstrap.java
index 0540fef817..2c47c082e4 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap/GridSystemServiceBootstrap.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/grid/bootstrap/GridSystemServiceBootstrap.java
@@ -436,7 +436,15 @@ extends GridSystemServiceAbstract<BSGrid> {
 
                 final ActionLayoutData actionLayoutData = new 
ActionLayoutData(actionId);
 
-                
actionLayoutData.setPosition(ActionLayout.Position.PANEL_DROPDOWN);
+                // since the action is to be associated with a fieldSet, the 
only available positions are PANEL and PANEL_DROPDOWN.
+                // if the action already has a preference for PANEL, then 
preserve it, otherwise default to PANEL_DROPDOWN
+                val actionPositionFacet = 
objectAction.getFacet(ActionPositionFacet.class);
+                if(actionPositionFacet != null && 
actionPositionFacet.position() == ActionLayout.Position.PANEL) {
+                    actionLayoutData.setPosition(ActionLayout.Position.PANEL);
+                } else {
+                    
actionLayoutData.setPosition(ActionLayout.Position.PANEL_DROPDOWN);
+                }
+
                 final FieldSet fieldSet = 
gridModel.getFieldSet(layoutGroupName);
                 addActionTo(fieldSet, actionLayoutData);
             }
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_IntegTest.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_Counter_IntegTest.java
similarity index 99%
rename from 
regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_IntegTest.java
rename to 
regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_Counter_IntegTest.java
index cca8034282..3b19e82c33 100644
--- 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_IntegTest.java
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_Counter_IntegTest.java
@@ -24,7 +24,6 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -80,10 +79,10 @@ import 
org.apache.isis.viewer.wicket.applib.IsisModuleViewerWicketApplibMixins;
 import lombok.val;
 
 @SpringBootTest(
-        classes = Layout_IntegTest.AppManifest.class
+        classes = Layout_Counter_IntegTest.AppManifest.class
 )
 @ActiveProfiles("test")
-public class Layout_IntegTest extends IsisIntegrationTestAbstract {
+public class Layout_Counter_IntegTest extends IsisIntegrationTestAbstract {
 
     @SpringBootConfiguration
     @EnableAutoConfiguration
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_SimpleObject_IntegTest.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_SimpleObject_IntegTest.java
new file mode 100644
index 0000000000..6a4c377f82
--- /dev/null
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/Layout_SimpleObject_IntegTest.java
@@ -0,0 +1,190 @@
+/*
+ *  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.regressiontests.layouts.integtest;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.SpringBootConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.context.annotation.PropertySources;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+import org.springframework.transaction.TransactionStatus;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.isis.applib.IsisModuleApplibMixins;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.id.LogicalType;
+import org.apache.isis.applib.layout.LayoutConstants;
+import org.apache.isis.applib.services.bookmark.Bookmark;
+import org.apache.isis.applib.services.bookmark.BookmarkService;
+import org.apache.isis.applib.services.iactnlayer.InteractionService;
+import org.apache.isis.applib.services.metamodel.Config;
+import org.apache.isis.applib.services.metamodel.MetaModelService;
+import org.apache.isis.core.config.beans.IsisBeanTypeRegistry;
+import org.apache.isis.core.config.presets.IsisPresets;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import 
org.apache.isis.core.metamodel.facets.actions.position.ActionPositionFacet;
+import 
org.apache.isis.core.metamodel.facets.members.layout.group.LayoutGroupFacet;
+import 
org.apache.isis.core.metamodel.facets.members.layout.order.LayoutOrderFacet;
+import org.apache.isis.core.metamodel.spec.feature.MixedIn;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+import org.apache.isis.core.runtimeservices.IsisModuleCoreRuntimeServices;
+import org.apache.isis.regressiontests.layouts.integtest.model.Counter;
+import 
org.apache.isis.regressiontests.layouts.integtest.model.LayoutTestDomainModel;
+import org.apache.isis.regressiontests.layouts.integtest.model.SimpleObject;
+import org.apache.isis.schema.metamodel.v2.Action;
+import org.apache.isis.schema.metamodel.v2.DomainClassDto;
+import org.apache.isis.schema.metamodel.v2.FacetAttr;
+import org.apache.isis.schema.metamodel.v2.MetamodelDto;
+import org.apache.isis.security.bypass.IsisModuleSecurityBypass;
+import 
org.apache.isis.testing.integtestsupport.applib.IsisIntegrationTestAbstract;
+import org.apache.isis.viewer.wicket.applib.IsisModuleViewerWicketApplibMixins;
+
+import lombok.val;
+
+@SpringBootTest(
+        classes = Layout_SimpleObject_IntegTest.AppManifest.class
+)
+@ActiveProfiles("test")
+public class Layout_SimpleObject_IntegTest extends IsisIntegrationTestAbstract 
{
+
+    @SpringBootConfiguration
+    @EnableAutoConfiguration
+    @Import({
+            IsisModuleApplibMixins.class,
+            IsisModuleViewerWicketApplibMixins.class,
+            IsisModuleCoreRuntimeServices.class,
+            IsisModuleSecurityBypass.class,
+    })
+    @PropertySources({
+            @PropertySource(IsisPresets.UseLog4j2Test)
+    })
+    @ComponentScan(basePackageClasses = {AppManifest.class, 
LayoutTestDomainModel.class})
+    public static class AppManifest {
+
+
+    }
+
+    @BeforeAll
+    static void beforeAll() {
+        IsisPresets.forcePrototyping();
+    }
+
+
+    @Test
+    void openRestApi() {
+
+        // given
+        val action = lookupAction("openRestApi");
+
+        // when, then
+        List<Facet> facets = 
action.getFacetHolder().streamFacets().collect(Collectors.toList());
+
+        val actionPositionFacet = action.getFacet(ActionPositionFacet.class);
+        assertThat(actionPositionFacet)
+                .satisfies(f -> 
assertThat(f).extracting(ActionPositionFacet::getPrecedence).isEqualTo(Facet.Precedence.DEFAULT))
+                .satisfies(f -> 
assertThat(f).extracting(ActionPositionFacet::position).isEqualTo(ActionLayout.Position.PANEL_DROPDOWN));
+
+        val layoutOrderFacet = action.getFacet(LayoutOrderFacet.class);
+        assertThat(layoutOrderFacet)
+                .satisfies(f -> 
assertThat(f).extracting(LayoutOrderFacet::getPrecedence).isEqualTo(Facet.Precedence.DEFAULT))
+                .satisfies(f -> 
assertThat(f).extracting(LayoutOrderFacet::getSequence).isEqualTo("750.1"))
+        ;
+
+        val layoutGroupFacet = action.getFacet(LayoutGroupFacet.class);
+        assertThat(layoutGroupFacet)
+                .satisfies(f -> 
assertThat(f).extracting(LayoutGroupFacet::getGroupId).isEqualTo(LayoutConstants.FieldSetId.METADATA))
+        ;
+    }
+
+    @Test
+    void clearHints() {
+
+        // given
+        val action = lookupAction("clearHints");
+
+        // when, then
+        List<Facet> facets = 
action.getFacetHolder().streamFacets().collect(Collectors.toList());
+
+        val actionPositionFacet = action.getFacet(ActionPositionFacet.class);
+        assertThat(actionPositionFacet)
+                .satisfies(f -> 
assertThat(f).extracting(ActionPositionFacet::getPrecedence).isEqualTo(Facet.Precedence.DEFAULT))
+                .satisfies(f -> 
assertThat(f).extracting(ActionPositionFacet::position).isEqualTo(ActionLayout.Position.PANEL));
+
+        val layoutOrderFacet = action.getFacet(LayoutOrderFacet.class);
+        assertThat(layoutOrderFacet)
+                .satisfies(f -> 
assertThat(f).extracting(LayoutOrderFacet::getPrecedence).isEqualTo(Facet.Precedence.DEFAULT))
+                .satisfies(f -> 
assertThat(f).extracting(LayoutOrderFacet::getSequence).isEqualTo("400.1"))
+        ;
+
+        val layoutGroupFacet = action.getFacet(LayoutGroupFacet.class);
+        assertThat(layoutGroupFacet)
+                .satisfies(f -> 
assertThat(f).extracting(LayoutGroupFacet::getGroupId).isEqualTo(LayoutConstants.FieldSetId.METADATA))
+        ;
+    }
+
+    private ObjectAction lookupAction(String id) {
+        val objectSpecification = 
specificationLoader.loadSpecification(SimpleObject.class);
+        List<ObjectAction> objectActions = 
objectSpecification.streamAnyActions(MixedIn.INCLUDED).collect(Collectors.toList());
+        return objectSpecification.streamAnyActions(MixedIn.INCLUDED).filter(x 
-> x.getId().equals(id)).findFirst().orElseThrow();
+    }
+
+
+    private void extracted(Class<?> cls) {
+        LogicalType logicalType = 
metaModelService.lookupLogicalTypeByClass(cls).orElseThrow();
+        MetamodelDto metamodelDto = metaModelService.exportMetaModel(new 
Config().withNamespacePrefix("layouts.test."));
+        Map<String, DomainClassDto> metaModelDtoById = 
metamodelDto.getDomainClassDto().stream().collect(Collectors.toMap(DomainClassDto::getId,
 Function.identity()));
+        DomainClassDto domainClassDto = 
metaModelDtoById.get(cls.getCanonicalName());
+        Map<String, Action> actionById = 
domainClassDto.getActions().getAct().stream().collect(Collectors.toMap(Action::getId,
 Function.identity()));
+        List<org.apache.isis.schema.metamodel.v2.Facet> facets = 
actionById.get("updateNameUsingDeclaredAction").getFacets().getFacet();
+        Map<String, org.apache.isis.schema.metamodel.v2.Facet> facetById = 
facets.stream().collect(Collectors.toMap(org.apache.isis.schema.metamodel.v2.Facet::getId,
 Function.identity()));
+        Map<String, String> facetAttrByName = 
facetById.get(LayoutGroupFacet.class.getCanonicalName()).getAttr().stream().collect(Collectors.toMap(FacetAttr::getName,
 FacetAttr::getValue));
+        facetAttrByName.get("Name");
+    }
+
+
+    @Inject InteractionService interactionService;
+    @Inject MetaModelService metaModelService;
+    @Inject SpecificationLoader specificationLoader;
+    @Inject BookmarkService bookmarkService;
+
+    @Inject IsisBeanTypeRegistry isisBeanTypeRegistry;
+
+}
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/Counter_updateNameUsingMixin.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/Counter_updateNameUsingMixin.java
deleted file mode 100644
index e3cee6dd93..0000000000
--- 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/Counter_updateNameUsingMixin.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *  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.regressiontests.layouts.integtest.model;
-
-import org.apache.isis.applib.annotation.Action;
-import org.apache.isis.applib.services.wrapper.Mixin;
-
-import lombok.RequiredArgsConstructor;
-
-@Action()
-@RequiredArgsConstructor
-public class Counter_updateNameUsingMixin implements Mixin<Counter> {
-
-    private final Counter counter;
-
-    public Counter act(String name) {
-        return counter.doUpdateName(name);
-    }
-}
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.java
new file mode 100644
index 0000000000..50f0c32c3c
--- /dev/null
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.java
@@ -0,0 +1,139 @@
+package org.apache.isis.regressiontests.layouts.integtest.model;
+
+import java.util.Comparator;
+
+import javax.inject.Inject;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+
+import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.annotation.ActionLayout;
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.DomainObjectLayout;
+import org.apache.isis.applib.annotation.PromptStyle;
+import org.apache.isis.applib.annotation.Property;
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.applib.annotation.Publishing;
+import org.apache.isis.applib.annotation.Title;
+import org.apache.isis.applib.jaxb.PersistentEntityAdapter;
+import org.apache.isis.applib.services.message.MessageService;
+import org.apache.isis.applib.services.repository.RepositoryService;
+import org.apache.isis.applib.services.title.TitleService;
+import org.apache.isis.regressiontests.layouts.integtest.model.types.Name;
+import org.apache.isis.regressiontests.layouts.integtest.model.types.Notes;
+//import org.apache.isis.persistence.jpa.applib.integration.IsisEntityListener;
+
+import static org.apache.isis.applib.annotation.SemanticsOf.IDEMPOTENT;
+import static 
org.apache.isis.applib.annotation.SemanticsOf.NON_IDEMPOTENT_ARE_YOU_SURE;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.val;
+
+
[email protected]
[email protected](
+    schema="simple",
+    uniqueConstraints = {
+        @javax.persistence.UniqueConstraint(name = "SimpleObject__name__UNQ", 
columnNames = {"NAME"})
+    }
+)
[email protected]({
+        @javax.persistence.NamedQuery(
+                name = SimpleObject.NAMED_QUERY__FIND_BY_NAME_LIKE,
+                query = "SELECT so " +
+                        "FROM SimpleObject so " +
+                        "WHERE so.name LIKE :name"
+        )
+})
+//@javax.persistence.EntityListeners(IsisEntityListener.class)
+@DomainObject(logicalTypeName = "simple.SimpleObject", entityChangePublishing 
= Publishing.ENABLED)
+@DomainObjectLayout()
+@NoArgsConstructor(access = AccessLevel.PUBLIC)
+@XmlJavaTypeAdapter(PersistentEntityAdapter.class)
+@ToString(onlyExplicitlyIncluded = true)
+public class SimpleObject implements Comparable<SimpleObject> {
+
+    static final String NAMED_QUERY__FIND_BY_NAME_LIKE = 
"SimpleObject.findByNameLike";
+
+    @javax.persistence.Id
+    @javax.persistence.GeneratedValue(strategy = 
javax.persistence.GenerationType.AUTO)
+    @javax.persistence.Column(name = "id", nullable = false)
+    private Long id;
+
+    @javax.persistence.Version
+    @javax.persistence.Column(name = "version", nullable = false)
+    @PropertyLayout(fieldSetId = "metadata", sequence = "999")
+    @Getter @Setter
+    private long version;
+
+    public static SimpleObject withName(String name) {
+        val simpleObject = new SimpleObject();
+        simpleObject.setName(name);
+        return simpleObject;
+    }
+
+    @Inject @javax.persistence.Transient RepositoryService repositoryService;
+    @Inject @javax.persistence.Transient TitleService titleService;
+    @Inject @javax.persistence.Transient MessageService messageService;
+
+
+
+    @Title
+    @Name
+    @javax.persistence.Column(length = Name.MAX_LEN, nullable = false)
+    @Getter @Setter @ToString.Include
+    @PropertyLayout(fieldSetId = "name", sequence = "1")
+    private String name;
+
+    @Notes
+    @javax.persistence.Column(length = Notes.MAX_LEN, nullable = true)
+    @Getter @Setter
+    @Property(commandPublishing = Publishing.ENABLED, executionPublishing = 
Publishing.ENABLED)
+    @PropertyLayout(fieldSetId = "name", sequence = "2")
+    private String notes;
+
+
+    @Action(semantics = IDEMPOTENT, commandPublishing = Publishing.ENABLED, 
executionPublishing = Publishing.ENABLED)
+    @ActionLayout(associateWith = "name", promptStyle = PromptStyle.INLINE)
+    public SimpleObject updateName(
+            @Name final String name) {
+        setName(name);
+        return this;
+    }
+    public String default0UpdateName() {
+        return getName();
+    }
+    public String validate0UpdateName(String newName) {
+        for (char prohibitedCharacter : "&%$!".toCharArray()) {
+            if( newName.contains(""+prohibitedCharacter)) {
+                return "Character '" + prohibitedCharacter + "' is not 
allowed.";
+            }
+        }
+        return null;
+    }
+
+
+    @Action(semantics = NON_IDEMPOTENT_ARE_YOU_SURE)
+    @ActionLayout(
+            position = ActionLayout.Position.PANEL,
+            describedAs = "Deletes this object from the persistent datastore")
+    public void delete() {
+        final String title = titleService.titleOf(this);
+        messageService.informUser(String.format("'%s' deleted", title));
+        repositoryService.removeAndFlush(this);
+    }
+
+
+
+    private final static Comparator<SimpleObject> comparator =
+            Comparator.comparing(SimpleObject::getName);
+
+    @Override
+    public int compareTo(final SimpleObject other) {
+        return comparator.compare(this, other);
+    }
+
+}
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.layout.xml
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.layout.xml
new file mode 100644
index 0000000000..deaca8e6f1
--- /dev/null
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/SimpleObject.layout.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<bs3:grid xsi:schemaLocation="http://isis.apache.org/applib/layout/component 
http://isis.apache.org/applib/layout/component/component.xsd 
http://isis.apache.org/applib/layout/grid/bootstrap3 
http://isis.apache.org/applib/layout/grid/bootstrap3/bootstrap3.xsd"; 
xmlns:c="http://isis.apache.org/applib/layout/component"; 
xmlns:bs3="http://isis.apache.org/applib/layout/grid/bootstrap3"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
+
+    <bs3:row>
+        <bs3:col span="12" unreferencedActions="true">
+            <c:domainObject bookmarking="AS_ROOT"/>
+        </bs3:col>
+    </bs3:row>
+    <bs3:row>
+        <bs3:col span="6">
+            <bs3:row>
+                <bs3:col span="12">
+                    <bs3:tabGroup>
+                        <bs3:tab name="Identity">
+                            <bs3:row>
+                                <bs3:col span="12">
+                                    <c:fieldSet name="Identity" id="identity"/>
+                                </bs3:col>
+                            </bs3:row>
+                        </bs3:tab>
+                        <bs3:tab name="Other">
+                            <bs3:row>
+                                <bs3:col span="12">
+                                    <c:fieldSet name="Other" id="other" 
unreferencedProperties="true"/>
+                                </bs3:col>
+                            </bs3:row>
+                        </bs3:tab>
+                        <bs3:tab name="Metadata">
+                            <bs3:row>
+                                <bs3:col span="12">
+                                    <c:fieldSet name="Metadata" id="metadata"/>
+                                </bs3:col>
+                            </bs3:row>
+                        </bs3:tab>
+                    </bs3:tabGroup>
+                </bs3:col>
+                <bs3:col span="12">
+                    <c:fieldSet name="Details" id="details"/>
+                </bs3:col>
+            </bs3:row>
+        </bs3:col>
+        <bs3:col span="6">
+            <bs3:tabGroup  unreferencedCollections="true">
+            </bs3:tabGroup>
+        </bs3:col>
+    </bs3:row>
+</bs3:grid>
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Name.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Name.java
new file mode 100644
index 0000000000..6895026986
--- /dev/null
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Name.java
@@ -0,0 +1,20 @@
+package org.apache.isis.regressiontests.layouts.integtest.model.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.annotation.Parameter;
+import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.annotation.Property;
+
+@Property(maxLength = Name.MAX_LEN)
+@Parameter(maxLength = Name.MAX_LEN)
+@ParameterLayout(named = "Name")
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, 
ElementType.ANNOTATION_TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Name {
+
+    int MAX_LEN = 40;
+}
diff --git 
a/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Notes.java
 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Notes.java
new file mode 100644
index 0000000000..8b9b62bff5
--- /dev/null
+++ 
b/regressiontests/stable-layouts/src/main/java/org/apache/isis/regressiontests/layouts/integtest/model/types/Notes.java
@@ -0,0 +1,25 @@
+package org.apache.isis.regressiontests.layouts.integtest.model.types;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.apache.isis.applib.annotation.Editing;
+import org.apache.isis.applib.annotation.Parameter;
+import org.apache.isis.applib.annotation.ParameterLayout;
+import org.apache.isis.applib.annotation.Property;
+import org.apache.isis.applib.annotation.PropertyLayout;
+import org.apache.isis.applib.annotation.Where;
+
+@Property(editing = Editing.ENABLED, maxLength = Notes.MAX_LEN)
+@PropertyLayout(named = "Notes", multiLine = 10, hidden = Where.ALL_TABLES)
+@Parameter(maxLength = Notes.MAX_LEN)
+@ParameterLayout(named = "Notes", multiLine = 10)
+@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, 
ElementType.ANNOTATION_TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Notes {
+
+    int MAX_LEN = 4000;
+
+}
diff --git 
a/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonate.java
 
b/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonate.java
index b541258374..ed666fabe8 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonate.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonate.java
@@ -49,6 +49,7 @@ import lombok.RequiredArgsConstructor;
 )
 @ActionLayout(
         cssClassFa = "fa-mask",
+        describedAs = "Switch to another user account (for prototype/testing 
only)",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         redirectPolicy = Redirect.EVEN_IF_SAME,
diff --git 
a/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonateWithRoles.java
 
b/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonateWithRoles.java
index 3b72bed935..b988a568bb 100644
--- 
a/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonateWithRoles.java
+++ 
b/viewers/commons/model/src/main/java/org/apache/isis/viewer/commons/applib/mixins/Object_impersonateWithRoles.java
@@ -52,6 +52,7 @@ import lombok.val;
 )
 @ActionLayout(
         cssClassFa = "fa-mask",
+        describedAs = "Switch to another user account with specified roles 
(for prototype/testing only)",
         fieldSetId = LayoutConstants.FieldSetId.METADATA,
         position = ActionLayout.Position.PANEL_DROPDOWN,
         redirectPolicy = Redirect.EVEN_IF_SAME,

Reply via email to