You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by jo...@apache.org on 2021/05/21 14:11:32 UTC

[isis] 04/04: ISIS-2505 ListDM/Aggregator renamed to Collection*, ObjectAggregator can have multiple CollectionAggregators (for parented collections), demo.JavaLangStringJdo entities not shown yet

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

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

commit afdc35358e878eb5605d5a41eba88b06a8e8dd90
Author: Jörg Rade <jo...@kuehne-nagel.com>
AuthorDate: Fri May 21 16:09:53 2021 +0200

    ISIS-2505 ListDM/Aggregator renamed to Collection*, ObjectAggregator can have multiple CollectionAggregators (for parented collections), demo.JavaLangStringJdo entities not shown yet
---
 .../kroviz/partials/design/seq-aggregator.adoc     |   6 +-
 .../kroviz/partials/design/uml-aggregator.adoc     |   8 +-
 .../kroviz/partials/design/uml-overview.adoc       |   6 +-
 .../{ListAggregator.kt => CollectionAggregator.kt} |  41 ++-
 .../kroviz/core/aggregator/ObjectAggregator.kt     |  41 ++-
 .../core/model/{ListDM.kt => CollectionDM.kt}      |  15 +-
 .../isis/client/kroviz/core/model/ObjectDM.kt      |   4 -
 .../isis/client/kroviz/handler/BaseHandler.kt      |   2 +-
 .../client/kroviz/handler/ResultListHandler.kt     |   6 +-
 .../isis/client/kroviz/to/PlainTransferObjects.kt  |   2 +-
 .../client/kroviz/ui/builder/FieldSetBuilder.kt    |  12 +-
 .../isis/client/kroviz/ui/core/ColumnFactory.kt    |   8 +-
 .../apache/isis/client/kroviz/ui/core/RoDisplay.kt |  11 +-
 .../apache/isis/client/kroviz/ui/core/RoTable.kt   |  10 +-
 .../apache/isis/client/kroviz/ui/core/UiManager.kt |   4 +-
 ...gregatorTest.kt => CollectionAggregatorTest.kt} |  14 +-
 .../client/kroviz/core/event/EventStoreTest.kt     |   4 +-
 .../{DisplayListTest.kt => CollectionDMTest.kt}    |   8 +-
 .../isis/client/kroviz/core/model/ExposerTest.kt   |  14 +
 .../snapshots/demo2_0_0/JAVA_LANG_STRING_JDO.kt    | 393 +++++++++++++++++++++
 20 files changed, 525 insertions(+), 84 deletions(-)

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 b067414..022f57f 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
@@ -1,6 +1,6 @@
 :Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or ag [...]
 
-.ListAggregator Sequence Diagram
+.CollectionAggregator Sequence Diagram
 [plantuml,file="seq-aggregator.png"]
 ----
 @startuml
@@ -11,8 +11,8 @@ participant "<<description>>\nLink" as LNK #LightBlue
 participant "(Xml)HttpRequest" as XHR
 participant "<<ChainOfResponsibility>>\nResponseHandler" as RH
 participant "<<description>>\n<<EventStore>>\nLogEntry" as LE #LightBlue
-participant "<<moment-interval>>\nListAggregator" as AGGT  #Pink
-participant "<<thing>>\n<<DisplayModel>>\nListDM" as DM #LightGreen
+participant "<<moment-interval>>\nCollectionAggregator" as AGGT  #Pink
+participant "<<thing>>\n<<DisplayModel>>\nCollectionDM" as DM #LightGreen
 participant "<<description>>\nTransferObject" as TO #LightBlue
 
 User -> UI : listAll()
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-aggregator.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-aggregator.adoc
index 08c3f2d..bc4091f 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-aggregator.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-aggregator.adoc
@@ -40,7 +40,7 @@ abstract class BaseAggregator {
 }
 
 IAggregator <|.. BaseAggregator
-BaseAggregator <|-- ListAggregator
+BaseAggregator <|-- CollectionAggregator
 BaseAggregator <|-- ObjectAggregator
 BaseAggregator --> BaseDisplayable : data
 
@@ -51,15 +51,15 @@ abstract class BaseDisplayable {
     +title()
 }
 
-class ListDM {
+class CollectionDM {
     list:List<Exposer>
 }
 
 BaseDisplayable -> Layout
-BaseDisplayable <|-- ListDM
+BaseDisplayable <|-- CollectionDM
 BaseDisplayable <|-- ObjectDM
 
-ObjectDM o-- ListDM
+ObjectDM o-- CollectionDM
 
 @enduml
 ----
diff --git a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-overview.adoc b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-overview.adoc
index 01b523f..2d41f70 100644
--- a/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-overview.adoc
+++ b/incubator/clients/kroviz/adoc/modules/kroviz/partials/design/uml-overview.adoc
@@ -82,11 +82,11 @@ to.Service o-- to.Member
 interface Aggregator {
     update(logEntry)
 }
-class ListAggregator {
+class CollectionAggregator {
     -list:ObjectList
 }
-ListAggregator *-- ObjectList
-Aggregator <|.. ListAggregator
+CollectionAggregator *-- ObjectList
+Aggregator <|.. CollectionAggregator
 
 class NavigationAggregator
 Aggregator <|.. NavigationAggregator
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
similarity index 70%
rename from incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregator.kt
rename to incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
index e7c9363..e1ac64f 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregator.kt
@@ -20,7 +20,8 @@ package org.apache.isis.client.kroviz.core.aggregator
 
 import org.apache.isis.client.kroviz.core.event.EventState
 import org.apache.isis.client.kroviz.core.event.LogEntry
-import org.apache.isis.client.kroviz.core.model.ListDM
+import org.apache.isis.client.kroviz.core.event.RoXmlHttpRequest
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import org.apache.isis.client.kroviz.layout.Layout
 import org.apache.isis.client.kroviz.to.*
 import org.apache.isis.client.kroviz.to.bs3.Grid
@@ -33,29 +34,35 @@ import org.apache.isis.client.kroviz.ui.core.UiManager
  * (3) FR_OBJECT_PROPERTY       PropertyHandler -> invoke()
  * (4) FR_PROPERTY_DESCRIPTION  <PropertyDescriptionHandler>
  */
-class ListAggregator(actionTitle: String) : AggregatorWithLayout() {
+class CollectionAggregator(actionTitle: String, val parent: ObjectAggregator? = null) : AggregatorWithLayout() {
 
     init {
-        dpm = ListDM(actionTitle)
+        dpm = CollectionDM(actionTitle)
     }
 
     override fun update(logEntry: LogEntry, subType: String) {
 
         if (logEntry.state == EventState.DUPLICATE) {
-            console.log("[ListAggregator.update] TODO duplicates should not be propagated to handlers")
+            console.log("[CollectionAggregator.update] TODO duplicates should not be propagated to handlers")
         } else {
             when (val obj = logEntry.getTransferObject()) {
                 null -> log(logEntry)
                 is ResultList -> handleList(obj)
                 is TObject -> handleObject(obj)
-                is Layout -> handleLayout(obj, dpm as ListDM)
+                is Layout -> handleLayout(obj, dpm as CollectionDM)
                 is Grid -> handleGrid(obj)
                 is Property -> handleProperty(obj)
+                is Collection -> handleCollection(obj)
                 else -> log(logEntry)
             }
 
-            if (dpm.canBeDisplayed()) {
-                UiManager.openListView(this)
+            if (parent == null) {
+                if (dpm.canBeDisplayed()) {
+                    UiManager.openListView(this)
+                }
+            } else {
+                console.log("[CA.opdate] can be displayed / parent = OA")
+                parent.update(logEntry, subType)
             }
         }
     }
@@ -70,17 +77,20 @@ class ListAggregator(actionTitle: String) : AggregatorWithLayout() {
     }
 
     private fun handleObject(obj: TObject) {
+        console.log("[CA.handleObject]")
+        console.log(obj)
         dpm.addData(obj)
         invokeLayoutLink(obj)
+//TODO        invokeIconLink(obj)
     }
 
 
     private fun handleGrid(grid: Grid) {
-        (dpm as ListDM).grid = grid
+        (dpm as CollectionDM).grid = grid
     }
 
     private fun handleProperty(p: Property) {
-        val dm = dpm as ListDM
+        val dm = dpm as CollectionDM
         if (p.isPropertyDescription()) {
             dm.addPropertyDescription(p)
         } else {
@@ -89,7 +99,14 @@ class ListAggregator(actionTitle: String) : AggregatorWithLayout() {
         }
     }
 
-    override fun reset(): ListAggregator {
+    private fun handleCollection(collection: Collection) {
+        collection.value.forEach {
+            console.log(it)
+            RoXmlHttpRequest().invoke(it, this)
+        }
+    }
+
+    override fun reset(): CollectionAggregator {
         dpm.reset()
         return this
     }
@@ -101,8 +118,8 @@ class ListAggregator(actionTitle: String) : AggregatorWithLayout() {
     }
 
     private fun Property.isPropertyDescription(): Boolean {
-        val selfLink = this.links.find { l ->
-            l.relation() == Relation.SELF
+        val selfLink = this.links.find {
+            it.relation() == Relation.SELF
         }
         return selfLink!!.representation() == Represention.PROPERTY_DESCRIPTION
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ObjectAggregator.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ObjectAggregator.kt
index 0143747..19e02b4 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ObjectAggregator.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/aggregator/ObjectAggregator.kt
@@ -19,12 +19,14 @@
 package org.apache.isis.client.kroviz.core.aggregator
 
 import org.apache.isis.client.kroviz.core.event.LogEntry
+import org.apache.isis.client.kroviz.core.event.RoXmlHttpRequest
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import org.apache.isis.client.kroviz.core.model.ObjectDM
 import org.apache.isis.client.kroviz.layout.Layout
 import org.apache.isis.client.kroviz.to.*
 import org.apache.isis.client.kroviz.to.bs3.Grid
-import org.apache.isis.client.kroviz.ui.dialog.ErrorDialog
 import org.apache.isis.client.kroviz.ui.core.UiManager
+import org.apache.isis.client.kroviz.ui.dialog.ErrorDialog
 
 /** sequence of operations:
  * (0) Menu Action              User clicks BasicTypes.String -> handled by ActionDispatcher
@@ -34,37 +36,47 @@ import org.apache.isis.client.kroviz.ui.core.UiManager
  * (4) ???_PROPERTY_DESCRIPTION  <PropertyDescriptionHandler>
  */
 class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
+    var collectionMap = mutableMapOf<String, CollectionAggregator>()
 
     init {
         dpm = ObjectDM(actionTitle)
     }
 
     override fun update(logEntry: LogEntry, subType: String) {
-        val obj = logEntry.getTransferObject()
-        when (obj) {
+        when (val obj = logEntry.getTransferObject()) {
             is TObject -> handleObject(obj)
             is ResultObject -> handleResultObject(obj)
             is Property -> handleProperty(obj)
-            is Collection -> handleCollection(obj)
             is Layout -> handleLayout(obj, dpm as ObjectDM)
             is Grid -> handleGrid(obj)
             is HttpError -> ErrorDialog(logEntry).open()
             else -> log(logEntry)
         }
 
-        if (dpm.canBeDisplayed()) {
+        if (dpm.canBeDisplayed() && collectionsCanBeDisplayed()) {
             UiManager.openObjectView(this)
         }
     }
 
+    private fun collectionsCanBeDisplayed(): Boolean {
+        if (collectionMap.isEmpty()) return true
+        return collectionMap.all {
+            val cdm = it.value.dpm as CollectionDM
+            cdm.parentedCollectionCanBeDisplayed()
+        }
+    }
+
     fun handleObject(obj: TObject) {
         // After ~/action/invoke is called, the actual object instance (containing properties) needs to be invoked as well.
-        // Note that rel.self/href is identical in both cases and both are of type TObject. logEntry.url is different, though.
+        // 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)
         } else {
             dpm.addData(obj)
         }
+        if (collectionMap.size == 0) {
+            handleCollections(obj)
+        }
         invokeLayoutLink(obj)
     }
 
@@ -79,15 +91,22 @@ class ObjectAggregator(val actionTitle: String) : AggregatorWithLayout() {
         (dpm as ObjectDM).addResult(resultObject)
     }
 
-    fun handleCollection(obj: Collection) {
-        console.log(obj)
-        throw Throwable("[ObjectAggregator.handleCollection] not implemented yet")
-    }
-
     override fun getObject(): TObject? {
         return dpm.getObject()
     }
 
+    private fun handleCollections(obj: TObject) {
+        console.log("[OA.handleCollections]")
+        obj.getCollections().forEach {
+            val key = it.id
+            val aggregator = CollectionAggregator(key, this)
+            collectionMap.put(key, aggregator)
+            console.log(key)
+            val link = it.links.first()
+            RoXmlHttpRequest().invoke(link, aggregator)
+        }
+    }
+
     private fun handleProperty(property: Property) {
         console.log(property)
         throw Throwable("[ObjectAggregator.handleProperty] not implemented yet")
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ListDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
similarity index 73%
rename from incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ListDM.kt
rename to incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
index f7e4eee..7cddbed 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ListDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDM.kt
@@ -18,11 +18,11 @@
  */
 package org.apache.isis.client.kroviz.core.model
 
+import io.kvision.state.observableListOf
 import org.apache.isis.client.kroviz.to.TObject
 import org.apache.isis.client.kroviz.to.TransferObject
-import io.kvision.state.observableListOf
 
-class ListDM(override val title: String) : DisplayModelWithLayout() {
+class CollectionDM(override val title: String) : DisplayModelWithLayout() {
     var data = observableListOf<Exposer>()
     private var rawData = observableListOf<TransferObject>()
 
@@ -30,7 +30,7 @@ class ListDM(override val title: String) : DisplayModelWithLayout() {
         if (!rawData.contains(obj)) {
             rawData.add(obj)
             val exo = Exposer(obj as TObject)
-            data.add(exo)  //if exposer is not dynamised, data access in tables won't work   .dynamise()
+            data.add(exo.dynamise())  //if exposer is not dynamised, data access in tables won't work
         }
     }
 
@@ -40,4 +40,13 @@ class ListDM(override val title: String) : DisplayModelWithLayout() {
         rawData = observableListOf()
     }
 
+    // canBeDisplayed checks for grid AND layout - for parented collection there seems to be no layout
+    fun parentedCollectionCanBeDisplayed(): Boolean {
+        console.log("[CDM.parentedCollectionCanBeDisplayed]")
+        console.log(this)
+        val answer = grid != null
+        console.log(answer)
+        return answer
+    }
+
 }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ObjectDM.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ObjectDM.kt
index b4a97a6..5774cef 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ObjectDM.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/core/model/ObjectDM.kt
@@ -47,10 +47,6 @@ class ObjectDM(override val title: String) : DisplayModelWithLayout() {
             val p = createPropertyFrom(m)
             addProperty(p)
         }
-        obj.getCollections().forEach { m ->
-            console.log("[ODM.addData] collection member")
-            console.log(m)
-        }
     }
 
     fun addResult(resultObject: ResultObject) {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
index 38c1a40..dbad1dc 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/BaseHandler.kt
@@ -30,7 +30,7 @@ import org.apache.isis.client.kroviz.ui.core.Constants
  *
  * Implementing classes are responsible for:
  * @item creating Objects by parsing responses (JSON/XML),
- * @item creating/finding Aggregators (eg. ListAggregator, ObjectAggregator), and
+ * @item creating/finding Aggregators (eg. CollectionAggregator, ObjectAggregator), and
  * @item setting Objects and Aggregators into LogEntry.
  */
 abstract class BaseHandler {
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResultListHandler.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResultListHandler.kt
index 592ebf7..6da7d52 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResultListHandler.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/handler/ResultListHandler.kt
@@ -19,18 +19,18 @@
 package org.apache.isis.client.kroviz.handler
 
 import kotlinx.serialization.json.Json
-import org.apache.isis.client.kroviz.core.aggregator.ListAggregator
+import org.apache.isis.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.isis.client.kroviz.to.ResultList
 import org.apache.isis.client.kroviz.to.TransferObject
 
 class ResultListHandler : BaseHandler() {
 
     override fun doHandle() {
-        logEntry.addAggregator(ListAggregator(logEntry.title))
+        logEntry.addAggregator(CollectionAggregator(logEntry.title))
         update()
     }
 
-    
+
     override fun parse(response: String): TransferObject {
         return Json.decodeFromString(ResultList.serializer(), response)
     }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/PlainTransferObjects.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/PlainTransferObjects.kt
index a0b62c8..353cb8c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/PlainTransferObjects.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/to/PlainTransferObjects.kt
@@ -32,7 +32,7 @@ enum class ActionSemantics(val type: String) {
 data class DomainType(
         override val links: List<Link>,
         val canonicalName: String,
-        val members: List<Link>,
+        val members: List<Link>,   // change to Map<String, Member>, once https://issues.apache.org/jira/browse/ISIS-2684 is fixed
         val typeActions: List<Link>,
         val extensions: Extensions
 ) : TransferObject, HasLinks
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/FieldSetBuilder.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/FieldSetBuilder.kt
index f3e1601..110f8ff 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/FieldSetBuilder.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/builder/FieldSetBuilder.kt
@@ -18,13 +18,13 @@
  */
 package org.apache.isis.client.kroviz.ui.builder
 
+import io.kvision.form.FormPanel
 import org.apache.isis.client.kroviz.to.TObject
 import org.apache.isis.client.kroviz.to.TypeMapper
 import org.apache.isis.client.kroviz.to.bs3.FieldSet
 import org.apache.isis.client.kroviz.ui.core.FormItem
 import org.apache.isis.client.kroviz.ui.core.FormPanelFactory
 import org.apache.isis.client.kroviz.ui.core.RoDisplay
-import io.kvision.form.FormPanel
 
 class FieldSetBuilder {
 
@@ -34,21 +34,17 @@ class FieldSetBuilder {
             tab: RoDisplay
     ): FormPanel<String>? {
 
-        console.log("[FSB.init]")
         val members = tObject.getProperties()
         val items = mutableListOf<FormItem>()
-        console.log("Layout-Properties: " + fieldSetLayout.propertyList.size)
 
         for (p in fieldSetLayout.propertyList) {
             val label = p.id
-
             val member = members.firstOrNull() { it.id == label }
-
             if (member != null) {
                 val memberType = TypeMapper().forType(member.type!!)
-
+                console.log("[FSB.init]")
+                console.log(memberType)
                 val size = maxOf(1, p.multiLine)
-
                 val fi = FormItem(
                         label = label,
                         type = memberType,
@@ -57,8 +53,6 @@ class FieldSetBuilder {
                         description = p.describedAs,
                         member = member,
                         dspl = tab)
-                console.log(fi)
-
                 items.add(fi)
             }
         }
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
index 3cce9e9..8207d58 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/ColumnFactory.kt
@@ -20,7 +20,7 @@ package org.apache.isis.client.kroviz.ui.core
 
 import org.apache.isis.client.kroviz.core.event.EventStore
 import org.apache.isis.client.kroviz.core.model.Exposer
-import org.apache.isis.client.kroviz.core.model.ListDM
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import io.kvision.html.Button
 import io.kvision.html.ButtonStyle
 import io.kvision.tabulator.Align
@@ -50,7 +50,7 @@ class ColumnFactory {
     }
 
     fun buildColumns(
-            displayList: ListDM,
+            displayCollection: CollectionDM,
             withCheckBox: Boolean = false): List<ColumnDefinition<dynamic>> {
 
         val columns = mutableListOf<ColumnDefinition<dynamic>>()
@@ -62,13 +62,13 @@ class ColumnFactory {
         val menu = buildMenu()
         columns.add(menu)
 
-        val model = displayList.data as List<dynamic>
+        val model = displayCollection.data as List<dynamic>
         if (model[0].hasOwnProperty("iconName") as Boolean) {
             val icon = buildLinkIcon()
             columns.add(icon)
         }
 
-        val propertyLabels = displayList.propertyDescriptionList
+        val propertyLabels = displayCollection.propertyDescriptionList
         for (pl in propertyLabels) {
             val id = pl.key
             val friendlyName = pl.value
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoDisplay.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoDisplay.kt
index 0774216..6b4f5b2 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoDisplay.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoDisplay.kt
@@ -18,15 +18,15 @@
  */
 package org.apache.isis.client.kroviz.ui.core
 
-import org.apache.isis.client.kroviz.core.model.ObjectDM
-import org.apache.isis.client.kroviz.to.TObject
-import org.apache.isis.client.kroviz.ui.builder.LayoutBuilder
 import io.kvision.core.CssSize
 import io.kvision.core.FontStyle
 import io.kvision.core.FontWeight
 import io.kvision.core.UNIT
 import io.kvision.dropdown.DropDown
 import io.kvision.panel.VPanel
+import org.apache.isis.client.kroviz.core.model.ObjectDM
+import org.apache.isis.client.kroviz.to.TObject
+import org.apache.isis.client.kroviz.ui.builder.LayoutBuilder
 
 class RoDisplay(val displayModel: ObjectDM) : Displayable, VPanel() {
 
@@ -34,12 +34,11 @@ class RoDisplay(val displayModel: ObjectDM) : Displayable, VPanel() {
     private var objectPanel: VPanel
 
     init {
+        console.log("[RD.init] tObject / grid")
+        console.log(displayModel)
         val model = displayModel.data!!
         val tObject: TObject = model.delegate
         val grid = displayModel.grid!!
-        console.log("[RD.init] tObject / grid")
-        console.log(tObject)
-        console.log(grid)
         objectPanel = LayoutBuilder().create(grid, tObject, this)
         objectPanel.width = CssSize(100, UNIT.perc)
         add(objectPanel)
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoTable.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoTable.kt
index c28c64d..9b0b750 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoTable.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/RoTable.kt
@@ -19,7 +19,7 @@
 package org.apache.isis.client.kroviz.ui.core
 
 import org.apache.isis.client.kroviz.core.model.Exposer
-import org.apache.isis.client.kroviz.core.model.ListDM
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import org.apache.isis.client.kroviz.utils.Utils
 import io.kvision.core.Container
 import io.kvision.core.CssSize
@@ -37,14 +37,14 @@ import io.kvision.utils.set
  * - attribute types (can only be determined at runtime) and
  * - accessor names
  */
-class RoTable(displayList: ListDM) : SimplePanel() {
+class RoTable(displayCollection: CollectionDM) : SimplePanel() {
 
     init {
-        title = Utils.extractTitle(displayList.title)
+        title = Utils.extractTitle(displayCollection.title)
         width = CssSize(100, UNIT.perc)
-        val model = displayList.data
+        val model = displayCollection.data
         val columns = ColumnFactory().buildColumns(
-                displayList,
+                displayCollection,
                 true)
         val options = TabulatorOptions(
                 movableColumns = true,
diff --git a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
index 4585a77..b8bef6c 100644
--- a/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
+++ b/incubator/clients/kroviz/src/main/kotlin/org/apache/isis/client/kroviz/ui/core/UiManager.kt
@@ -30,7 +30,7 @@ import org.apache.isis.client.kroviz.core.aggregator.UndefinedDispatcher
 import org.apache.isis.client.kroviz.core.event.EventStore
 import org.apache.isis.client.kroviz.core.event.LogEntry
 import org.apache.isis.client.kroviz.core.event.ResourceSpecification
-import org.apache.isis.client.kroviz.core.model.ListDM
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import org.apache.isis.client.kroviz.core.model.ObjectDM
 import org.apache.isis.client.kroviz.to.Relation
 import org.apache.isis.client.kroviz.to.TObject
@@ -136,7 +136,7 @@ object UiManager {
     fun openListView(aggregator: BaseAggregator) {
         val displayable = aggregator.dpm
         val title: String = Utils.extractTitle(displayable.title)
-        val panel = RoTable(displayable as ListDM)
+        val panel = RoTable(displayable as CollectionDM)
         add(title, panel, aggregator)
         displayable.isRendered = true
     }
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregatorTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
similarity index 89%
rename from incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregatorTest.kt
rename to incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
index e4a317d..b451c2a 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/ListAggregatorTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/aggregator/CollectionAggregatorTest.kt
@@ -21,7 +21,7 @@ package org.apache.isis.client.kroviz.core.aggregator
 import org.apache.isis.client.kroviz.IntegrationTest
 import org.apache.isis.client.kroviz.core.event.EventStore
 import org.apache.isis.client.kroviz.core.event.ResourceSpecification
-import org.apache.isis.client.kroviz.core.model.ListDM
+import org.apache.isis.client.kroviz.core.model.CollectionDM
 import org.apache.isis.client.kroviz.snapshots.simpleapp1_16_0.*
 import org.apache.isis.client.kroviz.to.Property
 import org.apache.isis.client.kroviz.to.Relation
@@ -29,7 +29,7 @@ import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
 import kotlin.test.assertTrue
 
-class ListAggregatorTest : IntegrationTest() {
+class CollectionAggregatorTest : IntegrationTest() {
 
     //@Test
     // sometimes fails with:
@@ -38,7 +38,7 @@ class ListAggregatorTest : IntegrationTest() {
         if (isAppAvailable()) {
             // given
             EventStore.reset()
-            val obs = ListAggregator("test")
+            val obs = CollectionAggregator("test")
             // when
             mockResponse(FR_OBJECT, obs)
             mockResponse(FR_OBJECT_LAYOUT, obs)
@@ -49,7 +49,7 @@ class ListAggregatorTest : IntegrationTest() {
             val layoutLe = mockResponse(FR_OBJECT_LAYOUT, obs)
 
             // then
-            val actObs = pLe.getAggregator() as ListAggregator
+            val actObs = pLe.getAggregator() as CollectionAggregator
             assertEquals(obs, actObs)  // 1
             assertEquals(pdLe.getAggregator(), layoutLe.getAggregator()) // 2 - trivial?
             // seems they are equal but not identical - changes on obs are not reflected in actObs !!!
@@ -65,7 +65,7 @@ class ListAggregatorTest : IntegrationTest() {
             assertNotNull(descLink)  // 4
 
             // then
-            val dl = obs.dpm as ListDM
+            val dl = obs.dpm as CollectionDM
             val propertyLabels = dl.propertyDescriptionList
             val property = pdLe.getTransferObject() as Property
             assertTrue(propertyLabels.size > 0)  // 5
@@ -81,14 +81,14 @@ class ListAggregatorTest : IntegrationTest() {
         if (isAppAvailable()) {
             // given
             EventStore.reset()
-            val obs = ListAggregator("test")
+            val obs = CollectionAggregator("test")
             // when
             mockResponse(SO_LIST_ALL, obs)
             mockResponse(SO_0, obs)
             // then
             val ol = obs.dpm
             assertNotNull(ol)
-            assertEquals(1, (ol as ListDM).data.size)
+            assertEquals(1, (ol as CollectionDM).data.size)
         }
     }
 
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/event/EventStoreTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/event/EventStoreTest.kt
index ce5c914..92a01be 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/event/EventStoreTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/event/EventStoreTest.kt
@@ -19,7 +19,7 @@
 package org.apache.isis.client.kroviz.core.event
 
 import org.apache.isis.client.kroviz.IntegrationTest
-import org.apache.isis.client.kroviz.core.aggregator.ListAggregator
+import org.apache.isis.client.kroviz.core.aggregator.CollectionAggregator
 import org.apache.isis.client.kroviz.core.aggregator.ObjectAggregator
 import org.apache.isis.client.kroviz.snapshots.simpleapp1_16_0.*
 import org.apache.isis.client.kroviz.to.Method
@@ -37,7 +37,7 @@ class EventStoreTest : IntegrationTest() {
         if (isAppAvailable()) {
             // given
             EventStore.reset()
-            val obs = ListAggregator("test")
+            val obs = CollectionAggregator("test")
 
             //when
             val soList = ResourceSpecification(SO_LIST_ALL.url)
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/DisplayListTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDMTest.kt
similarity index 95%
rename from incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/DisplayListTest.kt
rename to incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDMTest.kt
index 9e7bc06..7dc6ac4 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/DisplayListTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/CollectionDMTest.kt
@@ -28,7 +28,7 @@ import kotlin.test.Test
 import kotlin.test.assertEquals
 import kotlin.test.assertNotNull
 
-class DisplayListTest {
+class CollectionDMTest {
 
     @Test
     fun testSimpleObject() {
@@ -36,7 +36,7 @@ class DisplayListTest {
         val ro1 = TObjectHandler().parse(SO_1.str) as TObject
         val lt = LayoutHandler().parse(SO_OBJECT_LAYOUT.str) as Layout
 
-        val dl = ListDM("test")
+        val dl = CollectionDM("test")
         dl.addData(ro0)
         dl.addData(ro1)
         dl.addLayout(lt)
@@ -55,7 +55,7 @@ class DisplayListTest {
         val lt = LayoutHandler().parse(CFG_LAYOUT_JSON.str) as Layout
         // val grd = LayoutXmlHandler().parse(CFG_LAYOUT_XML.str) as Grid
 
-        val dl = ListDM("test")
+        val dl = CollectionDM("test")
         dl.addData(ro0)
 
         dl.addLayout(lt)
@@ -71,7 +71,7 @@ class DisplayListTest {
         val ro0 = TObjectHandler().parse(FR_OBJECT.str) as TObject
         val lt = LayoutXmlHandler().parse(FR_OBJECT_LAYOUT.str) as Layout
 
-        val dl = ListDM("test")
+        val dl = CollectionDM("test")
         dl.addData(ro0)
 
         dl.addLayout(lt)
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/ExposerTest.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/ExposerTest.kt
index e121cfa..0be23c6 100644
--- a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/ExposerTest.kt
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/core/model/ExposerTest.kt
@@ -19,6 +19,7 @@
 package org.apache.isis.client.kroviz.core.model
 
 import org.apache.isis.client.kroviz.handler.TObjectHandler
+import org.apache.isis.client.kroviz.snapshots.demo2_0_0.JAVA_LANG_STRING_JDO
 import org.apache.isis.client.kroviz.snapshots.simpleapp1_16_0.CFG_1
 import org.apache.isis.client.kroviz.snapshots.simpleapp1_16_0.SO_0
 import org.apache.isis.client.kroviz.to.TObject
@@ -30,6 +31,19 @@ import kotlin.test.assertFalse
 class ExposerTest {
 
     @Test
+    fun testParseJavaLangStringJdo() {
+        //given
+        val jsonStr = JAVA_LANG_STRING_JDO.str
+        //when
+        val to = TObjectHandler().parse(jsonStr) as TObject
+        //then
+        assertEquals("StringJDO entity: Hello", to.title)
+        assertEquals("demo.JavaLangStringJdo", to.domainType)
+        assertEquals("1", to.instanceId)
+    }
+
+
+    @Test
     fun testConfiguration() {
         val jsonStr = CFG_1.str
         val to = TObjectHandler().parse(jsonStr) as TObject
diff --git a/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/JAVA_LANG_STRING_JDO.kt b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/JAVA_LANG_STRING_JDO.kt
new file mode 100644
index 0000000..37af2ea
--- /dev/null
+++ b/incubator/clients/kroviz/src/test/kotlin/org/apache/isis/client/kroviz/snapshots/demo2_0_0/JAVA_LANG_STRING_JDO.kt
@@ -0,0 +1,393 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.client.kroviz.snapshots.demo2_0_0
+
+import org.apache.isis.client.kroviz.snapshots.Response
+
+object JAVA_LANG_STRING_JDO : Response() {
+    override val url = "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1"
+    override val str = """
+        {
+  "links" : [ {
+    "rel" : "self",
+    "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1",
+    "method" : "GET",
+    "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object\"",
+    "title" : "StringJDO entity: Hello"
+  }, {
+    "rel" : "describedby",
+    "href" : "http://localhost:8080/restful/domain-types/demo.JavaLangStringJdo",
+    "method" : "GET",
+    "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/domain-type\""
+  }, {
+    "rel" : "urn:org.apache.isis.restfulobjects:rels/object-layout",
+    "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/object-layout",
+    "method" : "GET",
+    "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-layout-bs3\""
+  }, {
+    "rel" : "urn:org.apache.isis.restfulobjects:rels/object-icon",
+    "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/image",
+    "method" : "GET",
+    "type" : "image/png"
+  }, {
+    "rel" : "urn:org.restfulobjects:rels/update",
+    "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo:1",
+    "method" : "PUT",
+    "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object\"",
+    "arguments" : { }
+  } ],
+  "extensions" : {
+    "oid" : "demo.JavaLangStringJdo:1",
+    "isService" : false,
+    "isPersistent" : true
+  },
+  "title" : "StringJDO entity: Hello",
+  "domainType" : "demo.JavaLangStringJdo",
+  "instanceId" : "1",
+  "members" : {
+    "mixinProperty" : {
+      "id" : "mixinProperty",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"mixinProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/mixinProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Contributed property"
+    },
+    "description" : {
+      "id" : "description",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"description\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/description",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "<div class=\"paragraph\">\n<p>JDO supports <code>String</code> <a href=\"http://www.datanucleus.org:15080/products/accessplatform_5_2/jdo/mapping.html#_primitive_and_java_lang_types\">out-of-the-box</a>, so no special annotations are required.</p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-java\" data-lang=\"java\">@PersistenceCapable(identityType = IdentityType.DATASTORE, schema = \"demo\")\n@Datastore [...]
+      "format" : "string",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Contributed property"
+    },
+    "readWriteProperty" : {
+      "id" : "readWriteProperty",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readWriteProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readWriteProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      }
+    },
+    "readOnlyPropertyDerivedLabelPositionLeft" : {
+      "id" : "readOnlyPropertyDerivedLabelPositionLeft",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyPropertyDerivedLabelPositionLeft\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyPropertyDerivedLabelPositionLeft",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Always disabled"
+    },
+    "readOnlyPropertyDerivedLabelPositionTop" : {
+      "id" : "readOnlyPropertyDerivedLabelPositionTop",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyPropertyDerivedLabelPositionTop\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyPropertyDerivedLabelPositionTop",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Always disabled"
+    },
+    "readOnlyPropertyDerivedLabelPositionRight" : {
+      "id" : "readOnlyPropertyDerivedLabelPositionRight",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyPropertyDerivedLabelPositionRight\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyPropertyDerivedLabelPositionRight",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Always disabled"
+    },
+    "readOnlyPropertyDerivedLabelPositionNone" : {
+      "id" : "readOnlyPropertyDerivedLabelPositionNone",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyPropertyDerivedLabelPositionNone\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyPropertyDerivedLabelPositionNone",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Always disabled"
+    },
+    "objectType" : {
+      "id" : "objectType",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"objectType\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/objectType",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "demo.JavaLangStringJdo",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Contributed property"
+    },
+    "objectIdentifier" : {
+      "id" : "objectIdentifier",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"objectIdentifier\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/objectIdentifier",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "1",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Contributed property"
+    },
+    "readOnlyOptionalProperty" : {
+      "id" : "readOnlyOptionalProperty",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyOptionalProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyOptionalProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : null,
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Disabled"
+    },
+    "readWriteOptionalProperty" : {
+      "id" : "readWriteOptionalProperty",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readWriteOptionalProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readWriteOptionalProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : null,
+      "extensions" : {
+        "x-isis-format" : "string"
+      }
+    },
+    "readOnlyProperty" : {
+      "id" : "readOnlyProperty",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"readOnlyProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/readOnlyProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "Hello",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Disabled"
+    },
+    "sources" : {
+      "id" : "sources",
+      "memberType" : "property",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;property=\"sources\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/properties/sources",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-property\""
+      } ],
+      "value" : "<div class=\"paragraph\">\n<p><a href=\"https://github.com/apache/isis/tree/master/examples/demo/domain/src/main/java/demoapp/dom/types/javalang/strings/jdo\">Sources</a> for this demo</p>\n</div>",
+      "format" : "string",
+      "extensions" : {
+        "x-isis-format" : "string"
+      },
+      "disabledReason" : "Contributed property"
+    },
+    "updateReadOnlyOptionalProperty" : {
+      "id" : "updateReadOnlyOptionalProperty",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"updateReadOnlyOptionalProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/updateReadOnlyOptionalProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "updateReadOnlyProperty" : {
+      "id" : "updateReadOnlyProperty",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"updateReadOnlyProperty\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/updateReadOnlyProperty",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "updateReadOnlyPropertyWithChoices" : {
+      "id" : "updateReadOnlyPropertyWithChoices",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"updateReadOnlyPropertyWithChoices\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/updateReadOnlyPropertyWithChoices",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "actionReturning" : {
+      "id" : "actionReturning",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"actionReturning\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/actionReturning",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "actionReturningCollection" : {
+      "id" : "actionReturningCollection",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"actionReturningCollection\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/actionReturningCollection",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "clearHints" : {
+      "id" : "clearHints",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"clearHints\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/clearHints",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "recentCommands" : {
+      "id" : "recentCommands",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"recentCommands\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/recentCommands",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "downloadLayoutXml" : {
+      "id" : "downloadLayoutXml",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"downloadLayoutXml\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/downloadLayoutXml",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "downloadJdoMetadata" : {
+      "id" : "downloadJdoMetadata",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"downloadJdoMetadata\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/downloadJdoMetadata",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "inspectMetamodel" : {
+      "id" : "inspectMetamodel",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"inspectMetamodel\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/inspectMetamodel",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "downloadMetamodelXml" : {
+      "id" : "downloadMetamodelXml",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"downloadMetamodelXml\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/downloadMetamodelXml",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "openRestApi" : {
+      "id" : "openRestApi",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"openRestApi\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/openRestApi",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    },
+    "rebuildMetamodel" : {
+      "id" : "rebuildMetamodel",
+      "memberType" : "action",
+      "links" : [ {
+        "rel" : "urn:org.restfulobjects:rels/details;action=\"rebuildMetamodel\"",
+        "href" : "http://localhost:8080/restful/objects/demo.JavaLangStringJdo/1/actions/rebuildMetamodel",
+        "method" : "GET",
+        "type" : "application/json;profile=\"urn:org.restfulobjects:repr-types/object-action\""
+      } ]
+    }
+  }
+}
+"""
+}
+