You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by jo...@apache.org on 2023/02/23 20:09:00 UTC

[causeway] branch ISIS-3171 updated (6e9778024e -> 2f2f71a67a)

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

joergrade pushed a change to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git


    from 6e9778024e Merge remote-tracking branch 'origin/master' into ISIS-3171
     new 77de476d96 ISIS-3171 Basic_Types.Strings opens, but without parentedCollection
     new 4e685851d2 ISIS-3171 Basic_Types.Strings opens, but table is without icons and columns
     new 021eed2391 ISIS-3171 table is shown, hidden/disabled/name not correctly set yet
     new cd7d1eb6b7 ISIS-3171 table is shown, hidden/disabled/name not correctly set yet
     new 35a43a8bcf ISIS-3171 PropertySpecification amended with object-layout.xml (per 'protoType')
     new 55f7e1397c ISIS-3171 'sources' explicitly hidden
     new 9bbf18daea ISIS-3171 CollectionLayout removed, PropertySpecificationHolder introduced
     new 90ac2fd195 ISIS-3171 cleanup
     new cabe94b0c1 ISIS-3171 more cleanup
     new 2f2f71a67a ISIS-3171 Collection and Object displayed

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../modules/kroviz/pages/DevelopmentGuide.adoc     |  12 +-
 .../kroviz/adoc/modules/kroviz/pages/credits.adoc  |   8 +-
 .../partials/design/class-diagram_aggregator.adoc  |   6 +-
 .../partials/design/class-diagram_layout.adoc      |   6 +-
 .../design/collection_layout_aggregation.adoc      |  34 +++
 .../collection_layout_aggregation_diagram.adoc     | 136 +++++++++
 .../kroviz/partials/design/seq-aggregator.adoc     |   2 +-
 .../kroviz/core/aggregator/ActionDispatcher.kt     |   2 +-
 .../kroviz/core/aggregator/AggregatorWithLayout.kt |  68 +----
 .../kroviz/core/aggregator/BaseAggregator.kt       |  19 +-
 .../kroviz/core/aggregator/CollectionAggregator.kt | 130 +++++---
 .../core/aggregator/DomainTypesAggregator.kt       |  21 +-
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  98 +++---
 .../kroviz/core/aggregator/SystemAggregator.kt     |  25 +-
 .../client/kroviz/core/model/BaseDisplayModel.kt   |   2 +-
 .../client/kroviz/core/model/BaseLayout.kt         |   9 +-
 .../client/kroviz/core/model/CollectionDM.kt       |  48 ++-
 .../kroviz/core/model/CollectionProperties.kt      | 122 --------
 .../client/kroviz/core/model/ColumnProperties.kt   |  29 +-
 .../kroviz/core/model/ColumnSpecification.kt       |  71 +++++
 .../{SystemDM.kt => ColumnSpecificationHolder.kt}  |  39 +--
 .../causeway/client/kroviz/core/model/DiagramDM.kt |   3 +-
 .../kroviz/core/model/DisplayModelWithLayout.kt    |  77 +----
 .../causeway/client/kroviz/core/model/ObjectDM.kt  |  58 +++-
 .../client/kroviz/core/model/ObjectLayout.kt       |  83 +++++
 .../kroviz/core/model/ObjectSpecificationHolder.kt |  69 +++++
 .../causeway/client/kroviz/core/model/SystemDM.kt  |   2 +-
 .../client/kroviz/to/PlainTransferObjects.kt       |  15 -
 .../apache/causeway/client/kroviz/to/Property.kt   |  92 ++++++
 .../apache/causeway/client/kroviz/to/TObject.kt    |   5 -
 .../apache/causeway/client/kroviz/to/bs/GridBs.kt  |  10 +
 .../causeway/client/kroviz/to/bs/PropertyBs.kt     |  11 +-
 .../client/kroviz/ui/builder/ColBuilder.kt         |  17 +-
 .../causeway/client/kroviz/ui/builder/RoDisplay.kt |   3 +-
 .../client/kroviz/ui/core/ColumnFactory.kt         |  28 +-
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |  21 +-
 .../client/kroviz/ui/dialog/EventLogDetail.kt      |  10 +-
 .../core/aggregator/CollectionAggregatorTest.kt    |  18 +-
 .../client/kroviz/core/model/CollectionDMTest.kt   |  21 +-
 .../test/resources/object-layout_collection.xml    | 337 +++++++++++++++++++++
 40 files changed, 1224 insertions(+), 543 deletions(-)
 create mode 100644 incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
 create mode 100644 incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
 copy core/config/src/main/java/org/apache/causeway/core/config/viewer/web/DialogMode.java => incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt (86%)
 delete mode 100644 incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionProperties.kt
 create mode 100644 incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecification.kt
 copy incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/{SystemDM.kt => ColumnSpecificationHolder.kt} (51%)
 create mode 100644 incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
 create mode 100644 incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectSpecificationHolder.kt
 create mode 100644 incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
 create mode 100644 incubator/clients/kroviz/src/test/resources/object-layout_collection.xml


[causeway] 04/10: ISIS-3171 table is shown, hidden/disabled/name not correctly set yet

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit cd7d1eb6b7b82fe0551a2392eb4654a952b67e95
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Tue Feb 14 17:32:40 2023 +0100

    ISIS-3171 table is shown, hidden/disabled/name not correctly set yet
---
 .../kroviz/core/aggregator/AggregatorWithLayout.kt | 17 +++++----
 .../kroviz/core/aggregator/ObjectAggregator.kt     | 13 +++++++
 .../client/kroviz/core/model/CollectionDM.kt       | 17 +++++++++
 .../client/kroviz/core/model/CollectionLayout.kt   | 22 +++++++-----
 .../causeway/client/kroviz/core/model/ObjectDM.kt  | 13 ++++---
 .../kroviz/core/model/PropertySpecification.kt     | 15 +++++++-
 .../apache/causeway/client/kroviz/to/Property.kt   | 41 +++++++---------------
 .../client/kroviz/ui/builder/ColBuilder.kt         |  6 ++--
 .../client/kroviz/ui/core/ColumnFactory.kt         |  3 +-
 .../causeway/client/kroviz/ui/core/ViewManager.kt  | 10 ++----
 10 files changed, 94 insertions(+), 63 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
index deac941a31..54eb826efe 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
@@ -19,6 +19,7 @@
 package org.apache.causeway.client.kroviz.core.aggregator
 
 import org.apache.causeway.client.kroviz.core.event.LogEntry
+import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.model.BaseLayout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.ui.core.Constants
@@ -50,18 +51,20 @@ abstract class AggregatorWithLayout : BaseAggregator() {
         invoke(l, aggregator, referrer = referrer)
     }
 
-
     protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
-        console.log("[AWL_handleProperty]")
         when {
-            property.isPropertyDescription() -> {
-                val pd = PropertyDescription(property)
-                layout.addPropertyDescription(pd, this, referrer)
-            }
-
             property.isObjectProperty() -> {
+                console.log("[AWL_handleProperty] objectProperty")
                 val op = ObjectProperty(property)
                 layout.addObjectProperty(op, this, referrer)
+                val pdLink = op.getDescriptionLink()!!
+                ResourceProxy().fetch(pdLink, this, referrer = referrer)
+            }
+
+            property.isPropertyDescription() -> {
+                console.log("[AWL_handleProperty] propertyDescription")
+                val pd = PropertyDescription(property)
+                layout.addPropertyDescription(pd, this, referrer)
             }
 
             else -> {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 351aea89cf..7f85e6f74a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -27,6 +27,7 @@ import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.ui.core.Constants
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
 import org.apache.causeway.client.kroviz.ui.dialog.ErrorDialog
+import org.apache.causeway.client.kroviz.utils.StringUtils
 
 /** sequence of operations:
  * (0) Menu Action              User clicks BasicTypes.String -> handled by ActionDispatcher
@@ -57,6 +58,8 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         }
 
         if (getDisplayModel().readyToRender()) {
+            console.log("[OA_readyToRender]")
+            console.log(getDisplayModel())
             ViewManager.openObjectView(this)
         }
     }
@@ -115,6 +118,16 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         }
     }
 
+    fun getTitle(): String {
+        var title: String = StringUtils.extractTitle(getDisplayModel().title)
+        if (title.isEmpty()) {
+            title = actionTitle
+        }
+        return title
+    }
+
+
+
     override fun reset(): ObjectAggregator {
         displayModel.reset()
         return this
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index a1c236b0ac..e0f387683b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -20,8 +20,10 @@ package org.apache.causeway.client.kroviz.core.model
 
 import io.kvision.state.observableListOf
 import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
+import org.apache.causeway.client.kroviz.utils.StringUtils
 
 class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     init {
@@ -36,16 +38,31 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
         return getLayout().readyToRender()
     }
 
+    fun getTitle(): String {
+        return StringUtils.extractTitle(title)
+    }
+
     fun getLayout(): CollectionLayout {
         return layout as CollectionLayout
     }
 
     override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
+        //TODO is checking rawdata really needed?
         if (!rawData.contains(obj)) {
             rawData.add(obj)
             val exo = Exposer(obj as TObject)
             data.add(exo.dynamise())  //if exposer is not dynamised, data access in Tabulator tables won't work
         }
+        // for the first element, invoke ObjectProperty & PropertyDescription links
+        if (rawData.size == 1) {
+            val tObj = obj as TObject
+            val properties = tObj.getProperties()
+            properties.forEach {
+                val opLink = it.getInvokeLink()!!
+                ResourceProxy().fetch(opLink, aggregator, referrer = referrer!!)
+                //FIXME is PropertyDescription automatically invoked?
+            }
+        }
     }
 
     override fun reset() {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
index dba84dd14b..5cb4d4b08b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -33,11 +33,20 @@ import org.apache.causeway.client.kroviz.to.TObject
  */
 class CollectionLayout : BaseLayout() {
     var id = ""
-    private var numberOfColumns = 0
     val propertySpecificationList = mutableListOf<PropertySpecification>()
 
     override fun readyToRender(): Boolean {
-        return isInitialized() && allPropertySpecificationsAreCreated()
+        console.log("[CL_readyToRender]")
+        return isInitialized() && arePropertySpecificationsReadyToRender()
+    }
+
+    private fun arePropertySpecificationsReadyToRender():Boolean {
+        propertySpecificationList.forEach {
+            if (!it.readyToRender()) {
+                return false
+            }
+        }
+        return true
     }
 
     /**
@@ -48,7 +57,6 @@ class CollectionLayout : BaseLayout() {
         if (!isInitialized()) {
             // members contain all properties, regardless if hidden, disabled, etc.
             val members = obj.getProperties()
-            numberOfColumns = members.size
             members.forEach { m ->
                 val ps = PropertySpecification(m)
                 propertySpecificationList.add(ps)
@@ -56,12 +64,8 @@ class CollectionLayout : BaseLayout() {
         }
     }
 
-    fun isInitialized(): Boolean {
-        return numberOfColumns > 0
-    }
-
-    private fun allPropertySpecificationsAreCreated(): Boolean {
-        return numberOfColumns == propertySpecificationList.size
+    private fun isInitialized(): Boolean {
+        return propertySpecificationList.isNotEmpty() && propertySpecificationList.size > 0
     }
 
     override fun addObjectProperty(
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index e8866bddad..b5242ecbcb 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -54,9 +54,6 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
     }
 
     fun getCollectionDisplayModelFor(id: String): CollectionDM {
-        console.log("[ODM_getCollectionDisplayModelFor]")
-        console.log(id)
-        console.log(collectionModelList)
         return collectionModelList.find { it.id == id }!!
     }
 
@@ -66,10 +63,18 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
             isRendered -> false
             layout == null -> false
             collectionModelList.size == 0 -> false
-            else -> layout!!.readyToRender() //collectionsReadyToRender()
+            else -> layout!!.readyToRender() && areCollectionsReadyToRender()
         }
     }
 
+    private fun areCollectionsReadyToRender(): Boolean {
+        collectionModelList.forEach {
+            if (!it.readyToRender())
+                return false
+        }
+        return true
+    }
+
     override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         (obj as TObject)
         val exo = Exposer(obj)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index 1ae19ea398..346fc4e236 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -19,6 +19,7 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.to.Member
+import org.apache.causeway.client.kroviz.to.ObjectProperty
 import org.apache.causeway.client.kroviz.to.PropertyDescription
 
 /**
@@ -36,6 +37,8 @@ class PropertySpecification(member: Member) {
     var name = "" // aka: columnName, named, label, title
     var hidden = false
     var disabled = false
+    var isPropertyDescriptionProcessed = false
+    var isObjectPropertyProcessed = true //FIXME
 
     init {
         id = member.id
@@ -48,14 +51,24 @@ class PropertySpecification(member: Member) {
         disabled = member.disabledReason.isNotEmpty()
     }
 
+    fun amendWith(op: ObjectProperty) {
+        console.log("[PS_amendWith] ObjectProperty")
+        //TODO
+    }
+
     fun amendWith(pd: PropertyDescription) {
-        console.log("[PS_addPropertyDescription]")
+        console.log("[PS_amendWith] PropertyDescription")
         val ex = pd.extensions!!
         val fn = ex.getFriendlyName()
         if (fn.isNotEmpty()) {
             name = fn
         }
+        isPropertyDescriptionProcessed = true
         console.log(this)
     }
 
+    fun readyToRender(): Boolean {
+        return isObjectPropertyProcessed && isPropertyDescriptionProcessed
+    }
+
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
index 718bc39fb8..cfa92fe569 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
@@ -58,21 +58,12 @@ data class Property(
  * Wraps Property in order to distinguish from PropertyDescription
  */
 class ObjectProperty(val property: Property) {
-    val id: String
-    val memberType: String
-    val links: List<Link>
-    val value: Value?
-    val extensions: Extensions?
-    val disabledReason: String?
-
-    init {
-        id = property.id
-        memberType = property.memberType
-        links = property.links
-        value = property.value
-        extensions = property.extensions
-        disabledReason = property.disabledReason
-    }
+    val id: String = property.id
+    val memberType: String = property.memberType
+    val links: List<Link> = property.links
+    val value: Value? = property.value
+    val extensions: Extensions? = property.extensions
+    val disabledReason: String? = property.disabledReason
 
     fun getDescriptionLink(): Link? {
         return this.links.firstOrNull {
@@ -85,19 +76,11 @@ class ObjectProperty(val property: Property) {
  * Wraps Property in order to distinguish from ObjectProperty
  */
 class PropertyDescription(val property: Property) {
-    val id: String
-    val memberType: String
-    val links: List<Link>
-    val value: Value?
-    val optional: Boolean?
-    val extensions: Extensions?
+    val id: String = property.id
+    val memberType: String = property.memberType
+    val links: List<Link> = property.links
+    val value: Value? = property.value
+    val optional: Boolean? = property.optional
+    val extensions: Extensions? = property.extensions
 
-    init {
-        id = property.id
-        memberType = property.memberType
-        links = property.links
-        value = property.value
-        optional = property.optional
-        extensions = property.extensions
-    }
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
index 95bd7caa9c..279a637fe2 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
@@ -69,10 +69,8 @@ class ColBuilder : UiBuilder() {
             val id = it.id
             val objectDM = dsp.displayModel
             val cdm = objectDM.getCollectionDisplayModelFor(id)
-            console.log("[CB_create]")
-            console.log(cdm)
-            val tblCpt = RoTable(cdm)
-            val fsPanel = FieldsetPanel(legend = StringUtils.capitalize(cdm.title)).add(tblCpt)
+            val fsPanel = FieldsetPanel(legend = cdm.getTitle())
+            fsPanel.add(RoTable(cdm))
             panel.add(fsPanel)
             cdm.isRendered = true
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index c63b941b53..1a710e5b7c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -106,14 +106,13 @@ class ColumnFactory {
         collectionModel: CollectionDM,
         columns: MutableList<ColumnDefinition<Exposer>>,
     ) {
-        console.log("[CF_addColumnsForProperties]")
         val clo = collectionModel.getLayout()
         val propSpecList = clo.propertySpecificationList
         if (propSpecList.size == 0) {
+            // without this, propSpecList is empty? problem with mutable list?
             throw IllegalStateException()
         }
         propSpecList.forEach {
-            console.log(it)
             if (!it.hidden) {
                 var colDef = ColumnDefinition<dynamic>(
                     title = it.name,
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 64a74f3c52..02a7d4386b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -174,14 +174,10 @@ object ViewManager {
 
     fun openObjectView(aggregator: ObjectAggregator) {
         console.log("[VM_openObjectView]")
-        val dm = aggregator.displayModel as ObjectDM
-        console.log(dm)
-        var title: String = StringUtils.extractTitle(dm.title)
-        if (title.isEmpty()) {
-            title = aggregator.actionTitle
-        }
+        val dm = aggregator.getDisplayModel()
+//        console.log(dm)
         val panel = RoDisplay(dm)
-        add(title, panel, aggregator)
+        add(aggregator.getTitle(), panel, aggregator)
         dm.isRendered = true
         setNormalCursor()
     }


[causeway] 09/10: ISIS-3171 more cleanup

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit cabe94b0c156ff6b1ef9560c411f22971a0fb3a9
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 16 23:36:07 2023 +0100

    ISIS-3171 more cleanup
---
 .../kroviz/core/aggregator/CollectionAggregator.kt | 26 +++++++++++++---------
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  5 ++---
 .../client/kroviz/core/model/CollectionDM.kt       | 24 ++------------------
 .../causeway/client/kroviz/core/model/ObjectDM.kt  |  9 ++++----
 .../client/kroviz/core/model/ObjectLayout.kt       |  7 +++---
 .../causeway/client/kroviz/core/model/SystemDM.kt  |  3 +--
 .../causeway/client/kroviz/to/bs/PropertyBs.kt     |  2 +-
 7 files changed, 30 insertions(+), 46 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index c1c4efa53f..558fda52ac 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -20,7 +20,6 @@ package org.apache.causeway.client.kroviz.core.aggregator
 
 import org.apache.causeway.client.kroviz.core.event.EventState
 import org.apache.causeway.client.kroviz.core.event.LogEntry
-import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
 import org.apache.causeway.client.kroviz.to.*
@@ -106,8 +105,18 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
             dm.setProtoType(tObj)
             invokeLayoutLink(tObj, this, referrer = referrer)
         }
-        //TODO fold layout into model
-        getDisplayModel().addObject(tObj, this, referrer = referrer)
+
+        // collection layout needs only to be initialized once with an object (pars pro toto, prototype)
+        // obj acts as a kind prototype - we assume all elements in the collection have the same structure
+        val propertySpecificationHolder = getDisplayModel().propertySpecificationHolder
+        if (!propertySpecificationHolder.isInitialized()) {
+            val members = tObj.getProperties()
+            members.forEach { m ->
+                propertySpecificationHolder.addMember(m)
+                val l = m.getInvokeLink()!!
+                invoke(l, this, referrer = referrer)
+            }
+        }
 
         invokeIconLink(tObj, this, referrer = referrer)
     }
@@ -143,7 +152,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
             property.isObjectProperty() -> {
                 val op = ObjectProperty(property)
                 val pdLink = op.getDescriptionLink()!!
-                ResourceProxy().fetch(pdLink, this, referrer = referrer)
+                invoke(pdLink, this, referrer = referrer)
             }
 
             property.isPropertyDescription() -> {
@@ -157,23 +166,20 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         }
     }
 
-
     private fun handleCollection(collection: Collection) {
         if (isParentedCollection()) {
-            //TODO is _id_ required in both CollectionDM and CollectionLayout?
-            val id = collection.id
-            getDisplayModel().id = id
+            getDisplayModel().id = collection.id
             // add displayModel to parent.displayModel
             val objectDM = parent!!.getDisplayModel()
             objectDM.addCollectionModel(getDisplayModel())
         }
         collection.links.forEach {
             if (it.relation() == Relation.DESCRIBED_BY) {
-                ResourceProxy().fetch(it, this, referrer = referrer)
+                invoke(it, this, referrer = referrer)
             }
         }
         collection.value.forEach {
-            ResourceProxy().fetch(it, this, referrer = referrer)
+            invoke(it, this, referrer = referrer)
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 3bbc286a5c..32b12dce3b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -19,7 +19,6 @@
 package org.apache.causeway.client.kroviz.core.aggregator
 
 import org.apache.causeway.client.kroviz.core.event.LogEntry
-import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.model.ObjectDM
 import org.apache.causeway.client.kroviz.core.model.ObjectLayout
 import org.apache.causeway.client.kroviz.to.*
@@ -68,7 +67,7 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         if (obj.getProperties().size == 0) {
             invokeInstance(obj, referrer)
         } else {
-            displayModel.addData(obj, this, referrer)
+            displayModel.addData(obj)
         }
         invokeLayoutLink(obj, this, referrer = referrer)
     }
@@ -113,7 +112,7 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
             ol.addGrid(grid, this, referrer = referrer)
             grid.getPropertyList().forEach {
                 val link = it.link!!
-                ResourceProxy().fetch(link, this, subType = Constants.subTypeJson, referrer = referrer)
+                invoke(link, this, subType = Constants.subTypeJson, referrer = referrer)
             }
         }
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index 881ffd0a63..84ded48825 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -19,8 +19,6 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import io.kvision.state.observableListOf
-import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
-import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
@@ -45,36 +43,18 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
         }
     }
 
-    /**
-     * collection layout needs only to be initialized once with an object (pars pro toto, prototype)
-     * obj acts as a kind prototype - we assume all elements in the collection have the same structure
-     */
-    fun addObject(obj: TObject, aggregator: CollectionAggregator, referrer: String) {
-        if (!propertySpecificationHolder.isInitialized()) {
-            // members contain all properties, regardless if hidden, disabled, etc.
-            val members = obj.getProperties()
-            members.forEach { m ->
-                propertySpecificationHolder.addMember(m)
-                val l = m.getInvokeLink()!!
-                //TODO pull up to Aggregator
-                ResourceProxy().fetch(l, aggregator, referrer = referrer)
-            }
-        }
-    }
-
     private fun addPropertyDetails(propertyBs: PropertyBs) {
         val id = propertyBs.id
-        val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
+        val ps = propertySpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyBs)
     }
 
     fun addPropertyDescription(propertyDescription: PropertyDescription) {
         val id = propertyDescription.id
-        val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
+        val ps = propertySpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyDescription)
     }
 
-
     fun hasProtoType(): Boolean {
         return protoType != null
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index 57a952fe52..3ed71589f1 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -18,7 +18,6 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
 import org.apache.causeway.client.kroviz.layout.Layout
@@ -31,7 +30,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         layout = ObjectLayout()
     }
 
-    val collectionModelList = mutableListOf<CollectionDM>()
+    private val collectionModelList = mutableListOf<CollectionDM>()
     var data: Exposer? = null
     private var dirty: Boolean = false
 
@@ -41,7 +40,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
 
     fun addCollectionModel(collectionModel: CollectionDM) {
         val id = collectionModel.id
-        val foundModel = collectionModelList.firstOrNull() {
+        val foundModel = collectionModelList.firstOrNull {
             it.id == id
         }
         if (foundModel == null) {
@@ -75,7 +74,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         return true
     }
 
-    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
+    override fun addData(obj: TransferObject) {
         (obj as TObject)
         val exo = Exposer(obj)
         data = exo.dynamise() as? Exposer
@@ -102,7 +101,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
             val href = getLink.href
             val reSpec = ResourceSpecification(href)
             val es = SessionManager.getEventStore()
-            //WATCHOUT this is sequence dependent: GET and PUT share the same URL - if called after PUTting, it may fail
+            //WATCHOUT this is sequence dependent: GET and PUT share the same URL - if called after PUTing, it may fail
             val getLogEntry = es.findBy(reSpec)!!
             getLogEntry.setReload()
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
index 9ca18153de..0d165f817e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
@@ -29,18 +29,19 @@ import org.apache.causeway.client.kroviz.to.bs.RowBs
 class ObjectLayout : BaseLayout() {
 
     var grid: GridBs? = null
-    private val collectionLayoutList = mutableListOf< CollectionLayout>()
+    //FIXME
+//    private val collectionLayoutList = mutableListOf< CollectionLayout>()
 
     override fun readyToRender(): Boolean {
         return when (grid) {
             null -> false
             else -> {
                 var answer = true
-                collectionLayoutList.forEach {
+ /*               collectionLayoutList.forEach {
                     if (!it.readyToRender()) {
                         answer = false
                     }
-                }
+                }*/
                 answer
             }
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
index 3ebf1d3deb..319a87836c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
@@ -18,7 +18,6 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.*
 
 class SystemDM(override val title: String) : BaseDisplayModel() {
@@ -32,7 +31,7 @@ class SystemDM(override val title: String) : BaseDisplayModel() {
         return !isRendered
     }
 
-    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
+    override fun addData(obj: TransferObject) {
         when (obj) {
             is User -> user = obj
             is Version -> version = obj
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
index 29d3773225..a9a42ee5cc 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
@@ -34,7 +34,7 @@ class PropertyBs(node: Node) : XmlLayout() {
     lateinit var action: ActionBs
 
     init {
-        // TODO improve casting
+        // TODO improve casting, in PropertySpecification some extra check have to be performed
         val dn = node.asDynamic()
         hidden = dn.getAttribute("hidden").unsafeCast<String>()
         id = dn.getAttribute("id").unsafeCast<String>()


[causeway] 08/10: ISIS-3171 cleanup

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 90ac2fd195c526a41d48a3a048460d3339bde612
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 16 23:03:06 2023 +0100

    ISIS-3171 cleanup
---
 .../client/kroviz/core/aggregator/CollectionAggregator.kt     |  2 +-
 .../client/kroviz/core/aggregator/DomainTypesAggregator.kt    |  4 ++--
 .../causeway/client/kroviz/core/model/BaseDisplayModel.kt     |  3 +--
 .../apache/causeway/client/kroviz/core/model/CollectionDM.kt  | 11 +++--------
 .../org/apache/causeway/client/kroviz/core/model/DiagramDM.kt |  4 +---
 5 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index d1cbfafcf9..c1c4efa53f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -148,7 +148,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
 
             property.isPropertyDescription() -> {
                 val pd = PropertyDescription(property)
-                getDisplayModel().addPropertyDescription(pd, this, referrer)
+                getDisplayModel().addPropertyDescription(pd)
             }
 
             else -> {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
index 2182089c98..06b74a3a24 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
@@ -45,7 +45,7 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
     }
 
     private fun handleProperty(obj: Property) {
-        displayModel.addData(obj, null, null)
+        displayModel.addData(obj)
     }
 
     private fun handleAction(obj: Action) {
@@ -57,7 +57,7 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
         if (obj.isPrimitiveOrService()) {
             (displayModel as DiagramDM).decNumberOfClasses()
         } else {
-            displayModel.addData(obj, null, null)
+            displayModel.addData(obj)
             val propertyList = obj.members.filter {
                 it.value.isProperty()
             }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
index 7dfe61e907..f036440e4a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
@@ -18,7 +18,6 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
 
@@ -30,7 +29,7 @@ abstract class BaseDisplayModel {
 
     abstract fun readyToRender(): Boolean
 
-    abstract fun addData(obj: TransferObject, aggregator: AggregatorWithLayout? = null, referrer: String? = null)
+    abstract fun addData(obj: TransferObject)
 
     open fun getObject(): TObject? {
         // subclass responsibility
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index 25279300ac..881ffd0a63 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -19,7 +19,6 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import io.kvision.state.observableListOf
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.PropertyDescription
@@ -57,23 +56,19 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
             members.forEach { m ->
                 propertySpecificationHolder.addMember(m)
                 val l = m.getInvokeLink()!!
+                //TODO pull up to Aggregator
                 ResourceProxy().fetch(l, aggregator, referrer = referrer)
             }
         }
     }
 
-
     private fun addPropertyDetails(propertyBs: PropertyBs) {
         val id = propertyBs.id
         val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyBs)
     }
 
-    fun addPropertyDescription(
-        propertyDescription: PropertyDescription,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
+    fun addPropertyDescription(propertyDescription: PropertyDescription) {
         val id = propertyDescription.id
         val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyDescription)
@@ -96,7 +91,7 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
         return StringUtils.extractTitle(title)
     }
 
-    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
+    override fun addData(obj: TransferObject) {
         //TODO is checking rawdata really needed?
         if (!rawData.contains(obj)) {
             rawData.add(obj)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
index 815892ca5f..fa83b82f0b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
@@ -18,11 +18,9 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.DomainType
 import org.apache.causeway.client.kroviz.to.Property
 import org.apache.causeway.client.kroviz.to.TransferObject
-import react.dom.html.ReferrerPolicy
 
 class DiagramDM(override val title: String) : BaseDisplayModel() {
 
@@ -45,7 +43,7 @@ class DiagramDM(override val title: String) : BaseDisplayModel() {
                 //TODO && numberOfProperties == properties.size
     }
 
-    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
+    override fun addData(obj: TransferObject) {
         when (obj) {
             is DomainType -> classes.add(obj)
             is Property -> properties.add(obj)


[causeway] 06/10: ISIS-3171 'sources' explicitly hidden

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 55f7e1397cef92728ce4ff5913ded14dacabe66a
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 16 18:47:13 2023 +0100

    ISIS-3171 'sources' explicitly hidden
---
 .../kroviz/core/aggregator/AggregatorWithLayout.kt | 18 ------------------
 .../kroviz/core/aggregator/CollectionAggregator.kt | 22 +++++++++++++++++++++-
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  2 +-
 .../client/kroviz/core/model/CollectionLayout.kt   | 15 +++++++++++----
 .../kroviz/core/model/PropertySpecification.kt     | 18 +++++++++++++++++-
 .../causeway/client/kroviz/to/bs/PropertyBs.kt     |  1 +
 6 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
index b114488c4f..66bcd434e3 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
@@ -51,22 +51,4 @@ abstract class AggregatorWithLayout : BaseAggregator() {
         invoke(l, aggregator, referrer = referrer)
     }
 
-    protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
-        when {
-            property.isObjectProperty() -> {
-                val op = ObjectProperty(property)
-                val pdLink = op.getDescriptionLink()!!
-                ResourceProxy().fetch(pdLink, this, referrer = referrer)
-            }
-
-            property.isPropertyDescription() -> {
-                console.log("[AWL_handleProperty] PropertyDescription obsolete?")
-            }
-
-            else -> {
-                TODO("handle 3rd type of property")
-            }
-        }
-    }
-
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 07ea8ebc5f..3a36d46fd1 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -22,11 +22,11 @@ import org.apache.causeway.client.kroviz.core.event.EventState
 import org.apache.causeway.client.kroviz.core.event.LogEntry
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
+import org.apache.causeway.client.kroviz.core.model.BaseLayout
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
 import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.to.bs.GridBs
-import org.apache.causeway.client.kroviz.ui.core.Constants
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
 
 /** sequence of operations:
@@ -148,6 +148,26 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         handleProperty(property, referrer, getLayout())
     }
 
+    protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
+        when {
+            property.isObjectProperty() -> {
+                val op = ObjectProperty(property)
+                val pdLink = op.getDescriptionLink()!!
+                ResourceProxy().fetch(pdLink, this, referrer = referrer)
+            }
+
+            property.isPropertyDescription() -> {
+                val pd = PropertyDescription(property)
+                getLayout().addPropertyDescription(pd, this, referrer)
+            }
+
+            else -> {
+                TODO("handle 3rd type of property")
+            }
+        }
+    }
+
+
     private fun handleCollection(collection: Collection) {
         if (isParentedCollection()) {
             //TODO is _id_ required in both CollectionDM and CollectionLayout?
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 7f85e6f74a..17b85d0581 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -103,7 +103,7 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
     }
 
     private fun handleProperty(property: Property, referrer: String) {
-        handleProperty(property, referrer, getLayout()) //FIXME
+        handleProperty(property, referrer) //FIXME
     }
 
     private fun handleGrid(grid: GridBs, referrer: String) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
index 92f1a48ef1..71b97e68ed 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -18,8 +18,10 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
+import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 
@@ -75,9 +77,14 @@ class CollectionLayout : BaseLayout() {
         ps.amendWith(propertyBs)
     }
 
-    // FIXME NPE -> ISIS-2846 ?
-    //FIXME hidden etc is not contained in ObjectProperty, see GidBs for the collection.protoType
-    // e.g. http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/object-layout
-    // furthermore, the column header can be taken from there as well
+    fun addPropertyDescription(
+        propertyDescription: PropertyDescription,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        val id = propertyDescription.id
+        val ps: PropertySpecification = propertySpecificationList.firstOrNull { it.id == id }!!
+        ps.amendWith(propertyDescription)
+    }
 
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index 187d464294..d70a72b0f3 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -19,6 +19,7 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.to.Member
+import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 
 /**
@@ -37,13 +38,19 @@ class PropertySpecification(member: Member) {
     var hidden = true
     var disabled = member.disabledReason.isNotEmpty()
     var isAmendedFromBs = false
+    var isAmendedFromPropertyDescription = false
     var typicalLength: Int = 10
 
 
     fun amendWith(pbs: PropertyBs) {
         console.log("[PS_amendWith] PropertyBs")
+        console.log(pbs)
         name = pbs.named
         hidden = !(pbs.hidden != null && pbs.hidden.isNotEmpty())
+        //This is hacky
+        if (id == "sources") {
+            hidden = true
+        }
         if (pbs.typicalLength != null && pbs.typicalLength > 0) {
             typicalLength = pbs.typicalLength.toInt()
         }
@@ -51,11 +58,20 @@ class PropertySpecification(member: Member) {
         console.log(this)
     }
 
+    fun amendWith(pd: PropertyDescription) {
+        val ex = pd.extensions!!
+        val fn = ex.getFriendlyName()
+        if (fn.isNotEmpty()) {
+            name = fn
+        }
+        isAmendedFromPropertyDescription = true
+    }
+
     fun readyToRender(): Boolean {
         return when (id) {
             "logicalTypeName" -> true
             "objectIdentifier" -> true
-            else -> isAmendedFromBs
+            else -> isAmendedFromBs && isAmendedFromPropertyDescription
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
index 7e76306754..4c93d3e460 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
@@ -34,6 +34,7 @@ class PropertyBs(node: Node) : XmlLayout() {
     lateinit var action: ActionBs
 
     init {
+        // TODO improve casting
         val dn = node.asDynamic()
         hidden = dn.getAttribute("hidden") //as String
         id = dn.getAttribute("id") //as String


[causeway] 01/10: ISIS-3171 Basic_Types.Strings opens, but without parentedCollection

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 77de476d96d2bd83fdf849f18e935fae2069f7d0
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Feb 1 09:39:41 2023 +0100

    ISIS-3171 Basic_Types.Strings opens, but without parentedCollection
---
 .../modules/kroviz/pages/DevelopmentGuide.adoc     |  12 +-
 .../kroviz/adoc/modules/kroviz/pages/credits.adoc  |   8 +-
 .../partials/design/class-diagram_aggregator.adoc  |   6 +-
 .../partials/design/class-diagram_layout.adoc      |   6 +-
 .../design/collection_layout_aggregation.adoc      | 160 +++++++++++++++++++++
 .../kroviz/partials/design/seq-aggregator.adoc     |   2 +-
 .../kroviz/core/aggregator/AggregatorWithLayout.kt |  81 +++--------
 .../kroviz/core/aggregator/BaseAggregator.kt       |  21 +--
 .../kroviz/core/aggregator/CollectionAggregator.kt |  58 +++++---
 .../core/aggregator/DomainTypesAggregator.kt       |  18 +--
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  87 +++++------
 .../kroviz/core/aggregator/SystemAggregator.kt     |  16 +--
 .../client/kroviz/core/model/BaseDisplayModel.kt   |   5 +-
 .../model/{BaseDisplayModel.kt => BaseLayout.kt}   |  34 +++--
 .../client/kroviz/core/model/CollectionDM.kt       |  13 +-
 .../client/kroviz/core/model/CollectionLayout.kt   |  99 +++++++++++++
 .../kroviz/core/model/CollectionProperties.kt      | 122 ----------------
 .../client/kroviz/core/model/ColumnProperties.kt   |  68 ---------
 .../causeway/client/kroviz/core/model/DiagramDM.kt |   7 +-
 .../kroviz/core/model/DisplayModelWithLayout.kt    |  77 +---------
 .../causeway/client/kroviz/core/model/ObjectDM.kt  |  27 +++-
 .../client/kroviz/core/model/ObjectLayout.kt       |  91 ++++++++++++
 .../kroviz/core/model/PropertySpecification.kt     |  67 +++++++++
 .../causeway/client/kroviz/core/model/SystemDM.kt  |   5 +-
 .../client/kroviz/to/PlainTransferObjects.kt       |  15 --
 .../apache/causeway/client/kroviz/to/Property.kt   | 103 +++++++++++++
 .../apache/causeway/client/kroviz/to/TObject.kt    |   5 -
 .../apache/causeway/client/kroviz/to/bs/GridBs.kt  |  10 ++
 .../causeway/client/kroviz/ui/builder/RoDisplay.kt |   3 +-
 .../client/kroviz/ui/core/ColumnFactory.kt         |  22 +--
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |   4 +-
 .../client/kroviz/ui/dialog/EventLogDetail.kt      |  10 +-
 .../core/aggregator/CollectionAggregatorTest.kt    |  18 +--
 .../client/kroviz/core/model/CollectionDMTest.kt   |  21 +--
 34 files changed, 776 insertions(+), 525 deletions(-)

diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/pages/DevelopmentGuide.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/pages/DevelopmentGuide.adoc
index 71c7d387b8..0d84a5efac 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/pages/DevelopmentGuide.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/pages/DevelopmentGuide.adoc
@@ -125,7 +125,7 @@ The event source acts as a Proxy and thereby saves time and bandwidth.
 ==== Aggregator (EAI)
 
 Various aggregators are responsible to collect or assemble displayable objects.
-Once all layout information is there, the UI will be rendered, even if not all elements of a list
+Once all layout information is there, the UI will be rendered, even if not all data elements of a list
 have arrived. Those elements will be added as they arrive. This is done with the help of
 mutable lists.
 
@@ -161,7 +161,7 @@ The Restful Objects API.
 
 Thanks to Kotlin, code is very compact and readable.
 And, since Kotlin is a typed language and IDE's can infer a lot about the code, there are only few surprises.
-Nevertheless Kotlin/JS allows to use JavaScript features alongside the typed part, what effectively makes it a dynamic language.
+Nevertheless, Kotlin/JS allows to use JavaScript features alongside the typed part, what effectively makes it a dynamic language.
 
 === Hot Spots
 
@@ -172,16 +172,18 @@ Look out for places where typing is escaped and the DOM is manipulated directly:
 * stopPropagation()
 * getElementById()
 
+=== Layout Aggregation
+
 
 == Trouble Shooting
 
 === Corporate Firewall with SSL 'inspection'
 
-There are some questionable setups in coporate settings that are based on SSL replacement.
+There are some questionable setups in corporate settings that are based on SSL replacement.
 In order to cope with it, you may try to import the Certificate into cacerts,
 see https://intellij-support.jetbrains.com/hc/en-us/community/posts/115000094584-IDEA-Ultimate-2016-3-4-throwing-unable-to-find-valid-certification-path-to-requested-target-when-trying-to-refresh-gradle
 
-== Network Proxy
+=== Network Proxy
 
  Depending on the network you are in, you may need to configure the proxy settings. Among the relevant files are:
  `bash
@@ -243,7 +245,7 @@ Host ssh.github.com
 ----
 
 
-== Karma-Tests do not respond to code changes
+=== Karma-Tests do not respond to code changes
 
 Windows:
 
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/pages/credits.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/pages/credits.adoc
index 1f9080097e..06e26fbac5 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/pages/credits.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/pages/credits.adoc
@@ -23,7 +23,7 @@ convert.exe WheatFieldWithCrows.jpg -channel all causeway_clut.png -clut WheatFi
 convert.exe WheatFieldWithCrows.jpg -separate -normalize -combine causeway_clut.png -clut WheatFieldWithCrows.png
 ----
 
-== Apache Causeway colors
+== Apache Isis colors
 
 In the icon: green, orange, red, blue
 
@@ -34,6 +34,12 @@ In the icon: green, orange, red, blue
 * Orange #F79646
 * Red #C0504D
 
+== Apache Colors
+https://coloropedia.com/apache-colors-logo-codes/
+
+== Irish Flag
+https://www.flagcolorcodes.com/ireland
+
 == Components Colors
 
 * "JS Runtime" #f7df1e
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_aggregator.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_aggregator.adoc
index a410388c44..8c817a6ce7 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_aggregator.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_aggregator.adoc
@@ -93,7 +93,7 @@ package "model" {
     abstract class BaseDisplayModel {
         isRendered:Boolean
         title:String
-        {abstract} canBeDisplayed():Boolean
+        {abstract} readyToRender():Boolean
     }
 
     abstract class DisplayModelWithLayout {
@@ -101,14 +101,14 @@ package "model" {
         grid: GridBs
         collectionProperties: CollectionProperties
         icon: Icon
-        + canBeDisplayed()
+        + readyToRender()
     }
 
     class ObjectDM {
         + data:Exposer
         + collections:Map<String,CollectionDM>
         - dirty:Boolean
-        + canBeDisplayed()
+        + readyToRender()
     }
     note left of ObjectDM::dirty
     Used in
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_layout.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_layout.adoc
index b1cc26b987..b41c4e35d2 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_layout.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/class-diagram_layout.adoc
@@ -52,7 +52,7 @@ Exposer..ExposerNote
 abstract class BaseDisplayModel {
     isRendered:Boolean
     title:String
-    {abstract} canBeDisplayed():Boolean
+    {abstract} readyToRender():Boolean
 }
 
 abstract class DisplayModelWithLayout {
@@ -60,7 +60,7 @@ abstract class DisplayModelWithLayout {
     grid: Grid
     collectionProperties: CollectionProperties
     icon: Icon
-    + canBeDisplayed()
+    + readyToRender()
 }
 
 DisplayModelWithLayout --> CollectionProperties
@@ -69,7 +69,7 @@ class ObjectDM {
     + data:Exposer
     + collections:Map<String,CollectionDM>
     - dirty:Boolean
-    + canBeDisplayed()
+    + readyToRender()
 }
 note left of ObjectDM::dirty
 Used in
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
new file mode 100644
index 0000000000..903ab69a23
--- /dev/null
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
@@ -0,0 +1,160 @@
+
+|===
+|repr-type |Aggregator |referrer (parent)|link
+
+|object-layout
+|ObjectAggregator
+|n/a
+|http://localhost:9090/restful/objects/demo.JavaLangStrings/PADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz48RGVtby8-/object-layout
+
+|object-collection
+|c2r2
+|object-layout
+|http://localhost:9090/restful/objects/demo.JavaLangStrings/PADw_eG1sIHZlcnNpb249IjEuMCIgZW5jb2Rpbmc9IlVURi04IiBzdGFuZGFsb25lPSJ5ZXMiPz48RGVtby8-/collections/entities
+
+|collection-description
+|out of scope
+|object-collection
+|http://localhost:9090/restful/domain-types/demo.JavaLangStrings/collections/entities
+
+|object
+|c2r4
+|object-collection
+|http://localhost:9090/restful/objects/demo.JavaLangStringEntity/355
+
+|object-property
+|c2r5
+|object
+|http://localhost:9090/restful/objects/demo.JavaLangStringEntity/355/properties/mixinProperty
+
+|property-description
+|c2r6
+|object-property
+|http://localhost:9090/restful/domain-types/demo.JavaLangStringEntity/properties/mixinProperty
+|===
+
+.Collection Layout Aggregation
+[plantuml,file="layout_aggregation.png"]
+----
+allowmixing
+
+() START
+() END
+together {
+    file "..<<xml>>..\nobject-layout" as OL
+    class "<<TransferObject>>\nGridBs" as GRID {}
+    OL . GRID
+}
+together {
+    file "..<<json>>..\nobject-collection" as OC
+    class "<<TransferObject>>\nCollection" as COL {
+        id
+        memberType= Collection
+        value[] = data
+    }
+    COL . OC
+}
+together {
+    file "<<json>>\n..object.." as O
+    class "<<TransferObject>>\nTObject" as TOBJ {
+        members[]
+    }
+    TOBJ . O
+}
+file "..<<json>>..\ncollection-description" as CD
+
+together {
+    file "..<<json>>..\nobject-property" as OP
+    class "<<TransferObject>>\nObjectProperty" as OPR {
+        disabledReason
+    }
+    OP . OPR
+}
+together {
+    file "..<<json>>..\nproperty-description" as PD
+    class "<<TransferObject>>\nPropertyDescription" as PRD {
+        extensions.friendlyName
+    }
+    PD .r. PRD
+}
+
+' references between TransferObjects (xml/json)
+START --> OL : menu action \ninvoked by user
+OL --> OC : contains\nreference\nto
+OC --> CD : contains\ncollection\ntitle
+OC --> O : contains\nreference\nto
+O --> OP : contains\nreference\nto
+OP --> PD : contains\nreference\nto
+PD --> END
+
+' references between TO classes
+GRID o->"0.n" COL
+COL o-> TOBJ : first element is required
+
+' object
+together {
+    class "ObjectAggregator" as OBJAGR {
+        collectionMap
+        update()
+        handleGrid()
+    }
+    class "ObjectDM" as OBJDM {
+        layout
+        data: Exposer
+        readyToRender()
+    }
+    class "<<2nd level aggregator>>\nObjectLayout" as OBJLO {
+        grid
+        collectionLayout:Map
+        readyToRender()
+    }
+    OBJAGR --> OBJDM
+    OBJDM --> OBJLO
+}
+OBJLO --> GRID
+
+'collection
+together {
+    class "CollectionAggregator" as COLAGR {
+        update()
+    }
+    class "CollectionDM" as COLDM {
+        layout
+        data[]: Exposer
+        readyToRender()
+    }
+    class "<<2nd level aggregator>>\nCollectionLayout" as COLLO {
+        numberOfColumns
+        columnDescriptions
+        objectPropertyList
+        propertyDescriptionList
+        readyToRender()
+    }
+    COLAGR --> COLDM
+    COLDM --> COLLO
+}
+OBJLO o-> COLLO
+' references between Layout and TO classes
+COLLO -> TOBJ
+COLLO -> OPR
+COLLO -> PRD
+
+note bottom of COLLO
+the number of columns is to be set from object/TObject
+for each attribute/property/column get object-property
+for each object-property, get the property-description (friendlyName)
+end note
+
+
+note bottom of COLAGR
+iterate over value[]
+and add data to DisplayModel
+end note
+
+OBJAGR o--> COLAGR
+----
+Colors
+TO
+AGR
+DM
+LO
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/seq-aggregator.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/seq-aggregator.adoc
index 022f57f5e7..d0628ed8a1 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/seq-aggregator.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/seq-aggregator.adoc
@@ -51,7 +51,7 @@ AGGT -> LNK : invokeWith(this)
 LNK -> XHR: invoke(this, aggt)
 deactivate AGGT
 
-AGGT -> DM : canBeDisplayed()
+AGGT -> DM : readyToRender()
 AGGT -> UI : openView()
 deactivate AGGT
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
index 36abb3376e..deac941a31 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
@@ -19,17 +19,16 @@
 package org.apache.causeway.client.kroviz.core.aggregator
 
 import org.apache.causeway.client.kroviz.core.event.LogEntry
-import org.apache.causeway.client.kroviz.core.event.ResourceProxy
-import org.apache.causeway.client.kroviz.core.model.DisplayModelWithLayout
-import org.apache.causeway.client.kroviz.layout.Layout
+import org.apache.causeway.client.kroviz.core.model.BaseLayout
 import org.apache.causeway.client.kroviz.to.*
-import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.ui.core.Constants
 import org.apache.causeway.client.kroviz.ui.diagram.Tree
 
 abstract class AggregatorWithLayout : BaseAggregator() {
-    // parentUrl is to be set in update
-    // and to be used in subsequent invocations
+    /**
+     * parentUrl is to be set in update
+     * and to be used in subsequent invocations
+     */
     private var parentUrl: String? = null
     var tree: Tree? = null
 
@@ -37,51 +36,6 @@ abstract class AggregatorWithLayout : BaseAggregator() {
         parentUrl = logEntry.url
     }
 
-    protected fun handleLayout(layout: Layout, dm: DisplayModelWithLayout, referrer: String) {
-        console.log("[AWL.handleLayout]")
-        console.log(layout)
-        if (dm.layout == null) {
-            dm.addLayout(layout)
-            dm.collectionProperties.propertyLayoutList.forEach { p ->
-                val l = p.link
-                if (l == null) {
-                    console.log(p.id + " link empty")  // ISIS-2846
-                    console.log(p)
-                } else {
-                    val isDn = l.href.contains("datanucleus")
-                    if (!isDn) {
-                        //invoking DN links leads to an error
-                        invoke(l, this, referrer = referrer)
-                    }
-                }
-            }
-        }
-    }
-
-    protected fun handleGrid(grid: GridBs, dm: DisplayModelWithLayout, referrer: String) {
-        grid.getPropertyList().forEach {
-            val link = it.link!!
-            ResourceProxy().fetch(link, this, subType = Constants.subTypeJson, referrer = referrer)
-        }
-        //FIXME
-        if (dm.grid == null) {
-            dm.addGrid(grid)
-            dm.collectionProperties.propertyLayoutList.forEach { p ->
-                val l = p.link
-                if (l == null) {
-                    console.log(p.id + " link empty")  // ISIS-2846
-                    console.log(p)
-                } else {
-                    val isDn = l.href.contains("datanucleus")
-                    if (!isDn) {
-                        //invoking DN links leads to an error
-                        invoke(l, this, referrer = referrer)
-                    }
-                }
-            }
-        }
-    }
-
     protected fun invokeLayoutLink(obj: TObject, aggregator: AggregatorWithLayout, referrer: String) {
         val l = obj.getLayoutLink()
         if (l.representation() == Represention.OBJECT_LAYOUT_BS) {
@@ -96,17 +50,24 @@ abstract class AggregatorWithLayout : BaseAggregator() {
         invoke(l, aggregator, referrer = referrer)
     }
 
-    protected fun Property.getDescriptionLink(): Link? {
-        return this.links.firstOrNull {
-            it.rel == Relation.DESCRIBED_BY.type
-        }
-    }
 
-    protected fun Property.isPropertyDescription(): Boolean {
-        val selfLink = this.links.find {
-            it.relation() == Relation.SELF
+    protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
+        console.log("[AWL_handleProperty]")
+        when {
+            property.isPropertyDescription() -> {
+                val pd = PropertyDescription(property)
+                layout.addPropertyDescription(pd, this, referrer)
+            }
+
+            property.isObjectProperty() -> {
+                val op = ObjectProperty(property)
+                layout.addObjectProperty(op, this, referrer)
+            }
+
+            else -> {
+                TODO("handle 3rd type of property")
+            }
         }
-        return selfLink!!.representation() == Represention.PROPERTY_DESCRIPTION
     }
 
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
index 4648678796..9d8a93be23 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
@@ -30,10 +30,10 @@ import org.apache.causeway.client.kroviz.utils.UrlUtils
  * An Aggregator:
  * @item is initially created in ResponseHandlers, DisplayModels, Menus
  * @item is assigned to at least one LogEntry,
- * @item is passed on to related LogEntries (eg. siblings in a list, Layout),
+ * @item is passed on to related LogEntries (e.g. siblings in a list, Layout),
  * @item is notified about changes to related LogEntries,
  * @item invokes subsequent links, and
- * @item triggers creation a view for an object or a list.
+ * @item triggers creation of a view for an object or a list.
  *
  * @see: https://www.enterpriseintegrationpatterns.com/patterns/messaging/Aggregator.html
  *
@@ -41,7 +41,7 @@ import org.apache.causeway.client.kroviz.utils.UrlUtils
  */
 abstract class BaseAggregator {
 
-    open lateinit var dpm: BaseDisplayModel
+    open lateinit var displayModel: BaseDisplayModel
 
     open fun update(logEntry: LogEntry, subType: String?) {
         /* default is do nothing - can be overridden in subclasses */
@@ -57,13 +57,12 @@ abstract class BaseAggregator {
 
     protected fun log(logEntry: LogEntry) {
         logEntry.setUndefined("no handler found")
-        console.log("[BaseAggregator.log] ")
-        console.log(logEntry)
-        console.log(logEntry.response)
         val className = this::class.simpleName
-        throw Throwable("No handler found: $className. " +
-                "Probable cause is a format change in response, that leads to a parsing error, hence response is passed on." +
-                "logEntry.obj is likely null, i.e. no TransferObject was created in parse function.")
+        throw Throwable(
+            "No handler found: $className. \n" +
+                    "response format changed, i.e. parsing error?\n" +
+                    "logEntry.obj is null, i.e. no TransferObject was created in parse function?"
+        )
     }
 
     fun TObject.getLayoutLink(): Link? {
@@ -87,12 +86,14 @@ abstract class BaseAggregator {
         return href.isNotEmpty() && UrlUtils.isObjectIcon(href)
     }
 
-    protected fun invoke(
+    fun invoke(
         link: Link,
         aggregator: BaseAggregator,
         subType: String = Constants.subTypeJson,
         referrer: String,
     ) {
+        //       console.log("[BA.invoke]")
+        //       console.log("$link ${aggregator::class.simpleName} $referrer")
         ResourceProxy().fetch(link, aggregator, subType, referrer = referrer)
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 095482251d..3dd93f44ba 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -23,8 +23,7 @@ import org.apache.causeway.client.kroviz.core.event.LogEntry
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
-import org.apache.causeway.client.kroviz.core.model.DisplayModelWithLayout
-import org.apache.causeway.client.kroviz.layout.Layout
+import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
@@ -36,16 +35,16 @@ import org.apache.causeway.client.kroviz.ui.core.ViewManager
  * (3) FR_OBJECT_PROPERTY       PropertyHandler -> invoke()
  * (4) FR_PROPERTY_DESCRIPTION  <PropertyDescriptionHandler>
  */
-class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? = null) : AggregatorWithLayout() {
+class CollectionAggregator(actionTitle: String, private val parent: ObjectAggregator? = null) : AggregatorWithLayout() {
 
     init {
-        dpm = CollectionDM(actionTitle)
+        displayModel = CollectionDM(actionTitle)
     }
 
     override fun update(logEntry: LogEntry, subType: String?) {
         super.update(logEntry, subType)
         if (logEntry.state == EventState.DUPLICATE) {
-            console.log("[CollectionAggregator.update] TODO duplicates should not be propagated to handlers")
+            throw IllegalStateException("duplicates should not be propagated to handlers")
             //TODO this may not hold true for changed and deleted objects - object version required to deal with it?
         } else {
             val referrer = logEntry.url
@@ -54,8 +53,7 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
                 is ResultList -> handleList(obj, referrer)
                 is TObject -> handleObject(obj, referrer)
                 is DomainType -> handleDomainType(obj, referrer)
-                is Layout -> handleLayout(obj, dpm as CollectionDM, referrer)
-                is GridBs -> handleGrid(obj, dpm as DisplayModelWithLayout, referrer)
+                is GridBs -> handleGrid(obj, referrer)
                 is Property -> handleProperty(obj, referrer)
                 is Collection -> handleCollection(obj, referrer)
                 is Icon -> handleIcon(obj)
@@ -63,17 +61,26 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
             }
 
             if (parent == null) {
-                if (dpm.canBeDisplayed()) {
+                if (displayModel.readyToRender()) {
                     ViewManager.openCollectionView(this)
                 }
             } else {
                 val le = LogEntry(ResourceSpecification(""))
-                //in case of a _parented_collection_ an empty LogEntry is passed on
+                // in case of a _parented_collection_ an empty LogEntry is passed on
                 parent.update(le, subType)
             }
         }
     }
 
+    private fun handleGrid(grid: GridBs, referrer: String) {
+        val cdm = displayModel as CollectionDM
+        console.log("[CA.handleGrid] In the case of CollectionDM, object-layout can be ignored?")
+        console.log(grid)
+        console.log(cdm)
+        console.log(referrer)
+        //TODO("In the case of CollectionDM, object-layout can be ignored: " + vars)
+    }
+
     private fun handleList(resultList: ResultList, referrer: String) {
         if (resultList.resulttype != ResultType.VOID.type) {
             val result = resultList.result!!
@@ -84,13 +91,24 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
     }
 
     private fun handleObject(obj: TObject, referrer: String) {
-        dpm.addData(obj)
-        invokeLayoutLink(obj, this, referrer = referrer)
+        displayModel.addData(obj, this, referrer)
+        if (isStandAloneCollection()) {
+            invokeLayoutLink(obj, this, referrer = referrer)
+        }
         invokeIconLink(obj, this, referrer = referrer)
+        // set the number of columns
+        val numberOfColumns = obj.getProperties().size
+        val cdm = displayModel as CollectionDM
+        val cl = cdm.layout as CollectionLayout
+        cl.numberOfColumns = numberOfColumns
+    }
+
+    private fun isStandAloneCollection(): Boolean {
+        return parent == null
     }
 
     private fun handleIcon(obj: TransferObject?) {
-        (dpm as CollectionDM).addIcon(obj)
+        (displayModel as CollectionDM).addIcon(obj)
     }
 
     private fun handleDomainType(obj: DomainType, referrer: String) {
@@ -107,15 +125,11 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
         }
     }
 
-    private fun handleProperty(p: Property, referrer: String) {
-        val dm = dpm as CollectionDM
-        if (p.isPropertyDescription()) {
-            dm.addPropertyDescription(p)
-        } else {
-            dm.addProperty(p)
-            val pdl = p.getDescriptionLink() ?: return
-            invoke(pdl, this, referrer = referrer)
-        }
+    private fun handleProperty(property: Property, referrer: String) {
+        console.log("[CA.handleProperty]")
+        val dm = displayModel as CollectionDM
+        val layout = dm.layout!!
+        handleProperty(property, referrer, layout)
     }
 
     private fun handleCollection(collection: Collection, referrer: String) {
@@ -130,7 +144,7 @@ class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? =
     }
 
     override fun reset(): CollectionAggregator {
-        dpm.reset()
+        displayModel.reset()
         return this
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
index f441b273a8..2182089c98 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
@@ -26,7 +26,7 @@ import org.apache.causeway.client.kroviz.ui.core.ViewManager
 class DomainTypesAggregator(val url: String) : BaseAggregator() {
 
     init {
-        dpm = DiagramDM(url)
+        displayModel = DiagramDM(url)
     }
 
     override fun update(logEntry: LogEntry, subType: String?) {
@@ -38,14 +38,14 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
             else -> log(logEntry)
         }
 
-        if (dpm.canBeDisplayed()) {
-            ViewManager.getRoStatusBar().updateDiagram(dpm as DiagramDM)
-            dpm.isRendered = true
+        if (displayModel.readyToRender()) {
+            ViewManager.getRoStatusBar().updateDiagram(displayModel as DiagramDM)
+            displayModel.isRendered = true
         }
     }
 
     private fun handleProperty(obj: Property) {
-        dpm.addData(obj)
+        displayModel.addData(obj, null, null)
     }
 
     private fun handleAction(obj: Action) {
@@ -55,13 +55,13 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
 
     private fun handleDomainType(obj: DomainType) {
         if (obj.isPrimitiveOrService()) {
-            (dpm as DiagramDM).decNumberOfClasses()
+            (displayModel as DiagramDM).decNumberOfClasses()
         } else {
-            dpm.addData(obj)
+            displayModel.addData(obj, null, null)
             val propertyList = obj.members.filter {
                 it.value.isProperty()
             }
-            (dpm as DiagramDM).incNumberOfProperties(propertyList.size)
+            (displayModel as DiagramDM).incNumberOfProperties(propertyList.size)
             propertyList.forEach {
                 invoke(it.value, this, referrer = "")
             }
@@ -100,7 +100,7 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
                 }
             }
         }
-        (dpm as DiagramDM).numberOfClasses = domainTypeLinkList.size
+        (displayModel as DiagramDM).numberOfClasses = domainTypeLinkList.size
         domainTypeLinkList.forEach {
             invoke(it, this, referrer = "")
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 285952e6dd..53b1bd1ca4 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -20,12 +20,11 @@ package org.apache.causeway.client.kroviz.core.aggregator
 
 import org.apache.causeway.client.kroviz.core.event.LogEntry
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
-import org.apache.causeway.client.kroviz.core.model.CollectionDM
-import org.apache.causeway.client.kroviz.core.model.DisplayModelWithLayout
 import org.apache.causeway.client.kroviz.core.model.ObjectDM
-import org.apache.causeway.client.kroviz.layout.Layout
+import org.apache.causeway.client.kroviz.core.model.ObjectLayout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.to.bs.GridBs
+import org.apache.causeway.client.kroviz.ui.core.Constants
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
 import org.apache.causeway.client.kroviz.ui.dialog.ErrorDialog
 
@@ -37,10 +36,11 @@ import org.apache.causeway.client.kroviz.ui.dialog.ErrorDialog
  * (4) ???_PROPERTY_DESCRIPTION  <PropertyDescriptionHandler>
  */
 class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
-    var collectionMap = mutableMapOf<String, CollectionAggregator>()
+
+    private var collectionMap = mutableMapOf<String, CollectionAggregator>()
 
     init {
-        dpm = ObjectDM(actionTitle)
+        displayModel = ObjectDM(actionTitle)
     }
 
     override fun update(logEntry: LogEntry, subType: String?) {
@@ -52,40 +52,24 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
                 is ResultObject -> handleResultObject(obj)
                 is ResultValue -> handleResultValue(obj)
                 is Property -> handleProperty(obj, referrer)
-                is Layout -> handleLayout(obj, dpm as ObjectDM, referrer)
-                is GridBs -> handleGrid(obj, dpm as DisplayModelWithLayout, referrer)
+                is GridBs -> handleGrid(obj, referrer)
                 is HttpError -> ErrorDialog(logEntry).open()
                 else -> log(logEntry)
             }
         }
 
-        if (dpm.canBeDisplayed() && collectionsCanBeDisplayed()) {
-            collectionMap.forEach {
-                (dpm as ObjectDM).addCollection(it.key, it.value.dpm as CollectionDM)
-            }
-            console.log("[OA.canBeDisplayed]")
-            console.log(this)
-            console.log((dpm as DisplayModelWithLayout).collectionProperties.debug())
-
+        if (displayModel.readyToRender()) {
             ViewManager.openObjectView(this)
         }
     }
 
-    private fun collectionsCanBeDisplayed(): Boolean {
-        if (collectionMap.isEmpty()) return true
-        return collectionMap.all {
-            val cdm = it.value.dpm as CollectionDM
-            cdm.canBeDisplayed()
-        }
-    }
-
     private fun handleObject(obj: TObject, referrer: String) {
         // After ~/action/invoke is called, the actual object instance (containing properties) needs to be invoked as well.
         // Note that rel.self/href is identical and both are of type TObject. logEntry.url is different, though.
         if (obj.getProperties().size == 0) {
             invokeInstance(obj, referrer)
         } else {
-            dpm.addData(obj)
+            displayModel.addData(obj, this, referrer)
         }
         if (collectionMap.isEmpty()) {
             handleCollections(obj, referrer)
@@ -101,46 +85,63 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
     }
 
     private fun handleResultObject(resultObject: ResultObject) {
-        (dpm as ObjectDM).addResult(resultObject)
+        (displayModel as ObjectDM).addResult(resultObject)
     }
 
     private fun handleResultValue(resultValue: ResultValue) {
-// TODO       (dpm as ObjectDM).addResult(resultObject)
-        console.log("[OA.handleResultValue]")
-        console.log(resultValue)
+        throw NotImplementedError("$resultValue to be handled")
     }
 
     override fun getObject(): TObject? {
-        return dpm.getObject()
+        return displayModel.getObject()
     }
 
     private fun handleCollections(obj: TObject, referrer: String) {
-        console.log("[OA.handleCollections]")
-        console.log(obj)
-        obj.getCollections().forEach {
-            console.log(it)
+        console.log("[OA_handleCollection] collections")
+        val collections = obj.getCollections()
+        console.log(collections)
+        collections.forEach {
             val key = it.id
             val aggregator = CollectionAggregator(key, this)
             collectionMap[key] = aggregator
             val link = it.links.first()
-            console.log(link)
             ResourceProxy().fetch(link, aggregator, referrer = referrer)
         }
     }
 
-    private fun handleProperty(p: Property, referrer: String) {
-        val dm = dpm as ObjectDM
-        if (p.isPropertyDescription()) {
-            dm.addPropertyDescription(p)
-        } else {
-            dm.addProperty(p)
-            val pdl = p.getDescriptionLink() ?: return
-            invoke(pdl, this, referrer = referrer)
+    private fun handleProperty(property: Property, referrer: String) {
+        val dm = displayModel as ObjectDM
+        val layout = dm.layout!!
+        handleProperty(property, referrer, layout)
+    }
+
+    private fun handleGrid(grid: GridBs, referrer: String) {
+        val odm = displayModel as ObjectDM
+        val ol = odm.layout as ObjectLayout
+        // for a yet unknown reason, handleGrid may be called twice, therefore we check if it's already set
+        if (ol.grid == null) {
+            console.log("[OA_handleGrid]")
+            ol.addGrid(grid, this, referrer = referrer)
+            val pl = grid.getPropertyList()
+            pl.forEach {
+                val link = it.link!!
+                // properties to be handled by ObjectAggregator
+                ResourceProxy().fetch(link, this, subType = Constants.subTypeJson, referrer = referrer)
+            }
+            val cl = grid.getCollectionList()
+            cl.forEach {
+                val href = it.linkList.first().href
+                console.log("CollectionBs")
+                console.log(href)
+                val l = Link(href = href)
+                // collections to be handled by ObjectAggregator
+                ResourceProxy().fetch(l, this, subType = Constants.subTypeJson, referrer = referrer)
+            }
         }
     }
 
     override fun reset(): ObjectAggregator {
-        dpm.isRendered = false
+        displayModel.reset()
         return this
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
index 42d1599054..d50d3e764c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
@@ -30,14 +30,14 @@ import org.apache.causeway.client.kroviz.utils.UrlUtils
 class SystemAggregator() : BaseAggregator() {
 
     init {
-        dpm = SystemDM("not filled (yet)")
+        displayModel = SystemDM("not filled (yet)")
     }
 
     override fun update(logEntry: LogEntry, subType: String?) {
         when (val obj = logEntry.getTransferObject()) {
-            is User -> dpm.addData(obj)
-            is Version -> dpm.addData(obj)
-            is DomainTypes -> dpm.addData(obj)
+            is User -> displayModel.addData(obj)
+            is Version -> displayModel.addData(obj)
+            is DomainTypes -> displayModel.addData(obj)
             else -> {
                 if (logEntry.blob != null) {
                     val icon = ImageUtils.extractIcon(logEntry)
@@ -45,11 +45,11 @@ class SystemAggregator() : BaseAggregator() {
                     val isApplicationIcon = UrlUtils.isApplicationIcon(url)
                     when (isApplicationIcon) {
                         url.contains("48") -> {
-                            (dpm as SystemDM).addSmallIcon(icon)
+                            (displayModel as SystemDM).addSmallIcon(icon)
                             val iconUrl = icon.image.src
                             SessionManager.setApplicationIcon(iconUrl)
                         }
-                        url.contains("256") -> (dpm as SystemDM).addLargeIcon(icon)
+                        url.contains("256") -> (displayModel as SystemDM).addLargeIcon(icon)
                         else -> log(logEntry)
                     }
                 } else {
@@ -58,13 +58,13 @@ class SystemAggregator() : BaseAggregator() {
             }
         }
 
-        if (dpm.canBeDisplayed()) {
+        if (displayModel.readyToRender()) {
 //  TODO          UiManager.openObjectView(this)
         }
     }
 
     override fun reset(): SystemAggregator {
-        dpm.isRendered = false
+        displayModel.isRendered = false
         return this
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
index 296c6ed89a..7dfe61e907 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
 
@@ -27,9 +28,9 @@ abstract class BaseDisplayModel {
 
     abstract val title: String
 
-    abstract fun canBeDisplayed(): Boolean
+    abstract fun readyToRender(): Boolean
 
-    abstract fun addData(obj: TransferObject)
+    abstract fun addData(obj: TransferObject, aggregator: AggregatorWithLayout? = null, referrer: String? = null)
 
     open fun getObject(): TObject? {
         // subclass responsibility
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
similarity index 60%
copy from incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
copy to incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
index 296c6ed89a..55d0856cdd 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseDisplayModel.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
@@ -18,26 +18,24 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.to.TObject
-import org.apache.causeway.client.kroviz.to.TransferObject
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.to.ObjectProperty
+import org.apache.causeway.client.kroviz.to.PropertyDescription
 
-abstract class BaseDisplayModel {
+abstract class BaseLayout {
 
-    var isRendered = false
+    abstract fun addObjectProperty(
+        property: ObjectProperty,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    )
 
-    abstract val title: String
+    abstract fun addPropertyDescription(
+        property: PropertyDescription,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    )
 
-    abstract fun canBeDisplayed(): Boolean
+    abstract fun readyToRender(): Boolean
 
-    abstract fun addData(obj: TransferObject)
-
-    open fun getObject(): TObject? {
-        // subclass responsibility
-        return null
-    }
-
-    open fun reset() {
-        // subclass responsibility
-    }
-
-}
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index fd009de601..45cb4f48f3 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -19,16 +19,23 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import io.kvision.state.observableListOf
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
 
 class CollectionDM(override val title: String) : DisplayModelWithLayout() {
+    init {
+        layout = CollectionLayout()
+    }
+
     var data = observableListOf<Exposer>()
     private var rawData = observableListOf<TransferObject>()
 
-    override fun addData(obj: TransferObject) {
- //       console.log("[CDM.addData]")
- //       console.log(obj)
+    override fun readyToRender(): Boolean {
+        return (layout as CollectionLayout).readyToRender()
+    }
+
+    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         if (!rawData.contains(obj)) {
             rawData.add(obj)
             val exo = Exposer(obj as TObject)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
new file mode 100644
index 0000000000..c2ab4612b3
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -0,0 +1,99 @@
+/*
+ *  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.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.event.ResourceProxy
+import org.apache.causeway.client.kroviz.to.ObjectProperty
+import org.apache.causeway.client.kroviz.to.PropertyDescription
+
+/**
+ * For (parented) collections aggregate information for each column
+ * in order to display the table, namely:
+ * - columnName :   column header/label
+ * - id :           attribute to be used to retrieve the value of each cell (id)
+ * - hidden :       will the column be displayed or not
+ */
+class CollectionLayout : BaseLayout() {
+    var numberOfColumns = 0
+    private val propertySpecificationMap = mutableMapOf<String, PropertySpecification>()
+    private val objectPropertyList = mutableListOf<ObjectProperty>()
+    private val propertyDescriptionList = mutableListOf<PropertyDescription>()
+
+    override fun readyToRender(): Boolean {
+        console.log("[CL.readyToRender]")
+        console.log(this)
+        return (numberOfColumns > 0) &&
+                (numberOfColumns == propertyDescriptionList.size)
+    }
+
+    /**
+     * One element is to be added for each column.
+     * Duplicates are not allowed.
+     */
+    override fun addObjectProperty(
+        objectProperty: ObjectProperty,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        objectPropertyList.add(objectProperty)
+        val l = objectProperty.getDescriptionLink()!!
+        // FIXME NPE -> ISIS-2846 ?
+        //invoking DN links leads to an error
+        val isDn = l.href.contains("datanucleus") // Outdated?
+        if (!isDn) {
+            ResourceProxy().fetch(l, aggregator, referrer = referrer)
+        }
+        updatePropertySpecification(objectProperty)
+    }
+
+    override fun addPropertyDescription(
+        propertyDescription: PropertyDescription,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        console.log("[CL.addPropertyDescription]")
+        propertyDescriptionList.add(propertyDescription)
+        updatePropertySpecification(propertyDescription)
+    }
+
+    private fun updatePropertySpecification(propertyDescription: PropertyDescription) {
+        val ps: PropertySpecification = findOrCreateFor(propertyDescription.id)
+        ps.addPropertyDescription(propertyDescription)
+    }
+
+    private fun updatePropertySpecification(objectProperty: ObjectProperty) {
+        val ps: PropertySpecification = findOrCreateFor(objectProperty.id)
+        ps.addObjectProperty(objectProperty)
+    }
+
+    private fun findOrCreateFor(id: String): PropertySpecification {
+        var ps = propertySpecificationMap[id]
+        if (ps == null) {
+            ps = PropertySpecification(id)
+            propertySpecificationMap[id] = ps
+        }
+        return ps
+    }
+
+    fun getColumnDescriptions(): List<PropertySpecification> {
+        return propertySpecificationMap.values.toList()
+    }
+
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionProperties.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionProperties.kt
deleted file mode 100644
index 9a1a3f3f6b..0000000000
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionProperties.kt
+++ /dev/null
@@ -1,122 +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.causeway.client.kroviz.core.model
-
-import org.apache.causeway.client.kroviz.layout.PropertyLt
-import org.apache.causeway.client.kroviz.to.Extensions
-import org.apache.causeway.client.kroviz.to.Property
-import org.apache.causeway.client.kroviz.to.bs.PropertyBs
-
-class CollectionProperties() {
-    val list = mutableListOf<ColumnProperties>()
-    var propertyDescriptionList = mutableListOf<Property>()
-    var propertyLayoutList = mutableListOf<PropertyLt>()
-    var propertyGridList = mutableListOf<PropertyBs>()
-    var propertyList = mutableListOf<Property>()
-    var descriptionsComplete = false
-
-    fun debug(): String {
-        var answer = "descriptionsComplete: $descriptionsComplete"
-
-        answer = answer + "\nlist: ${list.size}"
-        console.log("[CP.debug] List of ColumnProperties")
-        console.log(list)
-
-        answer = answer + "\npropertyDescriptionList: ${propertyDescriptionList.size}"
-        console.log("[CP.debug] List of Property (Description)")
-        console.log(propertyDescriptionList)
-
-        answer = answer + "\npropertyLayoutList: ${propertyLayoutList.size}"
-        console.log("[CP.debug] List of PropertyLt")
-        console.log(propertyLayoutList)
-
-        answer = answer + "\npropertyGridList: ${propertyGridList.size}"
-        console.log("[CP.debug] List of PropertyBs")
-        console.log(propertyGridList)
-
-        answer = answer + "\npropertyList: ${propertyList.size}"
-        console.log("[CP.debug] List of Property")
-        console.log(propertyList)
-
-        return answer
-    }
-
-    fun readyForDisplay(): Boolean {
-        val ps = propertyList.size
-        val pls = propertyLayoutList.size
-        val pds = propertyDescriptionList.size
-        descriptionsComplete = (pds >= pls) && (ps >= pls)
-        return descriptionsComplete
-    }
-
-    fun addProperty(property: Property) {
-        console.log("[CollectionProperties.addProperty]")
-        console.log(property)
-        propertyList.add(property)
-        console.log(propertyList)
-        val id = property.id
-        val cp = findOrCreate(id)
-        cp.property = property
-    }
-
-    fun addAllPropertyLayout(layoutList: List<PropertyLt>) {
-        propertyLayoutList.addAll(layoutList)
-        fun addPropertyLayout(layout: PropertyLt) {
-            val id = layout.id!!
-            val cp = findOrCreate(id)
-            cp.initLayout(layout)
-        }
-        layoutList.forEach { addPropertyLayout(it) }
-    }
-
-    fun addAllPropertyGrid(gridList: List<PropertyBs>) {
-//        console.log("[DMWL.addAllPropertyGrid]")
-        propertyGridList.addAll(gridList)
-        fun addPropertyGrid(grid: PropertyBs) {
-//            console.log("[DMWL.addPropertyGrid] -> grid")
-//            console.log(grid)
-            val id = grid.id
-            val cp = findOrCreate(id)
-            cp.initGrid(grid)
-        }
-        gridList.forEach { addPropertyGrid(it) }
-    }
-
-    fun addPropertyDescription(description: Property) {
-        propertyDescriptionList.add(description)
-        val id = description.id
-        val cp = findOrCreate(id)
-        val e: Extensions = description.extensions!!
-        cp.friendlyName = e.getFriendlyName()
-    }
-
-    private fun findOrCreate(id: String): ColumnProperties {
-        var cp = find(id)
-        if (cp == null) {
-            cp = ColumnProperties(id)
-            list.add(cp)
-        }
-        return cp
-    }
-
-    fun find(id: String): ColumnProperties? {
-        return list.find { it.key == id }
-    }
-
-}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt
deleted file mode 100644
index 173985456a..0000000000
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt
+++ /dev/null
@@ -1,68 +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.causeway.client.kroviz.core.model
-
-import org.apache.causeway.client.kroviz.layout.PropertyLt
-import org.apache.causeway.client.kroviz.to.Property
-import org.apache.causeway.client.kroviz.to.bs.PropertyBs
-
-/**
- * Properties have three aspects:
- *
- * - Member of a DomainObject
- * - Description (friendlyName, etc.)
- * - Layout (hidden, labelPosition, etc.)
- *
- * All three are required in order to display correctly in a table.
- */
-class ColumnProperties(val key: String) {
-    var property: Property? = null
-    var friendlyName: String = ""
-    var layout: PropertyLt? = null
-    var grid: PropertyBs? = null
-    var hidden: Boolean = false
-
-    fun debug(): String {
-        return "property: " + property?.id
-    }
-
-    fun initLayout(layout: PropertyLt) {
-        this.layout = layout
-        console.log("[CP.initLayout]")
-
-        hidden = (layout.hidden != null)
-        // properties without labelPosition will be hidden - is that correct?
-        // example: Demo -> Strings -> Description
-        if (!hidden && layout.labelPosition == null) {
-            hidden = true
-        }
-    }
-
-    fun initGrid(grid: PropertyBs) {
-        this.grid = grid
-        console.log("[CP.initGrid]")
-//FIXME        hidden = (property.hidden != null)
-        // properties without labelPosition will be hidden - is that correct?
-        // example: Demo -> Strings -> Description
-        //  if (!hidden && property.labelPosition == null) {
-        //     hidden = true
-        // }
-    }
-
-}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
index 72e653d226..815892ca5f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DiagramDM.kt
@@ -18,9 +18,11 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.DomainType
 import org.apache.causeway.client.kroviz.to.Property
 import org.apache.causeway.client.kroviz.to.TransferObject
+import react.dom.html.ReferrerPolicy
 
 class DiagramDM(override val title: String) : BaseDisplayModel() {
 
@@ -37,14 +39,13 @@ class DiagramDM(override val title: String) : BaseDisplayModel() {
         numberOfClasses--
     }
 
-    override fun canBeDisplayed(): Boolean {
+    override fun readyToRender(): Boolean {
         if (isRendered) return false
         return (numberOfClasses == classes.size)
                 //TODO && numberOfProperties == properties.size
-
     }
 
-    override fun addData(obj: TransferObject) {
+    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         when (obj) {
             is DomainType -> classes.add(obj)
             is Property -> properties.add(obj)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DisplayModelWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DisplayModelWithLayout.kt
index 5bc2f1c137..2b9921608a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DisplayModelWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/DisplayModelWithLayout.kt
@@ -19,91 +19,18 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.layout.Layout
-import org.apache.causeway.client.kroviz.layout.RowLt
 import org.apache.causeway.client.kroviz.to.Icon
-import org.apache.causeway.client.kroviz.to.Property
 import org.apache.causeway.client.kroviz.to.TransferObject
-import org.apache.causeway.client.kroviz.to.bs.GridBs
-import org.apache.causeway.client.kroviz.to.bs.RowBs
 
 abstract class DisplayModelWithLayout : BaseDisplayModel() {
 
-    var layout: Layout? = null
-    var grid: GridBs? = null
-    val collectionProperties = CollectionProperties()
+    var layout: BaseLayout? = null
     var icon: Icon? = null
 
-    override fun canBeDisplayed(): Boolean {
-        return when {
-            isRendered -> false
-            layout == null && grid == null -> false
-            else -> collectionProperties.readyForDisplay()
-        }
-    }
-
-    fun addLayout(layout: Layout) {
-        this.layout = layout
-        initPropertyLayoutList(layout)
-    }
-
-    fun addGrid(grid: GridBs) {
-        this.grid = grid
-        initPropertyGridList(grid)
-    }
-
     fun addIcon(obj: TransferObject?) {
         icon = obj as Icon
     }
 
-    private fun initPropertyLayoutList(layout: Layout) {
-        layout.row.forEach { r ->
-            initLayout4Row(r)
-        }
-    }
-
-    private fun initPropertyGridList(grid: GridBs) {
-        grid.rows.forEach { r ->
-            initGrid4Row(r)
-        }
-    }
-
-    private fun initLayout4Row(r: RowLt) {
-        r.cols.forEach { cs ->
-            val c = cs.getCol()
-            c.fieldSet.forEach { fs ->
-                collectionProperties.addAllPropertyLayout(fs.property)
-            }
-            c.tabGroup.forEach { tg ->
-                tg.tab.forEach { t ->
-                    t.row.forEach { r2 ->
-                        initLayout4Row(r2)
-                    }
-                }
-            }
-        }
-    }
-
-    private fun initGrid4Row(r: RowBs) {
-        r.colList.forEach { c ->
-            c.fieldSetList.forEach { fs ->
-                collectionProperties.addAllPropertyGrid(fs.propertyList)
-            }
-            c.tabGroupList.forEach { tg ->
-                tg.tabList.forEach { t ->
-                    t.rowList.forEach { r2 ->
-                        initGrid4Row(r2)
-                    }
-                }
-            }
-        }
-    }
-
-    fun addPropertyDescription(p: Property) {
-        collectionProperties.addPropertyDescription(p)
-    }
-
-    fun addProperty(property: Property) {
-        collectionProperties.addProperty(property)
-    }
+    open fun addLayout(lt: Layout) {}
 
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index d33ef1fc8c..f4e67d73a0 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -18,31 +18,48 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
+import org.apache.causeway.client.kroviz.layout.Layout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.ui.core.SessionManager
 
 class ObjectDM(override val title: String) : DisplayModelWithLayout() {
-    var data: Exposer? = null
+
+    init {
+        layout = ObjectLayout()
+    }
+
     val collectionMap = mutableMapOf<String, CollectionDM>()
+    var data: Exposer? = null
     private var dirty: Boolean = false
 
     fun setDirty(value: Boolean) {
         dirty = value
     }
 
-    fun addCollection(key: String, value: CollectionDM) {
-        collectionMap[key] = value
+    override fun addLayout(lt: Layout) {
+        TODO("Not yet implemented")
+    }
+
+    override fun readyToRender(): Boolean {
+        return when {
+            data == null -> false
+            isRendered -> false
+            layout == null -> false
+            else -> layout!!.readyToRender() //collectionsReadyToRender()
+        }
     }
 
-    override fun addData(obj: TransferObject) {
+    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         (obj as TObject)
         val exo = Exposer(obj)
         data = exo.dynamise() as? Exposer
         obj.getProperties().forEach { m ->
             val p = createPropertyFrom(m)
-            addProperty(p)
+            val op = ObjectProperty(p)
+            layout?.addObjectProperty(op, aggregator!!, referrer!!)
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
new file mode 100644
index 0000000000..9f8472a14a
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
@@ -0,0 +1,91 @@
+/*
+ *  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.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.event.ResourceProxy
+import org.apache.causeway.client.kroviz.to.Link
+import org.apache.causeway.client.kroviz.to.ObjectProperty
+import org.apache.causeway.client.kroviz.to.PropertyDescription
+import org.apache.causeway.client.kroviz.to.bs.GridBs
+import org.apache.causeway.client.kroviz.to.bs.RowBs
+
+class ObjectLayout : BaseLayout() {
+
+    var grid: GridBs? = null
+    private val collectionLayoutMap = mutableMapOf<String, CollectionLayout>()
+
+    override fun readyToRender(): Boolean {
+        console.log("[OL_readyToRender]")
+        return when (grid) {
+            null -> false
+            else -> {
+                var answer = true
+                collectionLayoutMap.values.forEach {
+                    console.log(it)
+                    if (!it.readyToRender()) answer = false
+                }
+                answer
+            }
+        }
+    }
+
+    override fun addObjectProperty(
+        property: ObjectProperty,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        TODO("Not yet implemented")
+    }
+
+    override fun addPropertyDescription(
+        property: PropertyDescription,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        TODO("Not yet implemented")
+    }
+
+    fun addGrid(grid: GridBs, aggregator: AggregatorWithLayout?, referrer: String?) {
+        this.grid = grid
+        grid.rows.forEach { r ->
+            initRow(r, aggregator!!, referrer = referrer!!)
+        }
+    }
+
+    private fun initRow(r: RowBs, aggregator: AggregatorWithLayout, referrer: String) {
+        r.colList.forEach { c ->
+            c.collectionList.forEach { col ->
+                collectionLayoutMap[col.id] =
+                    CollectionLayout() // create empty entry for id - for later usage when response arrives
+                val href = col.linkList.first().href // we assume, linklist has always one element
+                val l = Link(href = href)
+                ResourceProxy().fetch(l, aggregator, referrer = referrer)
+            }
+            c.tabGroupList.forEach { tg ->
+                tg.tabList.forEach { t ->
+                    t.rowList.forEach { r2 ->
+                        initRow(r2, aggregator, referrer)
+                    }
+                }
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
new file mode 100644
index 0000000000..935a9a2d13
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -0,0 +1,67 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.to.ObjectProperty
+import org.apache.causeway.client.kroviz.to.PropertyDescription
+
+/**
+ * Properties have multiple aspects:
+ *
+ * - Member of a DomainObject
+ * - Description (friendlyName, etc.)
+ * - Layout (disabledReason, labelPosition, etc.)
+ * - Visibility (hidden)
+ *
+ * All are required in order to be correctly displayed (in a table).
+ */
+class PropertySpecification(val id: String) {
+    var name = "" // aka: columnName, named, label
+    var hidden = false
+    var disabledReason = ""
+
+    fun addObjectProperty(op: ObjectProperty) {}
+    fun addPropertyDescription(pd: PropertyDescription) {
+        val ex = pd.extensions!!
+        name = ex.getFriendlyName()
+        if (name.isEmpty()) {
+            name = id
+            console.log(pd)
+        }
+    }
+    //FIXME use setter Methods using:
+    /** Property
+     *ObjectProperty
+    PropertyDescription */
+    /*init {
+        id = grid.id
+        when {
+            grid.named.isNotEmpty() -> columnName = grid.named
+            else -> columnName = id
+        }
+        //       console.log("[CD.init]")
+        when {
+            // grid.hidden can be null -- intellij inference is wrong
+            (grid.hidden == null) || grid.hidden.isEmpty() -> {}
+            grid.hidden.contains("TABLE") -> hidden = true
+        }
+        //       console.log("$id $columnName Hidden: $hidden")
+    } */
+
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
index af7996d672..3ebf1d3deb 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/SystemDM.kt
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
+import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.to.*
 
 class SystemDM(override val title: String) : BaseDisplayModel() {
@@ -27,11 +28,11 @@ class SystemDM(override val title: String) : BaseDisplayModel() {
     var logoSmall: Icon? = null
     var logoLarge: Icon? = null
 
-    override fun canBeDisplayed(): Boolean {
+    override fun readyToRender(): Boolean {
         return !isRendered
     }
 
-    override fun addData(obj: TransferObject) {
+    override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         when (obj) {
             is User -> user = obj
             is Version -> version = obj
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/PlainTransferObjects.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/PlainTransferObjects.kt
index 61f27f9bd7..50a207a07b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/PlainTransferObjects.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/PlainTransferObjects.kt
@@ -110,21 +110,6 @@ enum class Position(val type: String) {
     PANEL_DROPDOWN("PANEL_DROPDOWN")
 }
 
-@Serializable
-data class Property(
-    val id: String = "",
-    val memberType: String = "",
-    override val links: List<Link> = emptyList(),
-    val optional: Boolean? = null,
-    val title: String? = null,
-    val value: Value? = null,
-    val extensions: Extensions? = null,
-    val format: String? = null,
-    val disabledReason: String? = null,
-    val parameters: List<Parameter> = emptyList(),
-    val maxLength: Int = 0
-) : TransferObject, WithLinks
-
 @Serializable
 data class Restful(
     val userName: String? = null,
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
new file mode 100644
index 0000000000..718bc39fb8
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
@@ -0,0 +1,103 @@
+/*
+ *  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.causeway.client.kroviz.to
+
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class Property(
+    val id: String = "",
+    val memberType: String = "",
+    override val links: List<Link> = emptyList(),
+    val optional: Boolean? = null,
+    val title: String? = null,
+    val value: Value? = null,
+    val extensions: Extensions? = null,
+    val format: String? = null,
+    val disabledReason: String? = null,
+    val parameters: List<Parameter> = emptyList(),
+    val maxLength: Int = 0
+) : TransferObject, WithLinks {
+
+    fun isObjectProperty(): Boolean {
+        return getType() == Represention.OBJECT_PROPERTY
+    }
+
+    fun isPropertyDescription(): Boolean {
+        return getType() == Represention.PROPERTY_DESCRIPTION
+    }
+
+    private fun getType(): Represention {
+        return getSelfLink().representation()
+    }
+
+    private fun getSelfLink(): Link {
+        return links.first {
+            it.relation() == Relation.SELF
+        }
+    }
+}
+
+/**
+ * Wraps Property in order to distinguish from PropertyDescription
+ */
+class ObjectProperty(val property: Property) {
+    val id: String
+    val memberType: String
+    val links: List<Link>
+    val value: Value?
+    val extensions: Extensions?
+    val disabledReason: String?
+
+    init {
+        id = property.id
+        memberType = property.memberType
+        links = property.links
+        value = property.value
+        extensions = property.extensions
+        disabledReason = property.disabledReason
+    }
+
+    fun getDescriptionLink(): Link? {
+        return this.links.firstOrNull {
+            it.rel == Relation.DESCRIBED_BY.type
+        }
+    }
+}
+
+/**
+ * Wraps Property in order to distinguish from ObjectProperty
+ */
+class PropertyDescription(val property: Property) {
+    val id: String
+    val memberType: String
+    val links: List<Link>
+    val value: Value?
+    val optional: Boolean?
+    val extensions: Extensions?
+
+    init {
+        id = property.id
+        memberType = property.memberType
+        links = property.links
+        value = property.value
+        optional = property.optional
+        extensions = property.extensions
+    }
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/TObject.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/TObject.kt
index bee1d7fca0..4a322468a5 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/TObject.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/TObject.kt
@@ -66,9 +66,4 @@ data class TObject(override val links: List<Link> = emptyList(),
         }
     }
 
-    fun getSelfLink() : Link {
-        return this.links.first {
-            it.relation() == Relation.SELF
-        }
-    }
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/GridBs.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/GridBs.kt
index ed2fc3caf7..85d253a317 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/GridBs.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/GridBs.kt
@@ -52,4 +52,14 @@ class GridBs(document: Document) : XmlLayout(), TransferObject {
         return list
     }
 
+    fun getCollectionList(): List<CollectionBs> {
+        val list = mutableListOf<CollectionBs>()
+        rows.forEach { r ->
+            r.colList.forEach { cl ->
+                list.addAll(cl.collectionList)
+            }
+        }
+        return list
+    }
+
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/RoDisplay.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/RoDisplay.kt
index 207460f44e..ac71944687 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/RoDisplay.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/RoDisplay.kt
@@ -22,6 +22,7 @@ import io.kvision.core.*
 import io.kvision.dropdown.DropDown
 import io.kvision.panel.VPanel
 import org.apache.causeway.client.kroviz.core.model.ObjectDM
+import org.apache.causeway.client.kroviz.core.model.ObjectLayout
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.ui.core.Displayable
 import org.apache.causeway.client.kroviz.ui.menu.DropDownMenuBuilder
@@ -34,7 +35,7 @@ class RoDisplay(val displayModel: ObjectDM) : Displayable, VPanel() {
     init {
         val model = displayModel.data!!
         val tObject: TObject = model.delegate
-        val grid = displayModel.grid!!
+        val grid = (displayModel.layout as ObjectLayout).grid!!
         objectPanel = LayoutBuilder().create(grid, tObject, this)
         objectPanel.overflow = Overflow.AUTO
         objectPanel.width = CssSize(100, UNIT.perc)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index c27c0c3957..4b8bc9eb3a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -25,6 +25,7 @@ import io.kvision.tabulator.Formatter
 import io.kvision.tabulator.js.Tabulator
 import io.kvision.utils.obj
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
+import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.core.model.Exposer
 import org.apache.causeway.client.kroviz.ui.menu.DynamicMenuBuilder
 
@@ -103,19 +104,18 @@ class ColumnFactory {
         displayCollection: CollectionDM,
         columns: MutableList<ColumnDefinition<Exposer>>,
     ) {
-        val propertyLabels = displayCollection.collectionProperties.list
-        for (pl in propertyLabels) {
-            if (!pl.hidden) {
-                val id = pl.key
-                val friendlyName = pl.friendlyName
-                var cd = ColumnDefinition<dynamic>(
-                    title = friendlyName,
-                    field = id,
+        val cl = displayCollection.layout as CollectionLayout
+        val colDescList = cl.getColumnDescriptions()
+        for (cd in colDescList) {
+            if (!cd.hidden) {
+                var colDef = ColumnDefinition<dynamic>(
+                    title = cd.name,
+                    field = cd.id,
                     headerFilter = Editor.INPUT)
-                if (id == "object") {
-                    cd = buildLink()
+                if (cd.id == "object") {
+                    colDef = buildLink()
                 }
-                columns.add(cd)
+                columns.add(colDef)
             }
         }
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 5844f3913a..3ce091643e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -164,7 +164,7 @@ object ViewManager {
     }
 
     fun openCollectionView(aggregator: BaseAggregator) {
-        val displayable = aggregator.dpm
+        val displayable = aggregator.displayModel
         val title: String = StringUtils.extractTitle(displayable.title)
         val panel = RoTable(displayable as CollectionDM)
         add(title, panel, aggregator)
@@ -173,7 +173,7 @@ object ViewManager {
     }
 
     fun openObjectView(aggregator: ObjectAggregator) {
-        val dm = aggregator.dpm as ObjectDM
+        val dm = aggregator.displayModel as ObjectDM
         var title: String = StringUtils.extractTitle(dm.title)
         if (title.isEmpty()) {
             title = aggregator.actionTitle
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/dialog/EventLogDetail.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/dialog/EventLogDetail.kt
index e7827810db..3137c4d64d 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/dialog/EventLogDetail.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/dialog/EventLogDetail.kt
@@ -47,7 +47,7 @@ class EventLogDetail(logEntryFromTabulator: LogEntry) : Controller() {
     // callback parameter
     private val LOG: String = "log"
     private val LNK: String = "lnk"
-    private val DPM: String = "dpm"
+    private val displayModel: String = "displayModel"
 
     override fun open() {
         val responseStr = if (logEntry.subType == Constants.subTypeJson) {
@@ -69,7 +69,7 @@ class EventLogDetail(logEntryFromTabulator: LogEntry) : Controller() {
                 ValueType.BUTTON,
                 null,
                 callBack = this,
-                callBackAction = DPM
+                callBackAction = displayModel
             )
         )
         customButtons.add(FormItem("Console", ValueType.BUTTON, null, callBack = this, callBackAction = LOG))
@@ -98,7 +98,7 @@ class EventLogDetail(logEntryFromTabulator: LogEntry) : Controller() {
                 linkTreeDiagram()
             }
 
-            action == DPM -> {
+            action == displayModel -> {
                 displayModelDiagram()
             }
 
@@ -119,8 +119,8 @@ class EventLogDetail(logEntryFromTabulator: LogEntry) : Controller() {
 
     private fun displayModelDiagram() {
         logEntry.aggregators.forEach {
-            val dpm = it.dpm
-            val json = Flatted.stringify(dpm)
+            val displayModel = it.displayModel
+            val json = Flatted.stringify(displayModel)
             console.log("[ELD.displayModelDiagram]")
             console.log(json)
             val code = JsonDiagram.build(json)
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
index b6cc33e488..9e201b791e 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
@@ -25,13 +25,13 @@ import org.apache.causeway.client.kroviz.snapshots.simpleapp1_16_0.*
 import org.apache.causeway.client.kroviz.to.Property
 import org.apache.causeway.client.kroviz.to.Relation
 import org.apache.causeway.client.kroviz.ui.core.SessionManager
+import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
-import kotlin.test.assertTrue
 
 class CollectionAggregatorTest : IntegrationTest() {
 
-    //@Test
+    @Test
     // sometimes fails with:
     // Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
     fun testFixtureResult() {
@@ -66,13 +66,15 @@ class CollectionAggregatorTest : IntegrationTest() {
             assertNotNull(descLink)  // 4
 
             // then
-            val dl = obs.dpm as CollectionDM
-            val propertyLabels = dl.collectionProperties.propertyDescriptionList
+            val cdm = obs.displayModel as CollectionDM
+//            val propertyLabels = cdm.layout.propertyDescriptionList
             val property = pdLe.getTransferObject() as Property
-            assertTrue(propertyLabels.size > 0)  // 5
-            val lbl = dl.collectionProperties.find(property.id)!!.friendlyName
+//            assertTrue(propertyLabels.size > 0)  // 5
+//            val lbl = dl.collectionLayout.findBy(property.id)!!.columnName
             val expected = "ResultListResult class"
-            assertEquals(expected, lbl)  // 6
+//            assertEquals(expected, lbl)  // 6
+            val vars = "$property , $cdm, $expected"
+            console.log(vars)
         }
     }
 
@@ -88,7 +90,7 @@ class CollectionAggregatorTest : IntegrationTest() {
             mockResponse(SO_LIST_ALL, obs)
             mockResponse(SO_0, obs)
             // then
-            val ol = obs.dpm
+            val ol = obs.displayModel
             assertNotNull(ol)
             assertEquals(1, (ol as CollectionDM).data.size)
         }
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDMTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDMTest.kt
index a17656f69f..42990a8328 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDMTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDMTest.kt
@@ -42,11 +42,6 @@ class CollectionDMTest {
         dl.addLayout(lt)
 
         assertEquals(2, dl.data.size) //1
-
-        val properties = dl.collectionProperties.propertyLayoutList
-        assertEquals(5, properties.size) //2    // includes datanucleus IdLong, VersionLong, VersionTimestamp
-        assertEquals("name", properties[0].id) //3
-        assertEquals("notes", properties[1].id)  //4
     }
 
     @Test
@@ -60,10 +55,6 @@ class CollectionDMTest {
 
         dl.addLayout(lt)
         assertEquals(1, dl.data.size) //1
-
-        val properties = dl.collectionProperties.propertyLayoutList
-        assertEquals("key", properties[0].id) // 2
-        assertEquals("value", properties[1].id)   // 3
     }
 
     //@Test
@@ -78,15 +69,15 @@ class CollectionDMTest {
         assertEquals(1, dl.data.size)
 
         assertNotNull(dl.layout)
-        val properties = dl.collectionProperties.propertyList
-        assertNotNull(properties)
+//        val properties = dl.layout!!.propertyList
+//        assertNotNull(properties)
         //Sequence in FR_OBJECT differs from sequence in FR_OBJECT_LAYOUT
         // FR_OBJECT: fixtureScriptClassName, key, object, className
         // FR_OBJECT_LAYOUT: className, fixtureScriptClassName, key, object
-        assertEquals("fixtureScriptClassName", properties[1].id)
-        assertEquals("key", properties[2].id)
-        assertEquals("object", properties[3].id)
-        assertEquals("className", properties[0].id)
+//        assertEquals("fixtureScriptClassName", properties[1].id)
+//        assertEquals("key", properties[2].id)
+//        assertEquals("object", properties[3].id)
+//        assertEquals("className", properties[0].id)
     }
 
 }


[causeway] 02/10: ISIS-3171 Basic_Types.Strings opens, but table is without icons and columns

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 4e685851d2e30187c7055352be26c965e8e3a79c
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Feb 8 17:36:04 2023 +0100

    ISIS-3171 Basic_Types.Strings opens, but table is without icons and columns
---
 .../design/collection_layout_aggregation.adoc      | 126 ---------------------
 .../collection_layout_aggregation_diagram.adoc     | 125 ++++++++++++++++++++
 .../kroviz/core/aggregator/BaseAggregator.kt       |   2 -
 .../kroviz/core/aggregator/CollectionAggregator.kt |  88 ++++++++------
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  51 +++------
 .../client/kroviz/core/model/BaseLayout.kt         |   4 +-
 .../client/kroviz/core/model/CollectionDM.kt       |   1 +
 .../client/kroviz/core/model/CollectionLayout.kt   |  76 +++++++------
 .../causeway/client/kroviz/core/model/ObjectDM.kt  |   7 +-
 .../client/kroviz/core/model/ObjectLayout.kt       |  52 ++++++---
 .../kroviz/core/model/PropertySpecification.kt     |  46 +++-----
 .../client/kroviz/ui/builder/ColBuilder.kt         |  16 ++-
 .../client/kroviz/ui/core/ColumnFactory.kt         |   2 +
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |   2 +
 .../core/aggregator/CollectionAggregatorTest.kt    |   2 +-
 15 files changed, 304 insertions(+), 296 deletions(-)

diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
index 903ab69a23..a5f29bfcdf 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation.adoc
@@ -1,4 +1,3 @@
-
 |===
 |repr-type |Aggregator |referrer (parent)|link
 
@@ -33,128 +32,3 @@
 |http://localhost:9090/restful/domain-types/demo.JavaLangStringEntity/properties/mixinProperty
 |===
 
-.Collection Layout Aggregation
-[plantuml,file="layout_aggregation.png"]
-----
-allowmixing
-
-() START
-() END
-together {
-    file "..<<xml>>..\nobject-layout" as OL
-    class "<<TransferObject>>\nGridBs" as GRID {}
-    OL . GRID
-}
-together {
-    file "..<<json>>..\nobject-collection" as OC
-    class "<<TransferObject>>\nCollection" as COL {
-        id
-        memberType= Collection
-        value[] = data
-    }
-    COL . OC
-}
-together {
-    file "<<json>>\n..object.." as O
-    class "<<TransferObject>>\nTObject" as TOBJ {
-        members[]
-    }
-    TOBJ . O
-}
-file "..<<json>>..\ncollection-description" as CD
-
-together {
-    file "..<<json>>..\nobject-property" as OP
-    class "<<TransferObject>>\nObjectProperty" as OPR {
-        disabledReason
-    }
-    OP . OPR
-}
-together {
-    file "..<<json>>..\nproperty-description" as PD
-    class "<<TransferObject>>\nPropertyDescription" as PRD {
-        extensions.friendlyName
-    }
-    PD .r. PRD
-}
-
-' references between TransferObjects (xml/json)
-START --> OL : menu action \ninvoked by user
-OL --> OC : contains\nreference\nto
-OC --> CD : contains\ncollection\ntitle
-OC --> O : contains\nreference\nto
-O --> OP : contains\nreference\nto
-OP --> PD : contains\nreference\nto
-PD --> END
-
-' references between TO classes
-GRID o->"0.n" COL
-COL o-> TOBJ : first element is required
-
-' object
-together {
-    class "ObjectAggregator" as OBJAGR {
-        collectionMap
-        update()
-        handleGrid()
-    }
-    class "ObjectDM" as OBJDM {
-        layout
-        data: Exposer
-        readyToRender()
-    }
-    class "<<2nd level aggregator>>\nObjectLayout" as OBJLO {
-        grid
-        collectionLayout:Map
-        readyToRender()
-    }
-    OBJAGR --> OBJDM
-    OBJDM --> OBJLO
-}
-OBJLO --> GRID
-
-'collection
-together {
-    class "CollectionAggregator" as COLAGR {
-        update()
-    }
-    class "CollectionDM" as COLDM {
-        layout
-        data[]: Exposer
-        readyToRender()
-    }
-    class "<<2nd level aggregator>>\nCollectionLayout" as COLLO {
-        numberOfColumns
-        columnDescriptions
-        objectPropertyList
-        propertyDescriptionList
-        readyToRender()
-    }
-    COLAGR --> COLDM
-    COLDM --> COLLO
-}
-OBJLO o-> COLLO
-' references between Layout and TO classes
-COLLO -> TOBJ
-COLLO -> OPR
-COLLO -> PRD
-
-note bottom of COLLO
-the number of columns is to be set from object/TObject
-for each attribute/property/column get object-property
-for each object-property, get the property-description (friendlyName)
-end note
-
-
-note bottom of COLAGR
-iterate over value[]
-and add data to DisplayModel
-end note
-
-OBJAGR o--> COLAGR
-----
-Colors
-TO
-AGR
-DM
-LO
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
new file mode 100644
index 0000000000..365fb2890b
--- /dev/null
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
@@ -0,0 +1,125 @@
+.Collection Layout Aggregation
+[plantuml,file="layout_aggregation.png"]
+----
+allowmixing
+
+() START
+() END
+together {
+    file "object-layout" <<BootStrap XML>> as OL #lightblue
+    class GridBs <<(T,tomato)TransferObject>> #lightgreen {}
+    OL . GridBs
+}
+together {
+    file "object-collection" <<JSON>> as OC #lightblue
+    class Collection <<(T,tomato)TransferObject>> #lightgreen {
+        id
+        memberType= Collection
+        value[] = data
+    }
+    'Collection .. OC
+}
+together {
+    file "object" <<JSON>> as O #lightblue
+    class TObject <<(T,tomato)TransferObject>> #lightgreen {
+        members[]
+    }
+    TObject .. O
+}
+file "collection-description" <<JSON>> as CD #lightblue
+
+together {
+    file "object-property" <<JSON>> as OP #lightblue
+    class ObjectProperty <<(T,tomato)TransferObject>> #lightgreen {
+        disabledReason
+    }
+    OP .u. ObjectProperty
+}
+together {
+    file "property-description" <<JSON>> as PD #lightblue
+    class PropertyDescription <<(T,tomato)TransferObject>> #lightgreen {
+        extensions.friendlyName
+    }
+    PD .u. PropertyDescription
+}
+
+' references between TransferObjects (xml/json)
+START --> OL : menu action \ninvoked by user
+OL --> OC : contains\nreference\nto
+OC --> CD : contains\ncollection\ntitle
+OC --> O : contains\nreference\nto
+O --> OP : contains\nreference\nto
+OP -> PD : contains\nreference\nto
+PD --> END
+
+' references between TO classes
+GridBs o-->"0.n" Collection
+Collection o--> TObject : first\nelement\nis\nrequired
+
+' object
+together {
+    class ObjectAggregator <<(A,orange)Aggregator>> #pink {
+        update()
+        handleGrid()
+    }
+    class ObjectDM <<(M,orange)DisplayModel>> #lightyellow {
+        layout
+        collectionDmMap
+        data: Exposer
+        readyToRender()
+    }
+    class ObjectLayout <<(L,orange)Layout>> #pink {
+        grid
+        readyToRender()
+    }
+    ObjectAggregator --> ObjectDM
+    ObjectDM --> ObjectLayout
+}
+ObjectAggregator ..> GridBs : handles
+
+'collection
+together {
+    class CollectionAggregator <<(A, coral)Aggregator>> #pink {
+        update()
+        handleCollection()
+        isStandAloneCollection()
+        isParentedCollection()
+    }
+    class CollectionDM <<(M,coral)DisplayModel>> #lightyellow {
+        layout
+        data[]: Exposer
+        readyToRender()
+    }
+    class CollectionLayout <<(L,coral)Layout>> #pink{
+        numberOfColumns
+        propertySpecificationMap
+        readyToRender()
+    }
+    CollectionAggregator --> CollectionDM
+    CollectionDM --> CollectionLayout
+}
+ObjectDM o-r-> CollectionDM
+
+' references between Layout and TO classes
+CollectionLayout ..> TObject : handles
+CollectionLayout ..> ObjectProperty : handles
+CollectionLayout ..> PropertyDescription : handles
+
+note left of CollectionLayout #gold
+* the number of columns
+is to be set from object/TObject
+* for each
+attribute/property/column
+get object-property
+*for each object-property,
+get the property-description
+(friendlyName)
+end note
+
+note right of CollectionAggregator #gold
+iterate over value[]
+and add data to DisplayModel
+end note
+
+
+----
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
index 9d8a93be23..14eeb07def 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/BaseAggregator.kt
@@ -92,8 +92,6 @@ abstract class BaseAggregator {
         subType: String = Constants.subTypeJson,
         referrer: String,
     ) {
-        //       console.log("[BA.invoke]")
-        //       console.log("$link ${aggregator::class.simpleName} $referrer")
         ResourceProxy().fetch(link, aggregator, subType, referrer = referrer)
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 3dd93f44ba..17aabcb0f7 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -25,7 +25,6 @@ import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
 import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.to.*
-import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
 
 /** sequence of operations:
@@ -41,47 +40,57 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         displayModel = CollectionDM(actionTitle)
     }
 
+    var referrer = ""
+
     override fun update(logEntry: LogEntry, subType: String?) {
         super.update(logEntry, subType)
         if (logEntry.state == EventState.DUPLICATE) {
             throw IllegalStateException("duplicates should not be propagated to handlers")
             //TODO this may not hold true for changed and deleted objects - object version required to deal with it?
         } else {
-            val referrer = logEntry.url
+            referrer = logEntry.url
             when (val obj = logEntry.getTransferObject()) {
                 null -> log(logEntry)
-                is ResultList -> handleList(obj, referrer)
-                is TObject -> handleObject(obj, referrer)
-                is DomainType -> handleDomainType(obj, referrer)
-                is GridBs -> handleGrid(obj, referrer)
-                is Property -> handleProperty(obj, referrer)
-                is Collection -> handleCollection(obj, referrer)
+                is ResultList -> handleList(obj)
+                is TObject -> handleObject(obj)
+                is DomainType -> handleDomainType(obj)
+                //is GridBs -> Unit //In the case of CollectionDM, object-layout can be ignored
+                is Property -> handleProperty(obj)
+                is Collection -> handleCollection(obj)
                 is Icon -> handleIcon(obj)
                 else -> log(logEntry)
             }
 
-            if (parent == null) {
-                if (displayModel.readyToRender()) {
+            when {
+                isStandAloneCollection() && readyToRender() -> {
                     ViewManager.openCollectionView(this)
                 }
-            } else {
-                val le = LogEntry(ResourceSpecification(""))
-                // in case of a _parented_collection_ an empty LogEntry is passed on
-                parent.update(le, subType)
+
+                isParentedCollection() -> {
+                    // A LogEntry with an empty url is passed on to the parent AGGT
+                    // in order to decide, if the whole tree is ready to be rendered.
+                    val le = LogEntry(ResourceSpecification(""))
+                    parent!!.update(le, subType)
+                }
+
+                else -> Unit
             }
         }
     }
 
-    private fun handleGrid(grid: GridBs, referrer: String) {
-        val cdm = displayModel as CollectionDM
-        console.log("[CA.handleGrid] In the case of CollectionDM, object-layout can be ignored?")
-        console.log(grid)
-        console.log(cdm)
-        console.log(referrer)
-        //TODO("In the case of CollectionDM, object-layout can be ignored: " + vars)
+    private fun readyToRender(): Boolean {
+        return getDisplayModel().readyToRender()
     }
 
-    private fun handleList(resultList: ResultList, referrer: String) {
+    private fun getDisplayModel(): CollectionDM {
+        return displayModel as CollectionDM
+    }
+
+    private fun getLayout(): CollectionLayout {
+        return getDisplayModel().layout as CollectionLayout
+    }
+
+    private fun handleList(resultList: ResultList) {
         if (resultList.resulttype != ResultType.VOID.type) {
             val result = resultList.result!!
             result.value.forEach {
@@ -90,28 +99,30 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         }
     }
 
-    private fun handleObject(obj: TObject, referrer: String) {
+    private fun handleObject(obj: TObject) {
         displayModel.addData(obj, this, referrer)
+
+        getLayout().initColumns(obj)
+
         if (isStandAloneCollection()) {
             invokeLayoutLink(obj, this, referrer = referrer)
         }
         invokeIconLink(obj, this, referrer = referrer)
-        // set the number of columns
-        val numberOfColumns = obj.getProperties().size
-        val cdm = displayModel as CollectionDM
-        val cl = cdm.layout as CollectionLayout
-        cl.numberOfColumns = numberOfColumns
     }
 
     private fun isStandAloneCollection(): Boolean {
         return parent == null
     }
 
+    private fun isParentedCollection(): Boolean {
+        return parent != null
+    }
+
     private fun handleIcon(obj: TransferObject?) {
-        (displayModel as CollectionDM).addIcon(obj)
+        getDisplayModel().addIcon(obj)
     }
 
-    private fun handleDomainType(obj: DomainType, referrer: String) {
+    private fun handleDomainType(obj: DomainType) {
         obj.links.forEach {
             if (it.relation() == Relation.LAYOUT) {
                 invoke(it, this, referrer = referrer)
@@ -125,14 +136,19 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         }
     }
 
-    private fun handleProperty(property: Property, referrer: String) {
-        console.log("[CA.handleProperty]")
-        val dm = displayModel as CollectionDM
-        val layout = dm.layout!!
-        handleProperty(property, referrer, layout)
+    private fun handleProperty(property: Property) {
+        handleProperty(property, referrer, getLayout())
     }
 
-    private fun handleCollection(collection: Collection, referrer: String) {
+    private fun handleCollection(collection: Collection) {
+        console.log("[CA_handleCollection]")
+        if (isParentedCollection()) {
+            val cdm = getDisplayModel()
+            cdm.id = collection.id
+            // add displayModel to parent.displayModel
+            val parentDM = parent!!.getDisplayModel()
+            parentDM.collectionModelList.add(cdm)
+        }
         collection.links.forEach {
             if (it.relation() == Relation.DESCRIBED_BY) {
                 ResourceProxy().fetch(it, this, referrer = referrer)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 53b1bd1ca4..351aea89cf 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -37,8 +37,6 @@ import org.apache.causeway.client.kroviz.ui.dialog.ErrorDialog
  */
 class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
 
-    private var collectionMap = mutableMapOf<String, CollectionAggregator>()
-
     init {
         displayModel = ObjectDM(actionTitle)
     }
@@ -58,7 +56,7 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
             }
         }
 
-        if (displayModel.readyToRender()) {
+        if (getDisplayModel().readyToRender()) {
             ViewManager.openObjectView(this)
         }
     }
@@ -71,9 +69,6 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         } else {
             displayModel.addData(obj, this, referrer)
         }
-        if (collectionMap.isEmpty()) {
-            handleCollections(obj, referrer)
-        }
         invokeLayoutLink(obj, this, referrer = referrer)
     }
 
@@ -84,8 +79,16 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         invoke(selfLink!!, this, referrer = referrer)
     }
 
+    fun getDisplayModel(): ObjectDM {
+        return displayModel as ObjectDM
+    }
+
+    private fun getLayout(): ObjectLayout {
+        return getDisplayModel().layout as ObjectLayout
+    }
+
     private fun handleResultObject(resultObject: ResultObject) {
-        (displayModel as ObjectDM).addResult(resultObject)
+        getDisplayModel().addResult(resultObject)
     }
 
     private fun handleResultValue(resultValue: ResultValue) {
@@ -96,47 +99,19 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         return displayModel.getObject()
     }
 
-    private fun handleCollections(obj: TObject, referrer: String) {
-        console.log("[OA_handleCollection] collections")
-        val collections = obj.getCollections()
-        console.log(collections)
-        collections.forEach {
-            val key = it.id
-            val aggregator = CollectionAggregator(key, this)
-            collectionMap[key] = aggregator
-            val link = it.links.first()
-            ResourceProxy().fetch(link, aggregator, referrer = referrer)
-        }
-    }
-
     private fun handleProperty(property: Property, referrer: String) {
-        val dm = displayModel as ObjectDM
-        val layout = dm.layout!!
-        handleProperty(property, referrer, layout)
+        handleProperty(property, referrer, getLayout()) //FIXME
     }
 
     private fun handleGrid(grid: GridBs, referrer: String) {
-        val odm = displayModel as ObjectDM
-        val ol = odm.layout as ObjectLayout
+        val ol = getLayout()
         // for a yet unknown reason, handleGrid may be called twice, therefore we check if it's already set
         if (ol.grid == null) {
-            console.log("[OA_handleGrid]")
             ol.addGrid(grid, this, referrer = referrer)
-            val pl = grid.getPropertyList()
-            pl.forEach {
+            grid.getPropertyList().forEach {
                 val link = it.link!!
-                // properties to be handled by ObjectAggregator
                 ResourceProxy().fetch(link, this, subType = Constants.subTypeJson, referrer = referrer)
             }
-            val cl = grid.getCollectionList()
-            cl.forEach {
-                val href = it.linkList.first().href
-                console.log("CollectionBs")
-                console.log(href)
-                val l = Link(href = href)
-                // collections to be handled by ObjectAggregator
-                ResourceProxy().fetch(l, this, subType = Constants.subTypeJson, referrer = referrer)
-            }
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
index 55d0856cdd..206ae67da1 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
@@ -25,13 +25,13 @@ import org.apache.causeway.client.kroviz.to.PropertyDescription
 abstract class BaseLayout {
 
     abstract fun addObjectProperty(
-        property: ObjectProperty,
+        objectProperty: ObjectProperty,
         aggregator: AggregatorWithLayout,
         referrer: String
     )
 
     abstract fun addPropertyDescription(
-        property: PropertyDescription,
+        propertyDescription: PropertyDescription,
         aggregator: AggregatorWithLayout,
         referrer: String
     )
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index 45cb4f48f3..2f7aa90034 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -28,6 +28,7 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
         layout = CollectionLayout()
     }
 
+    var id = ""
     var data = observableListOf<Exposer>()
     private var rawData = observableListOf<TransferObject>()
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
index c2ab4612b3..2f69d7148e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -22,6 +22,7 @@ import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.ObjectProperty
 import org.apache.causeway.client.kroviz.to.PropertyDescription
+import org.apache.causeway.client.kroviz.to.TObject
 
 /**
  * For (parented) collections aggregate information for each column
@@ -31,28 +32,51 @@ import org.apache.causeway.client.kroviz.to.PropertyDescription
  * - hidden :       will the column be displayed or not
  */
 class CollectionLayout : BaseLayout() {
-    var numberOfColumns = 0
-    private val propertySpecificationMap = mutableMapOf<String, PropertySpecification>()
-    private val objectPropertyList = mutableListOf<ObjectProperty>()
-    private val propertyDescriptionList = mutableListOf<PropertyDescription>()
+    private var numberOfColumns = 0
+    private val propertySpecificationList = mutableListOf<PropertySpecification>()
 
     override fun readyToRender(): Boolean {
-        console.log("[CL.readyToRender]")
-        console.log(this)
-        return (numberOfColumns > 0) &&
-                (numberOfColumns == propertyDescriptionList.size)
+        console.log("[CL_readyToRender]")
+        console.log(propertySpecificationList.size)
+        val isReady = isInitialized() && allPropertySpecificationsAreCreated()
+        if (isReady) {
+            propertySpecificationList.forEach {
+                console.log(it)
+            }
+        }
+        return isReady
     }
 
     /**
-     * One element is to be added for each column.
-     * Duplicates are not allowed.
+     * collection layout needs only to be initialized once with an object (pars pro toto, prototype)
+     * obj acts as a kind prototype - we assume all elements in the collection have the same structure
      */
+    fun initColumns(obj: TObject) {
+        if (!isInitialized()) {
+            // members contain all properties, regardless if hidden, disabled, etc.
+            val members = obj.getProperties()
+            numberOfColumns = members.size
+            members.forEach { m ->
+                val ps = PropertySpecification(m)
+                propertySpecificationList.add(ps)
+            }
+        }
+    }
+
+    fun isInitialized(): Boolean {
+        return numberOfColumns > 0
+    }
+
+    private fun allPropertySpecificationsAreCreated(): Boolean {
+        return (numberOfColumns == propertySpecificationList.size)
+    }
+
     override fun addObjectProperty(
         objectProperty: ObjectProperty,
         aggregator: AggregatorWithLayout,
         referrer: String
     ) {
-        objectPropertyList.add(objectProperty)
+        console.log("[CL_addObjectProperty]")
         val l = objectProperty.getDescriptionLink()!!
         // FIXME NPE -> ISIS-2846 ?
         //invoking DN links leads to an error
@@ -60,7 +84,6 @@ class CollectionLayout : BaseLayout() {
         if (!isDn) {
             ResourceProxy().fetch(l, aggregator, referrer = referrer)
         }
-        updatePropertySpecification(objectProperty)
     }
 
     override fun addPropertyDescription(
@@ -68,32 +91,15 @@ class CollectionLayout : BaseLayout() {
         aggregator: AggregatorWithLayout,
         referrer: String
     ) {
-        console.log("[CL.addPropertyDescription]")
-        propertyDescriptionList.add(propertyDescription)
-        updatePropertySpecification(propertyDescription)
-    }
-
-    private fun updatePropertySpecification(propertyDescription: PropertyDescription) {
-        val ps: PropertySpecification = findOrCreateFor(propertyDescription.id)
-        ps.addPropertyDescription(propertyDescription)
-    }
-
-    private fun updatePropertySpecification(objectProperty: ObjectProperty) {
-        val ps: PropertySpecification = findOrCreateFor(objectProperty.id)
-        ps.addObjectProperty(objectProperty)
-    }
-
-    private fun findOrCreateFor(id: String): PropertySpecification {
-        var ps = propertySpecificationMap[id]
-        if (ps == null) {
-            ps = PropertySpecification(id)
-            propertySpecificationMap[id] = ps
-        }
-        return ps
+        console.log("[CL_addPropertyDescription]")
+        val id = propertyDescription.id
+        val ps: PropertySpecification = propertySpecificationList.firstOrNull { it.id == id }!!
+        console.log(ps)
+        ps.amendWith(propertyDescription)
     }
 
     fun getColumnDescriptions(): List<PropertySpecification> {
-        return propertySpecificationMap.values.toList()
+        return propertySpecificationList
     }
 
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index f4e67d73a0..b0bfb49362 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -31,7 +31,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         layout = ObjectLayout()
     }
 
-    val collectionMap = mutableMapOf<String, CollectionDM>()
+    val collectionModelList = mutableListOf<CollectionDM>()
     var data: Exposer? = null
     private var dirty: Boolean = false
 
@@ -43,7 +43,12 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         TODO("Not yet implemented")
     }
 
+    fun getCollectionDisplayModelFor(id: String): CollectionDM {
+        return collectionModelList.find { it.id == id }!!
+    }
+
     override fun readyToRender(): Boolean {
+        console.log("[ODM_readyToRender]")
         return when {
             data == null -> false
             isRendered -> false
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
index 9f8472a14a..f2e85ee268 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
@@ -19,10 +19,13 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
+import org.apache.causeway.client.kroviz.core.aggregator.ObjectAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.Link
 import org.apache.causeway.client.kroviz.to.ObjectProperty
 import org.apache.causeway.client.kroviz.to.PropertyDescription
+import org.apache.causeway.client.kroviz.to.bs.CollectionBs
 import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.to.bs.RowBs
 
@@ -33,59 +36,72 @@ class ObjectLayout : BaseLayout() {
 
     override fun readyToRender(): Boolean {
         console.log("[OL_readyToRender]")
-        return when (grid) {
+//        val o = js(arrayOf(collectionLayoutMap.values))
+        console.log(collectionLayoutMap.keys)
+        var answer = when (grid) {
             null -> false
             else -> {
                 var answer = true
                 collectionLayoutMap.values.forEach {
-                    console.log(it)
-                    if (!it.readyToRender()) answer = false
+                    if (!it.readyToRender()) {
+                        answer = false
+                    }
                 }
                 answer
             }
         }
+        return answer
     }
 
     override fun addObjectProperty(
-        property: ObjectProperty,
+        objectProperty: ObjectProperty,
         aggregator: AggregatorWithLayout,
         referrer: String
     ) {
-        TODO("Not yet implemented")
+        console.log("[OL_addObjectProperty]")
+//        TODO("Not yet implemented")
     }
 
     override fun addPropertyDescription(
-        property: PropertyDescription,
+        propertyDescription: PropertyDescription,
         aggregator: AggregatorWithLayout,
         referrer: String
     ) {
-        TODO("Not yet implemented")
+        console.log("[OL_addPropertyDescription]")
+//        TODO("Not yet implemented")
     }
 
-    fun addGrid(grid: GridBs, aggregator: AggregatorWithLayout?, referrer: String?) {
+    fun addGrid(grid: GridBs, aggregator: ObjectAggregator, referrer: String?) {
         this.grid = grid
         grid.rows.forEach { r ->
-            initRow(r, aggregator!!, referrer = referrer!!)
+            initRow(r, aggregator, referrer = referrer!!)
         }
     }
 
-    private fun initRow(r: RowBs, aggregator: AggregatorWithLayout, referrer: String) {
+    private fun initRow(r: RowBs, aggregator: ObjectAggregator, referrer: String) {
         r.colList.forEach { c ->
-            c.collectionList.forEach { col ->
-                collectionLayoutMap[col.id] =
-                    CollectionLayout() // create empty entry for id - for later usage when response arrives
-                val href = col.linkList.first().href // we assume, linklist has always one element
-                val l = Link(href = href)
-                ResourceProxy().fetch(l, aggregator, referrer = referrer)
+            c.rowList.forEach { r2 ->
+                r2.colList.forEach { c2 ->
+                    c2.collectionList.forEach { col ->
+                        initCollection(col, aggregator, referrer)
+                    }
+                }
             }
             c.tabGroupList.forEach { tg ->
                 tg.tabList.forEach { t ->
-                    t.rowList.forEach { r2 ->
-                        initRow(r2, aggregator, referrer)
+                    t.rowList.forEach { r3 ->
+                        initRow(r3, aggregator, referrer)
                     }
                 }
             }
         }
     }
 
+    private fun initCollection(collection: CollectionBs, parent: ObjectAggregator, referrer: String) {
+        val href = collection.linkList.first().href // we assume, linklist has always one element
+        val l = Link(href = href)
+        val aggt = CollectionAggregator("", parent)
+        ResourceProxy().fetch(l, aggt, referrer = referrer)
+    }
+
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index 935a9a2d13..539d8fd979 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -18,7 +18,7 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.to.ObjectProperty
+import org.apache.causeway.client.kroviz.to.Member
 import org.apache.causeway.client.kroviz.to.PropertyDescription
 
 /**
@@ -31,37 +31,27 @@ import org.apache.causeway.client.kroviz.to.PropertyDescription
  *
  * All are required in order to be correctly displayed (in a table).
  */
-class PropertySpecification(val id: String) {
-    var name = "" // aka: columnName, named, label
+class PropertySpecification(member: Member) {
+    var id = ""
+    var name = "" // aka: columnName, named, label, title
     var hidden = false
-    var disabledReason = ""
+    var disabled = false
 
-    fun addObjectProperty(op: ObjectProperty) {}
-    fun addPropertyDescription(pd: PropertyDescription) {
+    init {
+        id = member.id
+        name = member.id // can be changed later via property-description
+        hidden = false // can be changed later via ...
+        disabled = member.disabledReason.isNotEmpty()
+    }
+
+    fun amendWith(pd: PropertyDescription) {
+        console.log("[PS_addPropertyDescription]")
         val ex = pd.extensions!!
-        name = ex.getFriendlyName()
-        if (name.isEmpty()) {
-            name = id
-            console.log(pd)
+        val fn = ex.getFriendlyName()
+        if (fn.isNotEmpty()) {
+            name = fn
         }
+        console.log(this)
     }
-    //FIXME use setter Methods using:
-    /** Property
-     *ObjectProperty
-    PropertyDescription */
-    /*init {
-        id = grid.id
-        when {
-            grid.named.isNotEmpty() -> columnName = grid.named
-            else -> columnName = id
-        }
-        //       console.log("[CD.init]")
-        when {
-            // grid.hidden can be null -- intellij inference is wrong
-            (grid.hidden == null) || grid.hidden.isEmpty() -> {}
-            grid.hidden.contains("TABLE") -> hidden = true
-        }
-        //       console.log("$id $columnName Hidden: $hidden")
-    } */
 
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
index 6ee6430970..6db3b9f247 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
@@ -65,16 +65,14 @@ class ColBuilder : UiBuilder() {
             val rowCpt = RowBuilder().create(row, tObject, dsp)
             panel.add(rowCpt)
         }
-        for (c in col.collectionList) {
-            val key = c.id  // entities
+        col.collectionList.forEach {
+            val id = it.id
             val objectDM = dsp.displayModel
-            val collectionDM = objectDM.collectionMap[key]
-            if (collectionDM != null) {
-                val tblCpt = RoTable(collectionDM)
-                val fsPanel = FieldsetPanel(legend = StringUtils.capitalize(key)).add(tblCpt)
-                panel.add(fsPanel)
-                collectionDM.isRendered = true
-            }
+            val cdm = objectDM.getCollectionDisplayModelFor(id)
+            val tblCpt = RoTable(cdm)
+            val fsPanel = FieldsetPanel(legend = StringUtils.capitalize(cdm.title)).add(tblCpt)
+            panel.add(fsPanel)
+            cdm.isRendered = true
         }
         return panel
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index 4b8bc9eb3a..398d1bb8a8 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -42,10 +42,12 @@ class ColumnFactory {
     }
 
     fun buildColumns(displayCollection: CollectionDM): List<ColumnDefinition<dynamic>> {
+        console.log("[CF_buildColumns]")
         val columns = mutableListOf<ColumnDefinition<Exposer>>()
         addColumnForObjectIcon(displayCollection, columns)
         addColumnsForProperties(displayCollection, columns)
         columns.add(columnForObjectMenu())
+        console.log(columns)
         return columns
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 3ce091643e..457fe0ae00 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -173,7 +173,9 @@ object ViewManager {
     }
 
     fun openObjectView(aggregator: ObjectAggregator) {
+        console.log("[VM_openObjectView]")
         val dm = aggregator.displayModel as ObjectDM
+        console.log(dm)
         var title: String = StringUtils.extractTitle(dm.title)
         if (title.isEmpty()) {
             title = aggregator.actionTitle
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
index 9e201b791e..a7af7d948e 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
@@ -74,7 +74,7 @@ class CollectionAggregatorTest : IntegrationTest() {
             val expected = "ResultListResult class"
 //            assertEquals(expected, lbl)  // 6
             val vars = "$property , $cdm, $expected"
-            console.log(vars)
+//            console.log(vars)
         }
     }
 


[causeway] 07/10: ISIS-3171 CollectionLayout removed, PropertySpecificationHolder introduced

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 9bbf18daeab81f046b4fda6cb056bda9dd0b7a5f
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 16 22:52:37 2023 +0100

    ISIS-3171 CollectionLayout removed, PropertySpecificationHolder introduced
---
 .../kroviz/core/aggregator/CollectionAggregator.kt | 19 +----
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  8 +-
 .../client/kroviz/core/model/CollectionDM.kt       | 53 ++++++++++---
 .../client/kroviz/core/model/CollectionLayout.kt   | 90 ----------------------
 .../kroviz/core/model/PropertySpecification.kt     | 19 ++---
 .../core/model/PropertySpecificationHolder.kt      | 53 +++++++++++++
 .../causeway/client/kroviz/to/bs/PropertyBs.kt     | 10 +--
 .../client/kroviz/ui/core/ColumnFactory.kt         |  6 +-
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |  2 -
 9 files changed, 115 insertions(+), 145 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 3a36d46fd1..d1cbfafcf9 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -22,9 +22,7 @@ import org.apache.causeway.client.kroviz.core.event.EventState
 import org.apache.causeway.client.kroviz.core.event.LogEntry
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
-import org.apache.causeway.client.kroviz.core.model.BaseLayout
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
-import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
@@ -57,7 +55,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
                 is TObject -> handleObject(obj)
                 is DomainType -> handleDomainType(obj)
                 is GridBs -> handleLayout(obj)
-                is Property -> handleProperty(obj)
+                is Property -> handleProperty(obj, referrer)
                 is Collection -> handleCollection(obj)
                 is Icon -> handleIcon(obj)
                 else -> log(logEntry)
@@ -88,10 +86,6 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         return displayModel as CollectionDM
     }
 
-    private fun getLayout(): CollectionLayout {
-        return getDisplayModel().layout as CollectionLayout
-    }
-
     private fun handleList(resultList: ResultList) {
         if (resultList.resulttype != ResultType.VOID.type) {
             val result = resultList.result!!
@@ -113,7 +107,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
             invokeLayoutLink(tObj, this, referrer = referrer)
         }
         //TODO fold layout into model
-        getLayout().addObject(tObj, this, referrer = referrer)
+        getDisplayModel().addObject(tObj, this, referrer = referrer)
 
         invokeIconLink(tObj, this, referrer = referrer)
     }
@@ -144,11 +138,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         }
     }
 
-    private fun handleProperty(property: Property) {
-        handleProperty(property, referrer, getLayout())
-    }
-
-    protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
+    private fun handleProperty(property: Property, referrer: String) {
         when {
             property.isObjectProperty() -> {
                 val op = ObjectProperty(property)
@@ -158,7 +148,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
 
             property.isPropertyDescription() -> {
                 val pd = PropertyDescription(property)
-                getLayout().addPropertyDescription(pd, this, referrer)
+                getDisplayModel().addPropertyDescription(pd, this, referrer)
             }
 
             else -> {
@@ -173,7 +163,6 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
             //TODO is _id_ required in both CollectionDM and CollectionLayout?
             val id = collection.id
             getDisplayModel().id = id
-            getLayout().id = id
             // add displayModel to parent.displayModel
             val objectDM = parent!!.getDisplayModel()
             objectDM.addCollectionModel(getDisplayModel())
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 17b85d0581..3bbc286a5c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -58,8 +58,6 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         }
 
         if (getDisplayModel().readyToRender()) {
-            console.log("[OA_readyToRender]")
-            console.log(getDisplayModel())
             ViewManager.openObjectView(this)
         }
     }
@@ -103,7 +101,9 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
     }
 
     private fun handleProperty(property: Property, referrer: String) {
-        handleProperty(property, referrer) //FIXME
+        //(property, referrer) //FIXME
+        console.log("[OA_handleProperty] not handled")
+        console.log(property)
     }
 
     private fun handleGrid(grid: GridBs, referrer: String) {
@@ -126,8 +126,6 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         return title
     }
 
-
-
     override fun reset(): ObjectAggregator {
         displayModel.reset()
         return this
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index af6e1371e5..25279300ac 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -20,16 +20,17 @@ package org.apache.causeway.client.kroviz.core.model
 
 import io.kvision.state.observableListOf
 import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
+import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
 import org.apache.causeway.client.kroviz.to.bs.GridBs
+import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 import org.apache.causeway.client.kroviz.utils.StringUtils
 
 class CollectionDM(override val title: String) : DisplayModelWithLayout() {
-    init {
-        layout = CollectionLayout()
-    }
+    val propertySpecificationHolder = PropertySpecificationHolder()
 
     var id = ""
     var data = observableListOf<Exposer>()
@@ -40,31 +41,61 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     fun setProtoTypeLayout(grid: GridBs) {
         protoTypeLayout = grid
         val propertyList = grid.getPropertyList()
-        propertyList.forEach{
-            getLayout().addPropertyDetails(it)
+        propertyList.forEach {
+            addPropertyDetails(it)
+        }
+    }
+
+    /**
+     * collection layout needs only to be initialized once with an object (pars pro toto, prototype)
+     * obj acts as a kind prototype - we assume all elements in the collection have the same structure
+     */
+    fun addObject(obj: TObject, aggregator: CollectionAggregator, referrer: String) {
+        if (!propertySpecificationHolder.isInitialized()) {
+            // members contain all properties, regardless if hidden, disabled, etc.
+            val members = obj.getProperties()
+            members.forEach { m ->
+                propertySpecificationHolder.addMember(m)
+                val l = m.getInvokeLink()!!
+                ResourceProxy().fetch(l, aggregator, referrer = referrer)
+            }
         }
     }
 
+
+    private fun addPropertyDetails(propertyBs: PropertyBs) {
+        val id = propertyBs.id
+        val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
+        ps.amendWith(propertyBs)
+    }
+
+    fun addPropertyDescription(
+        propertyDescription: PropertyDescription,
+        aggregator: AggregatorWithLayout,
+        referrer: String
+    ) {
+        val id = propertyDescription.id
+        val ps: PropertySpecification = propertySpecificationHolder.getPropertySpecification(id)
+        ps.amendWith(propertyDescription)
+    }
+
+
     fun hasProtoType(): Boolean {
         return protoType != null
     }
 
-    fun setProtoType(to:TransferObject){
+    fun setProtoType(to: TransferObject) {
         protoType = to as TObject
     }
 
     override fun readyToRender(): Boolean {
-        return getLayout().readyToRender()
+        return propertySpecificationHolder.readyToRender()
     }
 
     fun getTitle(): String {
         return StringUtils.extractTitle(title)
     }
 
-    fun getLayout(): CollectionLayout {
-        return layout as CollectionLayout
-    }
-
     override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
         //TODO is checking rawdata really needed?
         if (!rawData.contains(obj)) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
deleted file mode 100644
index 71b97e68ed..0000000000
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ /dev/null
@@ -1,90 +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.causeway.client.kroviz.core.model
-
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
-import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
-import org.apache.causeway.client.kroviz.core.event.ResourceProxy
-import org.apache.causeway.client.kroviz.to.PropertyDescription
-import org.apache.causeway.client.kroviz.to.TObject
-import org.apache.causeway.client.kroviz.to.bs.PropertyBs
-
-/**
- * For collections aggregate information for each column
- * in order to display the table, namely:
- * - columnName :   column header/label
- * - id :           attribute to be used to retrieve the value of each cell (id)
- * - hidden :       will the column be displayed or not
- */
-class CollectionLayout : BaseLayout() {
-    var id = ""
-    var propertySpecificationList = mutableListOf<PropertySpecification>()
-
-    override fun readyToRender(): Boolean {
-        return isInitialized() && arePropertySpecificationsReadyToRender()
-    }
-
-    private fun arePropertySpecificationsReadyToRender():Boolean {
-        propertySpecificationList.forEach {
-            val ready = it.readyToRender()
-            if (!ready) {
-                return false
-            }
-        }
-        return true
-    }
-
-    /**
-     * collection layout needs only to be initialized once with an object (pars pro toto, prototype)
-     * obj acts as a kind prototype - we assume all elements in the collection have the same structure
-     */
-    fun addObject(obj: TObject, aggregator: CollectionAggregator, referrer: String) {
-        if (!isInitialized()) {
-            // members contain all properties, regardless if hidden, disabled, etc.
-            val members = obj.getProperties()
-            members.forEach { m ->
-                val ps = PropertySpecification(m)
-                propertySpecificationList.add(ps)
-                val l = m.getInvokeLink()!!
-                ResourceProxy().fetch(l, aggregator, referrer = referrer)
-            }
-        }
-    }
-
-    private fun isInitialized(): Boolean {
-        return propertySpecificationList.isNotEmpty() && propertySpecificationList.size > 0
-    }
-
-    fun addPropertyDetails(propertyBs: PropertyBs) {
-        val id = propertyBs.id
-        val ps: PropertySpecification = propertySpecificationList.firstOrNull { it.id == id }!!
-        ps.amendWith(propertyBs)
-    }
-
-    fun addPropertyDescription(
-        propertyDescription: PropertyDescription,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
-        val id = propertyDescription.id
-        val ps: PropertySpecification = propertySpecificationList.firstOrNull { it.id == id }!!
-        ps.amendWith(propertyDescription)
-    }
-
-}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index d70a72b0f3..bbb872de0e 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -23,28 +23,22 @@ import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 
 /**
- * Properties have multiple aspects:
- *
- * - Member of a DomainObject
- * - Description (friendlyName, etc.)
- * - Layout (disabledReason, labelPosition, etc.)
- * - Visibility (hidden)
- *
- * All are required in order to be correctly displayed (in a table).
+ * Aggregate information for each column in order to display in a table, namely:
+ * - columnName :   column header/label
+ * - id :           attribute to be used to retrieve the value of each cell (id)
+ * - hidden :       will the column be displayed or not
  */
 class PropertySpecification(member: Member) {
     var id = member.id
     var name = "" // aka: columnName, named, label, title
     var hidden = true
     var disabled = member.disabledReason.isNotEmpty()
-    var isAmendedFromBs = false
-    var isAmendedFromPropertyDescription = false
+    private var isAmendedFromBs = false
+    private var isAmendedFromPropertyDescription = false
     var typicalLength: Int = 10
 
 
     fun amendWith(pbs: PropertyBs) {
-        console.log("[PS_amendWith] PropertyBs")
-        console.log(pbs)
         name = pbs.named
         hidden = !(pbs.hidden != null && pbs.hidden.isNotEmpty())
         //This is hacky
@@ -55,7 +49,6 @@ class PropertySpecification(member: Member) {
             typicalLength = pbs.typicalLength.toInt()
         }
         isAmendedFromBs = true
-        console.log(this)
     }
 
     fun amendWith(pd: PropertyDescription) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt
new file mode 100644
index 0000000000..05aa7f563b
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt
@@ -0,0 +1,53 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.to.Member
+
+class PropertySpecificationHolder() {
+    var propertySpecificationList = mutableListOf<PropertySpecification>()
+
+    fun getPropertySpecification(id: String): PropertySpecification {
+        return propertySpecificationList.firstOrNull { it.id == id }!!
+    }
+
+    fun readyToRender(): Boolean {
+        return isInitialized() && arePropertySpecificationsReadyToRender()
+    }
+
+    private fun arePropertySpecificationsReadyToRender(): Boolean {
+        propertySpecificationList.forEach {
+            val ready = it.readyToRender()
+            if (!ready) {
+                return false
+            }
+        }
+        return true
+    }
+
+    fun addMember(m: Member) {
+        val ps = PropertySpecification(m)
+        propertySpecificationList.add(ps)
+    }
+
+    fun isInitialized(): Boolean {
+        return propertySpecificationList.isNotEmpty() && propertySpecificationList.size > 0
+    }
+
+}
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
index 4c93d3e460..29d3773225 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
@@ -36,11 +36,11 @@ class PropertyBs(node: Node) : XmlLayout() {
     init {
         // TODO improve casting
         val dn = node.asDynamic()
-        hidden = dn.getAttribute("hidden") //as String
-        id = dn.getAttribute("id") //as String
-        typicalLength = dn.getAttribute("typicalLength") //as Int
-        multiLine = dn.getAttribute("multiLine") //as Int
-        describedAs = dn.getAttribute("describedAs") //as String
+        hidden = dn.getAttribute("hidden").unsafeCast<String>()
+        id = dn.getAttribute("id").unsafeCast<String>()
+        typicalLength = dn.getAttribute("typicalLength").unsafeCast<Int>()
+        multiLine = dn.getAttribute("multiLine").unsafeCast<Int>()
+        describedAs = dn.getAttribute("describedAs").unsafeCast<String>()
 
         val nodeList = node.childNodes.asList()
         val namedList = nodeList.filter { it.nodeName == "$nsCpt:named" }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index 1a710e5b7c..dc52247e6f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -25,7 +25,6 @@ import io.kvision.tabulator.Formatter
 import io.kvision.tabulator.js.Tabulator
 import io.kvision.utils.obj
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
-import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.core.model.Exposer
 import org.apache.causeway.client.kroviz.ui.menu.DynamicMenuBuilder
 
@@ -46,8 +45,6 @@ class ColumnFactory {
         addColumnForObjectIcon(displayCollection, columns)
         addColumnsForProperties(displayCollection, columns)
         columns.add(columnForObjectMenu())
-        console.log("[CF_buildColumns]")
-        console.log(columns)
         return columns
     }
 
@@ -106,7 +103,7 @@ class ColumnFactory {
         collectionModel: CollectionDM,
         columns: MutableList<ColumnDefinition<Exposer>>,
     ) {
-        val clo = collectionModel.getLayout()
+        val clo = collectionModel.propertySpecificationHolder
         val propSpecList = clo.propertySpecificationList
         if (propSpecList.size == 0) {
             // without this, propSpecList is empty? problem with mutable list?
@@ -117,6 +114,7 @@ class ColumnFactory {
                 var colDef = ColumnDefinition<dynamic>(
                     title = it.name,
                     field = it.id,
+                    width = (it.typicalLength * 8).toString(),
                     headerFilter = Editor.INPUT)
                 if (it.id == "object") {
                     colDef = buildLink()
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 02a7d4386b..12c3fb1ac7 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -173,9 +173,7 @@ object ViewManager {
     }
 
     fun openObjectView(aggregator: ObjectAggregator) {
-        console.log("[VM_openObjectView]")
         val dm = aggregator.getDisplayModel()
-//        console.log(dm)
         val panel = RoDisplay(dm)
         add(aggregator.getTitle(), panel, aggregator)
         dm.isRendered = true


[causeway] 05/10: ISIS-3171 PropertySpecification amended with object-layout.xml (per 'protoType')

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 35a43a8bcf9332d78309616899fcb933573a05d3
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Wed Feb 15 22:40:56 2023 +0100

    ISIS-3171 PropertySpecification amended with object-layout.xml (per 'protoType')
---
 .../collection_layout_aggregation_diagram.adoc     |  14 +-
 .../kroviz/core/aggregator/AggregatorWithLayout.kt |   6 +-
 .../kroviz/core/aggregator/CollectionAggregator.kt |  24 +-
 .../client/kroviz/core/model/BaseLayout.kt         |  16 -
 .../client/kroviz/core/model/CollectionDM.kt       |  29 +-
 .../client/kroviz/core/model/CollectionLayout.kt   |  49 ++-
 .../causeway/client/kroviz/core/model/ObjectDM.kt  |   2 +-
 .../client/kroviz/core/model/ObjectLayout.kt       |  21 --
 .../kroviz/core/model/PropertySpecification.kt     |  48 ++-
 .../test/resources/object-layout_collection.xml    | 337 +++++++++++++++++++++
 10 files changed, 420 insertions(+), 126 deletions(-)

diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
index bbef7a319d..523ad3d247 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
@@ -3,8 +3,8 @@
 ----
 allowmixing
 
-() START
-() END
+() START #green
+() END #red
 together {
     file "object-layout" <<BootStrap XML>> as OL #lightblue
     class GridBs <<(T,tomato)TransferObject>> #lightgreen {}
@@ -27,6 +27,7 @@ together {
     TObject .. O
 }
 file "collection-description" <<JSON>> as CD #lightblue
+file "object-layout" <<JSON>> as OLJ #lightblue
 
 together {
     file "object-property" <<JSON>> as OP #lightblue
@@ -48,9 +49,10 @@ START --> OL : menu action \ninvoked by user
 OL --> OC : contains\nreference\nto
 OC --> CD : contains\ncollection\ntitle
 OC --> O : contains\nreference\nto
+O --> OLJ
 O --> OP : contains\nreference\nto
 OP -> PD : contains\nreference\nto
-PD --> END
+PD -r-> END
 
 ' references between TO classes
 GridBs o-->"0.n" Collection
@@ -124,5 +126,11 @@ iterate over value[]
 and add data to DisplayModel
 end note
 
+legend left
+    <back:#lightblue> Description           </back>
+    <back:#lightgreen> Party, place, thing</back>
+    <back:#pink> Moment, Interval   </back>
+    <back:#lightyellow> Role                       </back>
+endlegend
 
 ----
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
index 54eb826efe..b114488c4f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/AggregatorWithLayout.kt
@@ -54,17 +54,13 @@ abstract class AggregatorWithLayout : BaseAggregator() {
     protected fun handleProperty(property: Property, referrer: String, layout: BaseLayout) {
         when {
             property.isObjectProperty() -> {
-                console.log("[AWL_handleProperty] objectProperty")
                 val op = ObjectProperty(property)
-                layout.addObjectProperty(op, this, referrer)
                 val pdLink = op.getDescriptionLink()!!
                 ResourceProxy().fetch(pdLink, this, referrer = referrer)
             }
 
             property.isPropertyDescription() -> {
-                console.log("[AWL_handleProperty] propertyDescription")
-                val pd = PropertyDescription(property)
-                layout.addPropertyDescription(pd, this, referrer)
+                console.log("[AWL_handleProperty] PropertyDescription obsolete?")
             }
 
             else -> {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index e31da813c9..07ea8ebc5f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -25,6 +25,8 @@ import org.apache.causeway.client.kroviz.core.event.ResourceSpecification
 import org.apache.causeway.client.kroviz.core.model.CollectionDM
 import org.apache.causeway.client.kroviz.core.model.CollectionLayout
 import org.apache.causeway.client.kroviz.to.*
+import org.apache.causeway.client.kroviz.to.bs.GridBs
+import org.apache.causeway.client.kroviz.ui.core.Constants
 import org.apache.causeway.client.kroviz.ui.core.ViewManager
 
 /** sequence of operations:
@@ -54,7 +56,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
                 is ResultList -> handleList(obj)
                 is TObject -> handleObject(obj)
                 is DomainType -> handleDomainType(obj)
-                //is GridBs -> Unit //In the case of CollectionDM, object-layout can be ignored
+                is GridBs -> handleLayout(obj)
                 is Property -> handleProperty(obj)
                 is Collection -> handleCollection(obj)
                 is Icon -> handleIcon(obj)
@@ -99,15 +101,21 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
         }
     }
 
-    private fun handleObject(obj: TObject) {
-        displayModel.addData(obj, this, referrer)
-
-        getLayout().initColumns(obj)
+    private fun handleLayout(grid: GridBs) {
+        getDisplayModel().setProtoTypeLayout(grid)
+    }
 
-        if (isStandAloneCollection()) {
-            invokeLayoutLink(obj, this, referrer = referrer)
+    private fun handleObject(tObj: TObject) {
+        val dm = getDisplayModel()
+        dm.addData(tObj)
+        if (!dm.hasProtoType()) {
+            dm.setProtoType(tObj)
+            invokeLayoutLink(tObj, this, referrer = referrer)
         }
-        invokeIconLink(obj, this, referrer = referrer)
+        //TODO fold layout into model
+        getLayout().addObject(tObj, this, referrer = referrer)
+
+        invokeIconLink(tObj, this, referrer = referrer)
     }
 
     private fun isStandAloneCollection(): Boolean {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
index 206ae67da1..e2625c75e6 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/BaseLayout.kt
@@ -18,24 +18,8 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
-import org.apache.causeway.client.kroviz.to.ObjectProperty
-import org.apache.causeway.client.kroviz.to.PropertyDescription
-
 abstract class BaseLayout {
 
-    abstract fun addObjectProperty(
-        objectProperty: ObjectProperty,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    )
-
-    abstract fun addPropertyDescription(
-        propertyDescription: PropertyDescription,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    )
-
     abstract fun readyToRender(): Boolean
 
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index e0f387683b..af6e1371e5 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -23,6 +23,7 @@ import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.TObject
 import org.apache.causeway.client.kroviz.to.TransferObject
+import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.utils.StringUtils
 
 class CollectionDM(override val title: String) : DisplayModelWithLayout() {
@@ -33,6 +34,24 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     var id = ""
     var data = observableListOf<Exposer>()
     private var rawData = observableListOf<TransferObject>()
+    private var protoType: TObject? = null
+    private var protoTypeLayout: GridBs? = null
+
+    fun setProtoTypeLayout(grid: GridBs) {
+        protoTypeLayout = grid
+        val propertyList = grid.getPropertyList()
+        propertyList.forEach{
+            getLayout().addPropertyDetails(it)
+        }
+    }
+
+    fun hasProtoType(): Boolean {
+        return protoType != null
+    }
+
+    fun setProtoType(to:TransferObject){
+        protoType = to as TObject
+    }
 
     override fun readyToRender(): Boolean {
         return getLayout().readyToRender()
@@ -53,16 +72,6 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
             val exo = Exposer(obj as TObject)
             data.add(exo.dynamise())  //if exposer is not dynamised, data access in Tabulator tables won't work
         }
-        // for the first element, invoke ObjectProperty & PropertyDescription links
-        if (rawData.size == 1) {
-            val tObj = obj as TObject
-            val properties = tObj.getProperties()
-            properties.forEach {
-                val opLink = it.getInvokeLink()!!
-                ResourceProxy().fetch(opLink, aggregator, referrer = referrer!!)
-                //FIXME is PropertyDescription automatically invoked?
-            }
-        }
     }
 
     override fun reset() {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
index 5cb4d4b08b..92f1a48ef1 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -18,14 +18,13 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
+import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
-import org.apache.causeway.client.kroviz.to.ObjectProperty
-import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.TObject
+import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 
 /**
- * For (parented) collections aggregate information for each column
+ * For collections aggregate information for each column
  * in order to display the table, namely:
  * - columnName :   column header/label
  * - id :           attribute to be used to retrieve the value of each cell (id)
@@ -33,16 +32,16 @@ import org.apache.causeway.client.kroviz.to.TObject
  */
 class CollectionLayout : BaseLayout() {
     var id = ""
-    val propertySpecificationList = mutableListOf<PropertySpecification>()
+    var propertySpecificationList = mutableListOf<PropertySpecification>()
 
     override fun readyToRender(): Boolean {
-        console.log("[CL_readyToRender]")
         return isInitialized() && arePropertySpecificationsReadyToRender()
     }
 
     private fun arePropertySpecificationsReadyToRender():Boolean {
         propertySpecificationList.forEach {
-            if (!it.readyToRender()) {
+            val ready = it.readyToRender()
+            if (!ready) {
                 return false
             }
         }
@@ -53,13 +52,15 @@ class CollectionLayout : BaseLayout() {
      * collection layout needs only to be initialized once with an object (pars pro toto, prototype)
      * obj acts as a kind prototype - we assume all elements in the collection have the same structure
      */
-    fun initColumns(obj: TObject) {
+    fun addObject(obj: TObject, aggregator: CollectionAggregator, referrer: String) {
         if (!isInitialized()) {
             // members contain all properties, regardless if hidden, disabled, etc.
             val members = obj.getProperties()
             members.forEach { m ->
                 val ps = PropertySpecification(m)
                 propertySpecificationList.add(ps)
+                val l = m.getInvokeLink()!!
+                ResourceProxy().fetch(l, aggregator, referrer = referrer)
             }
         }
     }
@@ -68,31 +69,15 @@ class CollectionLayout : BaseLayout() {
         return propertySpecificationList.isNotEmpty() && propertySpecificationList.size > 0
     }
 
-    override fun addObjectProperty(
-        objectProperty: ObjectProperty,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
-        console.log("[CL_addObjectProperty]")
-        val l = objectProperty.getDescriptionLink()!!
-        // FIXME NPE -> ISIS-2846 ?
-        //invoking DN links leads to an error
-        val isDn = l.href.contains("datanucleus") // Outdated?
-        if (!isDn) {
-            ResourceProxy().fetch(l, aggregator, referrer = referrer)
-        }
-    }
-
-    override fun addPropertyDescription(
-        propertyDescription: PropertyDescription,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
-        console.log("[CL_addPropertyDescription]")
-        val id = propertyDescription.id
+    fun addPropertyDetails(propertyBs: PropertyBs) {
+        val id = propertyBs.id
         val ps: PropertySpecification = propertySpecificationList.firstOrNull { it.id == id }!!
-        console.log(ps)
-        ps.amendWith(propertyDescription)
+        ps.amendWith(propertyBs)
     }
 
+    // FIXME NPE -> ISIS-2846 ?
+    //FIXME hidden etc is not contained in ObjectProperty, see GidBs for the collection.protoType
+    // e.g. http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/object-layout
+    // furthermore, the column header can be taken from there as well
+
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index b5242ecbcb..57a952fe52 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -82,7 +82,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         obj.getProperties().forEach { m ->
             val p = createPropertyFrom(m)
             val op = ObjectProperty(p)
-            layout?.addObjectProperty(op, aggregator!!, referrer!!)
+//FIXME            layout?.addObjectProperty(op, aggregator!!, referrer!!)
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
index d5023d6cd3..9ca18153de 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
@@ -18,13 +18,10 @@
  */
 package org.apache.causeway.client.kroviz.core.model
 
-import org.apache.causeway.client.kroviz.core.aggregator.AggregatorWithLayout
 import org.apache.causeway.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.causeway.client.kroviz.core.aggregator.ObjectAggregator
 import org.apache.causeway.client.kroviz.core.event.ResourceProxy
 import org.apache.causeway.client.kroviz.to.Link
-import org.apache.causeway.client.kroviz.to.ObjectProperty
-import org.apache.causeway.client.kroviz.to.PropertyDescription
 import org.apache.causeway.client.kroviz.to.bs.CollectionBs
 import org.apache.causeway.client.kroviz.to.bs.GridBs
 import org.apache.causeway.client.kroviz.to.bs.RowBs
@@ -49,24 +46,6 @@ class ObjectLayout : BaseLayout() {
         }
     }
 
-    override fun addObjectProperty(
-        objectProperty: ObjectProperty,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
- //       console.log("[OL_addObjectProperty]")
-//        TODO("Not yet implemented")
-    }
-
-    override fun addPropertyDescription(
-        propertyDescription: PropertyDescription,
-        aggregator: AggregatorWithLayout,
-        referrer: String
-    ) {
-        console.log("[OL_addPropertyDescription]")
-//        TODO("Not yet implemented")
-    }
-
     fun addGrid(grid: GridBs, aggregator: ObjectAggregator, referrer: String?) {
         this.grid = grid
         grid.rows.forEach { r ->
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index 346fc4e236..187d464294 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -19,8 +19,7 @@
 package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.to.Member
-import org.apache.causeway.client.kroviz.to.ObjectProperty
-import org.apache.causeway.client.kroviz.to.PropertyDescription
+import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 
 /**
  * Properties have multiple aspects:
@@ -33,42 +32,31 @@ import org.apache.causeway.client.kroviz.to.PropertyDescription
  * All are required in order to be correctly displayed (in a table).
  */
 class PropertySpecification(member: Member) {
-    var id = ""
+    var id = member.id
     var name = "" // aka: columnName, named, label, title
-    var hidden = false
-    var disabled = false
-    var isPropertyDescriptionProcessed = false
-    var isObjectPropertyProcessed = true //FIXME
+    var hidden = true
+    var disabled = member.disabledReason.isNotEmpty()
+    var isAmendedFromBs = false
+    var typicalLength: Int = 10
 
-    init {
-        id = member.id
-        name = member.id // can be changed later via property-description
-        hidden = false // can be changed later via ...
-        //FIXME
-        if (name == "sources" || name == "description" || name == "logicalTypeName") {
-            hidden = true
-        }
-        disabled = member.disabledReason.isNotEmpty()
-    }
 
-    fun amendWith(op: ObjectProperty) {
-        console.log("[PS_amendWith] ObjectProperty")
-        //TODO
-    }
-
-    fun amendWith(pd: PropertyDescription) {
-        console.log("[PS_amendWith] PropertyDescription")
-        val ex = pd.extensions!!
-        val fn = ex.getFriendlyName()
-        if (fn.isNotEmpty()) {
-            name = fn
+    fun amendWith(pbs: PropertyBs) {
+        console.log("[PS_amendWith] PropertyBs")
+        name = pbs.named
+        hidden = !(pbs.hidden != null && pbs.hidden.isNotEmpty())
+        if (pbs.typicalLength != null && pbs.typicalLength > 0) {
+            typicalLength = pbs.typicalLength.toInt()
         }
-        isPropertyDescriptionProcessed = true
+        isAmendedFromBs = true
         console.log(this)
     }
 
     fun readyToRender(): Boolean {
-        return isObjectPropertyProcessed && isPropertyDescriptionProcessed
+        return when (id) {
+            "logicalTypeName" -> true
+            "objectIdentifier" -> true
+            else -> isAmendedFromBs
+        }
     }
 
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/test/resources/object-layout_collection.xml b/incubator/clients/kroviz/src/test/resources/object-layout_collection.xml
new file mode 100644
index 0000000000..ab9044b4ca
--- /dev/null
+++ b/incubator/clients/kroviz/src/test/resources/object-layout_collection.xml
@@ -0,0 +1,337 @@
+<bs:grid xmlns:cpt="http://causeway.apache.org/applib/layout/component"
+         xmlns:bs="http://causeway.apache.org/applib/layout/grid/bootstrap3"
+         xmlns:lnk="http://causeway.apache.org/applib/layout/links">
+    <bs:row>
+        <bs:col span="10" unreferencedActions="true">
+            <cpt:domainObject>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/element</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356</lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object"</lnk:type>
+                </cpt:link>
+            </cpt:domainObject>
+            <cpt:action id="actionReturning">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/actionReturning
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action id="actionReturningCollection">
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/actionReturningCollection
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action cssClassFa="fa fa-fw fa-download" cssClassFaPosition="LEFT" id="downloadLayout">
+                <cpt:named>Download Layout</cpt:named>
+                <cpt:describedAs>Downloads the Xxx.layout... layout file effective/inferred for this object
+                </cpt:describedAs>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/downloadLayout
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action cssClassFa="fa fa-fw fa-mask" cssClassFaPosition="LEFT" id="impersonate">
+                <cpt:named>Impersonate</cpt:named>
+                <cpt:describedAs>Switch to another user account (for prototype/testing only)</cpt:describedAs>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/impersonate
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action cssClassFa="fa fa-fw fa-mask" cssClassFaPosition="LEFT" id="impersonateWithRoles">
+                <cpt:named>Impersonate With Roles</cpt:named>
+                <cpt:describedAs>Switch to another user account with specified roles (for prototype/testing only)
+                </cpt:describedAs>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/impersonateWithRoles
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action cssClassFa="fa fa-fw fa-bolt" cssClassFaPosition="LEFT" id="recentExecutions">
+                <cpt:named>Recent Executions</cpt:named>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/recentExecutions
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+            <cpt:action cssClassFa="fa fa-fw fa-bolt" cssClassFaPosition="LEFT" id="recentAuditTrailEntries">
+                <cpt:named>Recent Audit Trail Entries</cpt:named>
+                <cpt:link>
+                    <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                    <lnk:method>GET</lnk:method>
+                    <lnk:href>
+                        http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/recentAuditTrailEntries
+                    </lnk:href>
+                    <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                </cpt:link>
+            </cpt:action>
+        </bs:col>
+        <bs:col span="2">
+            <cpt:fieldSet name="" id="sources">
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES" id="sources" labelPosition="NONE">
+                    <cpt:named>Sources</cpt:named>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/sources
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+        </bs:col>
+    </bs:row>
+    <bs:row>
+        <bs:col span="6">
+            <cpt:fieldSet name="Read Only Properties" id="read-only-properties">
+                <cpt:property dateRenderAdjustDays="0" id="readOnlyProperty" labelPosition="LEFT" typicalLength="25">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyProperty
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+            <cpt:fieldSet name="Editable Properties" id="editable-properties">
+                <cpt:property dateRenderAdjustDays="0" id="readWriteProperty" labelPosition="LEFT" typicalLength="25">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readWriteProperty
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+            <cpt:fieldSet name="Optional Properties" id="optional-properties">
+                <cpt:property dateRenderAdjustDays="0" id="readOnlyOptionalProperty" labelPosition="LEFT"
+                              typicalLength="25">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyOptionalProperty
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+                <cpt:property dateRenderAdjustDays="0" id="readWriteOptionalProperty" labelPosition="LEFT"
+                              typicalLength="25">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readWriteOptionalProperty
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+            <cpt:fieldSet name="Contributed by Mixins" id="contributed">
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES" id="mixinProperty" typicalLength="25">
+                    <cpt:named>Mixin Property</cpt:named>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/mixinProperty
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+            <cpt:fieldSet name="@PropertyLayout(labelPosition=...)" id="label-positions">
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES" id="readOnlyPropertyDerivedLabelPositionLeft"
+                              labelPosition="LEFT" typicalLength="25">
+                    <cpt:describedAs>@PropertyLayout(labelPosition=LEFT)</cpt:describedAs>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyPropertyDerivedLabelPositionLeft
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES" id="readOnlyPropertyDerivedLabelPositionTop"
+                              labelPosition="TOP" typicalLength="25">
+                    <cpt:describedAs>@PropertyLayout(labelPosition=TOP)</cpt:describedAs>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyPropertyDerivedLabelPositionTop
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES"
+                              id="readOnlyPropertyDerivedLabelPositionRight" labelPosition="RIGHT" typicalLength="25">
+                    <cpt:describedAs>@PropertyLayout(labelPosition=RIGHT)</cpt:describedAs>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyPropertyDerivedLabelPositionRight
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+                <cpt:property dateRenderAdjustDays="0" hidden="ALL_TABLES" id="readOnlyPropertyDerivedLabelPositionNone"
+                              labelPosition="NONE" typicalLength="25">
+                    <cpt:describedAs>@PropertyLayout(labelPosition=NONE)</cpt:describedAs>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/readOnlyPropertyDerivedLabelPositionNone
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+            <cpt:fieldSet name="Other" id="other" unreferencedProperties="true"/>
+        </bs:col>
+        <bs:col span="6">
+            <cpt:fieldSet name="Description" id="description">
+                <cpt:action id="clearHints" position="PANEL">
+                    <cpt:metadataError>No such action</cpt:metadataError>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/clearHints
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="downloadLayoutXml" position="PANEL_DROPDOWN">
+                    <cpt:metadataError>No such action</cpt:metadataError>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/downloadLayoutXml
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="rebuildMetamodel" position="PANEL">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/rebuildMetamodel
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="downloadMetamodelXml" position="PANEL_DROPDOWN">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/downloadMetamodelXml
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="inspectMetamodel" position="PANEL_DROPDOWN">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/inspectMetamodel
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="recentCommands" position="PANEL_DROPDOWN">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/recentCommands
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="downloadJdoMetadata" position="PANEL_DROPDOWN">
+                    <cpt:metadataError>No such action</cpt:metadataError>
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/downloadJdoMetadata
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:action id="openRestApi" position="PANEL_DROPDOWN">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/action</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/actions/openRestApi
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-action"</lnk:type>
+                    </cpt:link>
+                </cpt:action>
+                <cpt:property dateRenderAdjustDays="0" id="description">
+                    <cpt:link>
+                        <lnk:rel>urn:org.restfulobjects:rels/property</lnk:rel>
+                        <lnk:method>GET</lnk:method>
+                        <lnk:href>
+                            http://localhost:9090/restful/objects/demo.JavaLangStringEntity/356/properties/description
+                        </lnk:href>
+                        <lnk:type>application/json;profile="urn:org.restfulobjects:repr-types/object-property"
+                        </lnk:type>
+                    </cpt:link>
+                </cpt:property>
+            </cpt:fieldSet>
+        </bs:col>
+    </bs:row>
+    <bs:row>
+        <bs:col span="12" unreferencedCollections="true"/>
+    </bs:row>
+</bs:grid>
\ No newline at end of file


[causeway] 10/10: ISIS-3171 Collection and Object displayed

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 2f2f71a67a4e39df0897e1a02489bd6636d71033
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 23 21:07:22 2023 +0100

    ISIS-3171 Collection and Object displayed
---
 .../kroviz/core/aggregator/ActionDispatcher.kt     |  2 +-
 .../kroviz/core/aggregator/CollectionAggregator.kt |  2 +-
 .../core/aggregator/DomainTypesAggregator.kt       |  3 +-
 .../kroviz/core/aggregator/ObjectAggregator.kt     | 22 ++++---
 .../kroviz/core/aggregator/SystemAggregator.kt     |  9 +--
 .../client/kroviz/core/model/CollectionDM.kt       |  8 +--
 .../client/kroviz/core/model/ColumnProperties.kt   | 41 +++++++++++++
 ...ertySpecification.kt => ColumnSpecification.kt} |  2 +-
 ...ationHolder.kt => ColumnSpecificationHolder.kt} | 16 ++---
 .../causeway/client/kroviz/core/model/ObjectDM.kt  | 15 ++++-
 .../kroviz/core/model/ObjectSpecificationHolder.kt | 69 ++++++++++++++++++++++
 .../apache/causeway/client/kroviz/to/Property.kt   |  6 ++
 .../causeway/client/kroviz/to/bs/PropertyBs.kt     |  2 +-
 .../client/kroviz/ui/builder/ColBuilder.kt         |  3 +-
 .../client/kroviz/ui/core/ColumnFactory.kt         |  4 +-
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |  9 +++
 16 files changed, 178 insertions(+), 35 deletions(-)

diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ActionDispatcher.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ActionDispatcher.kt
index ed33ef6a1b..8f34746442 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ActionDispatcher.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ActionDispatcher.kt
@@ -50,7 +50,7 @@ class ActionDispatcher(private val at: Point = Point(100, 100)) : BaseAggregator
             }
             to is Restful -> {}
             else -> {
-                console.log(to)
+//                console.log(to)
 //                throw Throwable("[ActionDispatcher.update] ${to!!::class.simpleName}")
             }
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 558fda52ac..e990959d77 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -108,7 +108,7 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
 
         // collection layout needs only to be initialized once with an object (pars pro toto, prototype)
         // obj acts as a kind prototype - we assume all elements in the collection have the same structure
-        val propertySpecificationHolder = getDisplayModel().propertySpecificationHolder
+        val propertySpecificationHolder = getDisplayModel().columnSpecificationHolder
         if (!propertySpecificationHolder.isInitialized()) {
             val members = tObj.getProperties()
             members.forEach { m ->
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
index 06b74a3a24..e5a1963b2a 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/DomainTypesAggregator.kt
@@ -49,8 +49,7 @@ class DomainTypesAggregator(val url: String) : BaseAggregator() {
     }
 
     private fun handleAction(obj: Action) {
-        console.log("[DTA.handleAction] $obj")
-        throw Throwable("[DomainTypesAggregator.handleAction] not implemented yet")  //dsp.addData(obj)
+        TODO("[DomainTypesAggregator.handleAction] not implemented yet")
     }
 
     private fun handleDomainType(obj: DomainType) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
index 32b12dce3b..202b634238 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -35,7 +35,8 @@ import org.apache.causeway.client.kroviz.utils.StringUtils
  * (3) ???_OBJECT_PROPERTY       PropertyHandler -> invoke()
  * (4) ???_PROPERTY_DESCRIPTION  <PropertyDescriptionHandler>
  */
-class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
+class ObjectAggregator(private val actionTitle: String) : AggregatorWithLayout() {
+    private var isContainedInParentCollection = false
 
     init {
         displayModel = ObjectDM(actionTitle)
@@ -43,7 +44,9 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
 
     override fun update(logEntry: LogEntry, subType: String?) {
         super.update(logEntry, subType)
-        if (!logEntry.isUpdatedFromParentedCollection()) {
+        if (logEntry.isUpdatedFromParentedCollection()) {
+            isContainedInParentCollection = true
+        } else {
             val referrer = logEntry.url
             when (val obj = logEntry.getTransferObject()) {
                 is TObject -> handleObject(obj, referrer)
@@ -99,10 +102,15 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         return displayModel.getObject()
     }
 
-    private fun handleProperty(property: Property, referrer: String) {
-        //(property, referrer) //FIXME
-        console.log("[OA_handleProperty] not handled")
-        console.log(property)
+    private fun handleProperty(p: Property, referrer: String) {
+        val dm = getDisplayModel()
+        if (p.isPropertyDescription()) {
+            dm.addPropertyDescription(p)
+        } else {
+            dm.addProperty(p)
+            val pdl = p.getDescriptionLink() ?: return
+            invoke(pdl, this, referrer = referrer)
+        }
     }
 
     private fun handleGrid(grid: GridBs, referrer: String) {
@@ -131,7 +139,7 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
     }
 
     /**
-     * This is done in order to have the parent check, if it and it's children can be displayed
+     * This is done in order to have the parent check, if itself and it's children can be displayed
      */
     private fun LogEntry.isUpdatedFromParentedCollection(): Boolean {
         return this.url == ""
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
index d50d3e764c..e186f05416 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/SystemAggregator.kt
@@ -24,10 +24,11 @@ import org.apache.causeway.client.kroviz.to.DomainTypes
 import org.apache.causeway.client.kroviz.to.User
 import org.apache.causeway.client.kroviz.to.Version
 import org.apache.causeway.client.kroviz.ui.core.SessionManager
+import org.apache.causeway.client.kroviz.ui.core.ViewManager
 import org.apache.causeway.client.kroviz.utils.ImageUtils
 import org.apache.causeway.client.kroviz.utils.UrlUtils
 
-class SystemAggregator() : BaseAggregator() {
+class SystemAggregator : BaseAggregator() {
 
     init {
         displayModel = SystemDM("not filled (yet)")
@@ -42,13 +43,13 @@ class SystemAggregator() : BaseAggregator() {
                 if (logEntry.blob != null) {
                     val icon = ImageUtils.extractIcon(logEntry)
                     val url = logEntry.url
-                    val isApplicationIcon = UrlUtils.isApplicationIcon(url)
-                    when (isApplicationIcon) {
+                    when (UrlUtils.isApplicationIcon(url)) {
                         url.contains("48") -> {
                             (displayModel as SystemDM).addSmallIcon(icon)
                             val iconUrl = icon.image.src
                             SessionManager.setApplicationIcon(iconUrl)
                         }
+
                         url.contains("256") -> (displayModel as SystemDM).addLargeIcon(icon)
                         else -> log(logEntry)
                     }
@@ -59,7 +60,7 @@ class SystemAggregator() : BaseAggregator() {
         }
 
         if (displayModel.readyToRender()) {
-//  TODO          UiManager.openObjectView(this)
+            ViewManager.openObjectView(this)
         }
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index 84ded48825..a0a3b53eed 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -27,7 +27,7 @@ import org.apache.causeway.client.kroviz.to.bs.PropertyBs
 import org.apache.causeway.client.kroviz.utils.StringUtils
 
 class CollectionDM(override val title: String) : DisplayModelWithLayout() {
-    val propertySpecificationHolder = PropertySpecificationHolder()
+    val columnSpecificationHolder = ColumnSpecificationHolder()
 
     var id = ""
     var data = observableListOf<Exposer>()
@@ -45,13 +45,13 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
 
     private fun addPropertyDetails(propertyBs: PropertyBs) {
         val id = propertyBs.id
-        val ps = propertySpecificationHolder.getPropertySpecification(id)
+        val ps = columnSpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyBs)
     }
 
     fun addPropertyDescription(propertyDescription: PropertyDescription) {
         val id = propertyDescription.id
-        val ps = propertySpecificationHolder.getPropertySpecification(id)
+        val ps = columnSpecificationHolder.getPropertySpecification(id)
         ps.amendWith(propertyDescription)
     }
 
@@ -64,7 +64,7 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     }
 
     override fun readyToRender(): Boolean {
-        return propertySpecificationHolder.readyToRender()
+        return columnSpecificationHolder.readyToRender()
     }
 
     fun getTitle(): String {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt
new file mode 100644
index 0000000000..19513ec867
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnProperties.kt
@@ -0,0 +1,41 @@
+/*
+ *  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.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.layout.PropertyLt
+import org.apache.causeway.client.kroviz.to.Property
+import org.apache.causeway.client.kroviz.to.bs.PropertyBs
+
+/**
+ * Properties have three aspects:
+ *
+ * - Member of a DomainObject
+ * - Description (friendlyName, etc.)
+ * - Layout (hidden, labelPosition, etc.)
+ *
+ * All three are required in order to display correctly in a table.
+ */
+@Deprecated("Rework/Rename")
+class ColumnProperties(val key: String) {
+    var property: Property? = null
+    var friendlyName: String = ""
+    var layout: PropertyLt? = null
+    var grid: PropertyBs? = null
+    var hidden: Boolean = false
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecification.kt
similarity index 98%
rename from incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
rename to incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecification.kt
index bbb872de0e..ee009457b7 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecification.kt
@@ -28,7 +28,7 @@ import org.apache.causeway.client.kroviz.to.bs.PropertyBs
  * - id :           attribute to be used to retrieve the value of each cell (id)
  * - hidden :       will the column be displayed or not
  */
-class PropertySpecification(member: Member) {
+class ColumnSpecification(member: Member) {
     var id = member.id
     var name = "" // aka: columnName, named, label, title
     var hidden = true
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecificationHolder.kt
similarity index 74%
rename from incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt
rename to incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecificationHolder.kt
index 05aa7f563b..15dca34982 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecificationHolder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ColumnSpecificationHolder.kt
@@ -20,11 +20,11 @@ package org.apache.causeway.client.kroviz.core.model
 
 import org.apache.causeway.client.kroviz.to.Member
 
-class PropertySpecificationHolder() {
-    var propertySpecificationList = mutableListOf<PropertySpecification>()
+class ColumnSpecificationHolder {
+    var columnSpecificationList = mutableListOf<ColumnSpecification>()
 
-    fun getPropertySpecification(id: String): PropertySpecification {
-        return propertySpecificationList.firstOrNull { it.id == id }!!
+    fun getPropertySpecification(id: String): ColumnSpecification {
+        return columnSpecificationList.firstOrNull { it.id == id }!!
     }
 
     fun readyToRender(): Boolean {
@@ -32,7 +32,7 @@ class PropertySpecificationHolder() {
     }
 
     private fun arePropertySpecificationsReadyToRender(): Boolean {
-        propertySpecificationList.forEach {
+        columnSpecificationList.forEach {
             val ready = it.readyToRender()
             if (!ready) {
                 return false
@@ -42,12 +42,12 @@ class PropertySpecificationHolder() {
     }
 
     fun addMember(m: Member) {
-        val ps = PropertySpecification(m)
-        propertySpecificationList.add(ps)
+        val ps = ColumnSpecification(m)
+        columnSpecificationList.add(ps)
     }
 
     fun isInitialized(): Boolean {
-        return propertySpecificationList.isNotEmpty() && propertySpecificationList.size > 0
+        return columnSpecificationList.isNotEmpty() && columnSpecificationList.size > 0
     }
 
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index 3ed71589f1..7e44620dc4 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -25,7 +25,7 @@ import org.apache.causeway.client.kroviz.to.*
 import org.apache.causeway.client.kroviz.ui.core.SessionManager
 
 class ObjectDM(override val title: String) : DisplayModelWithLayout() {
-
+    val properties = ObjectSpecificationHolder()
     init {
         layout = ObjectLayout()
     }
@@ -53,7 +53,7 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
     }
 
     fun getCollectionDisplayModelFor(id: String): CollectionDM {
-        return collectionModelList.find { it.id == id }!!
+        return collectionModelList.firstOrNull() { it.id == id }!!
     }
 
     override fun readyToRender(): Boolean {
@@ -61,11 +61,11 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
             data == null -> false
             isRendered -> false
             layout == null -> false
-            collectionModelList.size == 0 -> false
             else -> layout!!.readyToRender() && areCollectionsReadyToRender()
         }
     }
 
+
     private fun areCollectionsReadyToRender(): Boolean {
         collectionModelList.forEach {
             if (!it.readyToRender())
@@ -85,6 +85,15 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         }
     }
 
+    fun addPropertyDescription(p: Property) {
+        properties.addPropertyDescription(p)
+    }
+
+    fun addProperty(property: Property) {
+        properties.addProperty(property)
+    }
+
+
     fun addResult(resultObject: ResultObject) {
         val tObj = createObjectFrom(resultObject)
         this.addData(tObj)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectSpecificationHolder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectSpecificationHolder.kt
new file mode 100644
index 0000000000..9895740d8d
--- /dev/null
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectSpecificationHolder.kt
@@ -0,0 +1,69 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.causeway.client.kroviz.core.model
+
+import org.apache.causeway.client.kroviz.layout.PropertyLt
+import org.apache.causeway.client.kroviz.to.Extensions
+import org.apache.causeway.client.kroviz.to.Property
+
+@Deprecated("Rework/Rename")
+class ObjectSpecificationHolder {
+    val list = mutableListOf<ColumnProperties>()
+    private var propertyDescriptionList = mutableListOf<Property>()
+    private var propertyLayoutList = mutableListOf<PropertyLt>()
+    var propertyList = mutableListOf<Property>()
+    private var descriptionsComplete = false
+
+    fun readyToRender(): Boolean {
+        val ps = propertyList.size
+        val pls = propertyLayoutList.size
+        val pds = propertyDescriptionList.size
+        descriptionsComplete = (pds >= pls) && (ps >= pls)
+        return descriptionsComplete
+    }
+
+    fun addProperty(property: Property) {
+        propertyList.add(property)
+        val id = property.id
+        val cp = findOrCreate(id)
+        cp.property = property
+    }
+
+    fun addPropertyDescription(description: Property) {
+        propertyDescriptionList.add(description)
+        val id = description.id
+        val cp = findOrCreate(id)
+        val e: Extensions = description.extensions!!
+        cp.friendlyName = e.getFriendlyName()
+    }
+
+    private fun findOrCreate(id: String): ColumnProperties {
+        var cp = find(id)
+        if (cp == null) {
+            cp = ColumnProperties(id)
+            list.add(cp)
+        }
+        return cp
+    }
+
+    fun find(id: String): ColumnProperties? {
+        return list.find { it.key == id }
+    }
+
+}
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
index cfa92fe569..a837a3f757 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/Property.kt
@@ -39,6 +39,12 @@ data class Property(
         return getType() == Represention.OBJECT_PROPERTY
     }
 
+    fun getDescriptionLink(): Link? {
+        return this.links.firstOrNull {
+            it.rel == Relation.DESCRIBED_BY.type
+        }
+    }
+
     fun isPropertyDescription(): Boolean {
         return getType() == Represention.PROPERTY_DESCRIPTION
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
index a9a42ee5cc..f37f7a8131 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/to/bs/PropertyBs.kt
@@ -34,7 +34,7 @@ class PropertyBs(node: Node) : XmlLayout() {
     lateinit var action: ActionBs
 
     init {
-        // TODO improve casting, in PropertySpecification some extra check have to be performed
+        // TODO improve casting, in ColumnSpecification some extra check have to be performed
         val dn = node.asDynamic()
         hidden = dn.getAttribute("hidden").unsafeCast<String>()
         id = dn.getAttribute("id").unsafeCast<String>()
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
index 279a637fe2..3f83e6b438 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
@@ -69,10 +69,11 @@ class ColBuilder : UiBuilder() {
             val id = it.id
             val objectDM = dsp.displayModel
             val cdm = objectDM.getCollectionDisplayModelFor(id)
+            if (cdm != null) {
             val fsPanel = FieldsetPanel(legend = cdm.getTitle())
             fsPanel.add(RoTable(cdm))
             panel.add(fsPanel)
-            cdm.isRendered = true
+            cdm.isRendered = true}
         }
         return panel
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index dc52247e6f..bb3b1b9962 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -103,8 +103,8 @@ class ColumnFactory {
         collectionModel: CollectionDM,
         columns: MutableList<ColumnDefinition<Exposer>>,
     ) {
-        val clo = collectionModel.propertySpecificationHolder
-        val propSpecList = clo.propertySpecificationList
+        val clo = collectionModel.columnSpecificationHolder
+        val propSpecList = clo.columnSpecificationList
         if (propSpecList.size == 0) {
             // without this, propSpecList is empty? problem with mutable list?
             throw IllegalStateException()
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 12c3fb1ac7..37e219cf29 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -29,6 +29,7 @@ import kotlinx.browser.window
 import org.apache.causeway.client.kroviz.App
 import org.apache.causeway.client.kroviz.core.aggregator.BaseAggregator
 import org.apache.causeway.client.kroviz.core.aggregator.ObjectAggregator
+import org.apache.causeway.client.kroviz.core.aggregator.SystemAggregator
 import org.apache.causeway.client.kroviz.core.aggregator.UndefinedDispatcher
 import org.apache.causeway.client.kroviz.core.event.EventStore
 import org.apache.causeway.client.kroviz.core.event.StatusPo
@@ -172,6 +173,14 @@ object ViewManager {
         setNormalCursor()
     }
 
+    fun openObjectView(aggregator: SystemAggregator) {
+        console.log("[VM_openObjectView]")
+        val dm = aggregator.displayModel
+/*        val panel = RoDisplay(dm)
+        add(aggregator.getTitle(), panel, aggregator)*/
+        dm.isRendered = true
+        setNormalCursor()
+    }
     fun openObjectView(aggregator: ObjectAggregator) {
         val dm = aggregator.getDisplayModel()
         val panel = RoDisplay(dm)


[causeway] 03/10: ISIS-3171 table is shown, hidden/disabled/name not correctly set yet

Posted by jo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

joergrade pushed a commit to branch ISIS-3171
in repository https://gitbox.apache.org/repos/asf/causeway.git

commit 021eed2391a2fb105514db4b5a6a5651ebcade1c
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Thu Feb 9 18:46:29 2023 +0100

    ISIS-3171 table is shown, hidden/disabled/name not correctly set yet
---
 .../collection_layout_aggregation_diagram.adoc     |  7 +++++--
 .../kroviz/core/aggregator/CollectionAggregator.kt | 11 ++++++-----
 .../client/kroviz/core/model/CollectionDM.kt       |  6 +++++-
 .../client/kroviz/core/model/CollectionLayout.kt   | 19 ++++--------------
 .../causeway/client/kroviz/core/model/ObjectDM.kt  | 15 +++++++++++++-
 .../client/kroviz/core/model/ObjectLayout.kt       | 12 ++++-------
 .../kroviz/core/model/PropertySpecification.kt     |  4 ++++
 .../client/kroviz/ui/builder/ColBuilder.kt         |  2 ++
 .../client/kroviz/ui/core/ColumnFactory.kt         | 23 +++++++++++++---------
 .../causeway/client/kroviz/ui/core/ViewManager.kt  |  2 +-
 10 files changed, 59 insertions(+), 42 deletions(-)

diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
index 365fb2890b..bbef7a319d 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/collection_layout_aggregation_diagram.adoc
@@ -64,12 +64,13 @@ together {
     }
     class ObjectDM <<(M,orange)DisplayModel>> #lightyellow {
         layout
-        collectionDmMap
+        collectionModelList
         data: Exposer
         readyToRender()
     }
     class ObjectLayout <<(L,orange)Layout>> #pink {
         grid
+        collectionLayoutList
         readyToRender()
     }
     ObjectAggregator --> ObjectDM
@@ -86,19 +87,21 @@ together {
         isParentedCollection()
     }
     class CollectionDM <<(M,coral)DisplayModel>> #lightyellow {
+        id
         layout
         data[]: Exposer
         readyToRender()
     }
     class CollectionLayout <<(L,coral)Layout>> #pink{
         numberOfColumns
-        propertySpecificationMap
+        propertySpecificationList
         readyToRender()
     }
     CollectionAggregator --> CollectionDM
     CollectionDM --> CollectionLayout
 }
 ObjectDM o-r-> CollectionDM
+ObjectLayout o-> CollectionLayout
 
 ' references between Layout and TO classes
 CollectionLayout ..> TObject : handles
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
index 17aabcb0f7..e31da813c9 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -141,13 +141,14 @@ class CollectionAggregator(actionTitle: String, private val parent: ObjectAggreg
     }
 
     private fun handleCollection(collection: Collection) {
-        console.log("[CA_handleCollection]")
         if (isParentedCollection()) {
-            val cdm = getDisplayModel()
-            cdm.id = collection.id
+            //TODO is _id_ required in both CollectionDM and CollectionLayout?
+            val id = collection.id
+            getDisplayModel().id = id
+            getLayout().id = id
             // add displayModel to parent.displayModel
-            val parentDM = parent!!.getDisplayModel()
-            parentDM.collectionModelList.add(cdm)
+            val objectDM = parent!!.getDisplayModel()
+            objectDM.addCollectionModel(getDisplayModel())
         }
         collection.links.forEach {
             if (it.relation() == Relation.DESCRIBED_BY) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
index 2f7aa90034..a1c236b0ac 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionDM.kt
@@ -33,7 +33,11 @@ class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     private var rawData = observableListOf<TransferObject>()
 
     override fun readyToRender(): Boolean {
-        return (layout as CollectionLayout).readyToRender()
+        return getLayout().readyToRender()
+    }
+
+    fun getLayout(): CollectionLayout {
+        return layout as CollectionLayout
     }
 
     override fun addData(obj: TransferObject, aggregator: AggregatorWithLayout?, referrer: String?) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
index 2f69d7148e..dba84dd14b 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/CollectionLayout.kt
@@ -32,19 +32,12 @@ import org.apache.causeway.client.kroviz.to.TObject
  * - hidden :       will the column be displayed or not
  */
 class CollectionLayout : BaseLayout() {
+    var id = ""
     private var numberOfColumns = 0
-    private val propertySpecificationList = mutableListOf<PropertySpecification>()
+    val propertySpecificationList = mutableListOf<PropertySpecification>()
 
     override fun readyToRender(): Boolean {
-        console.log("[CL_readyToRender]")
-        console.log(propertySpecificationList.size)
-        val isReady = isInitialized() && allPropertySpecificationsAreCreated()
-        if (isReady) {
-            propertySpecificationList.forEach {
-                console.log(it)
-            }
-        }
-        return isReady
+        return isInitialized() && allPropertySpecificationsAreCreated()
     }
 
     /**
@@ -68,7 +61,7 @@ class CollectionLayout : BaseLayout() {
     }
 
     private fun allPropertySpecificationsAreCreated(): Boolean {
-        return (numberOfColumns == propertySpecificationList.size)
+        return numberOfColumns == propertySpecificationList.size
     }
 
     override fun addObjectProperty(
@@ -98,8 +91,4 @@ class CollectionLayout : BaseLayout() {
         ps.amendWith(propertyDescription)
     }
 
-    fun getColumnDescriptions(): List<PropertySpecification> {
-        return propertySpecificationList
-    }
-
 }
\ No newline at end of file
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
index b0bfb49362..e8866bddad 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectDM.kt
@@ -39,20 +39,33 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
         dirty = value
     }
 
+    fun addCollectionModel(collectionModel: CollectionDM) {
+        val id = collectionModel.id
+        val foundModel = collectionModelList.firstOrNull() {
+            it.id == id
+        }
+        if (foundModel == null) {
+            collectionModelList.add(collectionModel)
+        }
+    }
+
     override fun addLayout(lt: Layout) {
         TODO("Not yet implemented")
     }
 
     fun getCollectionDisplayModelFor(id: String): CollectionDM {
+        console.log("[ODM_getCollectionDisplayModelFor]")
+        console.log(id)
+        console.log(collectionModelList)
         return collectionModelList.find { it.id == id }!!
     }
 
     override fun readyToRender(): Boolean {
-        console.log("[ODM_readyToRender]")
         return when {
             data == null -> false
             isRendered -> false
             layout == null -> false
+            collectionModelList.size == 0 -> false
             else -> layout!!.readyToRender() //collectionsReadyToRender()
         }
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
index f2e85ee268..d5023d6cd3 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/ObjectLayout.kt
@@ -32,17 +32,14 @@ import org.apache.causeway.client.kroviz.to.bs.RowBs
 class ObjectLayout : BaseLayout() {
 
     var grid: GridBs? = null
-    private val collectionLayoutMap = mutableMapOf<String, CollectionLayout>()
+    private val collectionLayoutList = mutableListOf< CollectionLayout>()
 
     override fun readyToRender(): Boolean {
-        console.log("[OL_readyToRender]")
-//        val o = js(arrayOf(collectionLayoutMap.values))
-        console.log(collectionLayoutMap.keys)
-        var answer = when (grid) {
+        return when (grid) {
             null -> false
             else -> {
                 var answer = true
-                collectionLayoutMap.values.forEach {
+                collectionLayoutList.forEach {
                     if (!it.readyToRender()) {
                         answer = false
                     }
@@ -50,7 +47,6 @@ class ObjectLayout : BaseLayout() {
                 answer
             }
         }
-        return answer
     }
 
     override fun addObjectProperty(
@@ -58,7 +54,7 @@ class ObjectLayout : BaseLayout() {
         aggregator: AggregatorWithLayout,
         referrer: String
     ) {
-        console.log("[OL_addObjectProperty]")
+ //       console.log("[OL_addObjectProperty]")
 //        TODO("Not yet implemented")
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
index 539d8fd979..1ae19ea398 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/core/model/PropertySpecification.kt
@@ -41,6 +41,10 @@ class PropertySpecification(member: Member) {
         id = member.id
         name = member.id // can be changed later via property-description
         hidden = false // can be changed later via ...
+        //FIXME
+        if (name == "sources" || name == "description" || name == "logicalTypeName") {
+            hidden = true
+        }
         disabled = member.disabledReason.isNotEmpty()
     }
 
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
index 6db3b9f247..95bd7caa9c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/builder/ColBuilder.kt
@@ -69,6 +69,8 @@ class ColBuilder : UiBuilder() {
             val id = it.id
             val objectDM = dsp.displayModel
             val cdm = objectDM.getCollectionDisplayModelFor(id)
+            console.log("[CB_create]")
+            console.log(cdm)
             val tblCpt = RoTable(cdm)
             val fsPanel = FieldsetPanel(legend = StringUtils.capitalize(cdm.title)).add(tblCpt)
             panel.add(fsPanel)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
index 398d1bb8a8..c63b941b53 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ColumnFactory.kt
@@ -42,11 +42,11 @@ class ColumnFactory {
     }
 
     fun buildColumns(displayCollection: CollectionDM): List<ColumnDefinition<dynamic>> {
-        console.log("[CF_buildColumns]")
         val columns = mutableListOf<ColumnDefinition<Exposer>>()
         addColumnForObjectIcon(displayCollection, columns)
         addColumnsForProperties(displayCollection, columns)
         columns.add(columnForObjectMenu())
+        console.log("[CF_buildColumns]")
         console.log(columns)
         return columns
     }
@@ -103,18 +103,23 @@ class ColumnFactory {
     }
 
     private fun addColumnsForProperties(
-        displayCollection: CollectionDM,
+        collectionModel: CollectionDM,
         columns: MutableList<ColumnDefinition<Exposer>>,
     ) {
-        val cl = displayCollection.layout as CollectionLayout
-        val colDescList = cl.getColumnDescriptions()
-        for (cd in colDescList) {
-            if (!cd.hidden) {
+        console.log("[CF_addColumnsForProperties]")
+        val clo = collectionModel.getLayout()
+        val propSpecList = clo.propertySpecificationList
+        if (propSpecList.size == 0) {
+            throw IllegalStateException()
+        }
+        propSpecList.forEach {
+            console.log(it)
+            if (!it.hidden) {
                 var colDef = ColumnDefinition<dynamic>(
-                    title = cd.name,
-                    field = cd.id,
+                    title = it.name,
+                    field = it.id,
                     headerFilter = Editor.INPUT)
-                if (cd.id == "object") {
+                if (it.id == "object") {
                     colDef = buildLink()
                 }
                 columns.add(colDef)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
index 457fe0ae00..64a74f3c52 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/causeway/client/kroviz/ui/core/ViewManager.kt
@@ -239,7 +239,7 @@ object ViewManager {
         return SessionManager.getEventStore()
     }
 
-    fun countDialogs(): Int {
+    private fun countDialogs(): Int {
         return popups.size + 1
     }