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

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


The following commit(s) were added to refs/heads/master by this push:
     new 18b06c3c5d ISIS-2297: adds simple CSV MM export option
18b06c3c5d is described below

commit 18b06c3c5d046a094d0040497fde2650150daa04
Author: Andi Huber <[email protected]>
AuthorDate: Mon Dec 5 15:02:07 2022 +0100

    ISIS-2297: adds simple CSV MM export option
---
 .../services/metamodel/MetaModelServiceMenu.java   |  99 +++++++++---------
 .../applib/services/metamodel/_CsvExport2.java     | 115 +++++++++++++++++++++
 .../src/main/java/demoapp/dom/menubars.layout.xml  |   3 +-
 .../domainmodel/MetaModelRegressionTest.java       |   6 +-
 4 files changed, 171 insertions(+), 52 deletions(-)

diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/MetaModelServiceMenu.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/MetaModelServiceMenu.java
index 89e7d26dab..7d7f766832 100644
--- 
a/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/MetaModelServiceMenu.java
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/MetaModelServiceMenu.java
@@ -45,7 +45,6 @@ import org.apache.causeway.applib.annotation.SemanticsOf;
 import org.apache.causeway.applib.services.jaxb.JaxbService;
 import org.apache.causeway.applib.value.Blob;
 import org.apache.causeway.applib.value.Clob;
-import org.apache.causeway.applib.value.NamedWithMimeType;
 import org.apache.causeway.applib.value.NamedWithMimeType.CommonMimeType;
 import org.apache.causeway.commons.internal.collections._Sets;
 import org.apache.causeway.commons.internal.resources._Json;
@@ -74,41 +73,19 @@ public class MetaModelServiceMenu {
 
     static final String LOGICAL_TYPE_NAME = CausewayModuleApplib.NAMESPACE + 
".MetaModelServiceMenu";
 
-    public static abstract class ActionDomainEvent<T> extends 
CausewayModuleApplib.ActionDomainEvent<T> { }
-
-
-    @Action(
-            domainEvent = downloadMetaModelCsv.ActionDomainEvent.class,
-            semantics = SemanticsOf.NON_IDEMPOTENT, //disable client-side 
caching
-            restrictTo = RestrictTo.PROTOTYPING
-            )
-    @ActionLayout(
-            cssClassFa = "fa-download",
-            named = "Download Meta Model (CSV)",
-            sequence="500.500.2")
-    public class downloadMetaModelCsv {
-
-        public class ActionDomainEvent extends 
MetaModelServiceMenu.ActionDomainEvent<downloadMetaModelCsv> { }
-
-        @MemberSupport public Blob act(
-                @ParameterLayout(named = ".csv file name")
-                final String csvFileName) {
-
-            final DomainModel domainModel =  metaModelService.getDomainModel();
-            final StringBuilder csv = _CsvExport.toCsv(domainModel);
-
-            return Clob.of(csvFileName, CommonMimeType.CSV, csv)
-                    .toBlob(UTF_8)
-                    .zip();
-        }
-
-        @MemberSupport public String default0Act() {
-            return "metamodel.csv";
-        }
-
-    }
-
     public static enum ExportFormat implements BiFunction<String, 
MetamodelDto, Clob>  {
+        ASCII{
+            @Override public Clob apply(final String fileName, final 
MetamodelDto dto) {
+                val content = _AsciiExport.toAscii(dto).toString();
+                return Clob.of(fileName, CommonMimeType.TXT, content);
+            }
+        },
+        CSV{
+            @Override public Clob apply(final String fileName, final 
MetamodelDto dto) {
+                val content = _CsvExport2.toCsv(dto);
+                return Clob.of(fileName, CommonMimeType.CSV, content);
+            }
+        },
         JSON{
             @Override public Clob apply(final String fileName, final 
MetamodelDto dto) {
                 val content = _Json.toString(dto);
@@ -130,14 +107,9 @@ public class MetaModelServiceMenu {
                 return Clob.of(fileName, CommonMimeType.YAML, content);
             }
         },
-        ASCII{
-            @Override public Clob apply(final String fileName, final 
MetamodelDto dto) {
-                val content = _AsciiExport.toAscii(dto).toString();
-                return Clob.of(fileName, CommonMimeType.TXT, content);
-            }
-        },
     }
 
+    public static abstract class ActionDomainEvent<T> extends 
CausewayModuleApplib.ActionDomainEvent<T> { }
 
     @Action(
             domainEvent = downloadMetaModel.ActionDomainEvent.class,
@@ -152,7 +124,7 @@ public class MetaModelServiceMenu {
 
         public class ActionDomainEvent extends 
MetaModelServiceMenu.ActionDomainEvent<downloadMetaModel> { }
 
-        @MemberSupport public NamedWithMimeType act(
+        @MemberSupport public Blob act(
                 @ParameterLayout(named = "file name (does not require an 
extension)")
                 final String fileName,
 
@@ -176,12 +148,11 @@ public class MetaModelServiceMenu {
 
             final MetamodelDto metamodelDto =  
metaModelService.exportMetaModel(config);
 
-            val clob = exportFormat.apply(fileName, metamodelDto);
+            val blob = exportFormat.apply(fileName, metamodelDto)
+                    .toBlob(UTF_8);
             return zip
-                    ? clob
-                            .toBlob(UTF_8)
-                            .zip()
-                    : clob;
+                    ? blob.zip()
+                    : blob;
         }
 
         @MemberSupport public String validateAct(
@@ -193,7 +164,7 @@ public class MetaModelServiceMenu {
             return null;
         }
 
-        @MemberSupport public String defaultFileName() { return 
"metamodel.xml"; }
+        @MemberSupport public String defaultFileName() { return "metamodel"; }
         @MemberSupport public List<String> choicesNamespaces() { return 
namespaceChoices(); }
         @MemberSupport public boolean defaultIncludeInterfaces() { return 
false; }
         @MemberSupport public ExportFormat defaultExportFormat() { return 
ExportFormat.XML; }
@@ -201,6 +172,38 @@ public class MetaModelServiceMenu {
 
     }
 
+
+    @Action(
+            domainEvent = downloadMetaModelCsv.ActionDomainEvent.class,
+            semantics = SemanticsOf.NON_IDEMPOTENT, //disable client-side 
caching
+            restrictTo = RestrictTo.PROTOTYPING
+            )
+    @ActionLayout(
+            cssClassFa = "fa-download",
+            named = "Download Meta Model (CSV)",
+            sequence="500.500.2")
+    public class downloadMetaModelCsv {
+
+        public class ActionDomainEvent extends 
MetaModelServiceMenu.ActionDomainEvent<downloadMetaModelCsv> { }
+
+        @MemberSupport public Blob act(
+                @ParameterLayout(named = ".csv file name")
+                final String csvFileName) {
+
+            final DomainModel domainModel =  metaModelService.getDomainModel();
+            final StringBuilder csv = _CsvExport.toCsv(domainModel);
+
+            return Clob.of(csvFileName, CommonMimeType.CSV, csv)
+                    .toBlob(UTF_8)
+                    .zip();
+        }
+
+        @MemberSupport public String default0Act() {
+            return "metamodel.csv";
+        }
+
+    }
+
     @Action(
             domainEvent = downloadMetaModelDiff.ActionDomainEvent.class,
             semantics = SemanticsOf.NON_IDEMPOTENT, //disable client-side 
caching
diff --git 
a/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/_CsvExport2.java
 
b/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/_CsvExport2.java
new file mode 100644
index 0000000000..690234fc87
--- /dev/null
+++ 
b/api/applib/src/main/java/org/apache/causeway/applib/services/metamodel/_CsvExport2.java
@@ -0,0 +1,115 @@
+/*
+ *  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.applib.services.metamodel;
+
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.causeway.commons.internal.base._NullSafe;
+import org.apache.causeway.schema.metamodel.v2.Action;
+import org.apache.causeway.schema.metamodel.v2.Collection;
+import org.apache.causeway.schema.metamodel.v2.DomainClassDto;
+import org.apache.causeway.schema.metamodel.v2.MetamodelDto;
+import org.apache.causeway.schema.metamodel.v2.Property;
+
+import lombok.val;
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+class _CsvExport2 {
+
+    StringBuilder toCsv(final MetamodelDto metamodelDto) {
+        val sb = new StringBuilder();
+
+        sb.append(header()).append("\n");
+
+        metamodelDto
+            .getDomainClassDto()
+            .forEach(typeDto->appendCsvRow(typeDto, sb));
+
+        return sb;
+    }
+
+    // -- HELPER
+
+    private String header() {
+        return "logicalType,service?,memberType,memberId,numParams,mixedIn?";
+    }
+
+    private void appendCsvRow(final DomainClassDto typeDto, final 
StringBuilder sb) {
+
+        Optional.ofNullable(typeDto.getProperties())
+        .map(props->props.getProp())
+        .ifPresent(list->list.forEach(propDto->appendCsvRow(typeDto, propDto, 
sb)));
+
+        Optional.ofNullable(typeDto.getCollections())
+        .map(colls->colls.getColl())
+        .ifPresent(list->list.forEach(collDto->appendCsvRow(typeDto, collDto, 
sb)));
+
+        Optional.ofNullable(typeDto.getActions())
+        .map(acts->acts.getAct())
+        .ifPresent(list->list.forEach(actDto->appendCsvRow(typeDto, actDto, 
sb)));
+
+        typeDto.getCollections();
+        typeDto.getActions();
+    }
+
+    private void appendCsvRow(final DomainClassDto typeDto, final Property 
prop, final StringBuilder sb) {
+        val rowString =  Stream.of(
+                typeDto.getId(),
+                Optional.ofNullable(typeDto.isService()).orElse(false) ? "Y" : 
"",
+                "prop",
+                prop.getId(),
+                "",
+                prop.isMixedIn() ? "Y" : "")
+                .collect(Collectors.joining(","));
+
+        sb.append(rowString).append("\n");
+    }
+
+    private void appendCsvRow(final DomainClassDto typeDto, final Collection 
coll, final StringBuilder sb) {
+        val rowString =  Stream.of(
+                typeDto.getId(),
+                Optional.ofNullable(typeDto.isService()).orElse(false) ? "Y" : 
"",
+                "coll",
+                coll.getId(),
+                "",
+                coll.isMixedIn() ? "Y" : "")
+                .collect(Collectors.joining(","));
+
+        sb.append(rowString).append("\n");
+    }
+
+    private void appendCsvRow(final DomainClassDto typeDto, final Action act, 
final StringBuilder sb) {
+        val rowString =  Stream.of(
+                typeDto.getId(),
+                Optional.ofNullable(typeDto.isService()).orElse(false) ? "Y" : 
"",
+                "act",
+                act.getId(),
+                Optional.ofNullable(act.getParams())
+                    .map(params->"" + _NullSafe.size(params.getParam()))
+                    .orElse("0"),
+                act.isMixedIn() ? "Y" : "")
+                .collect(Collectors.joining(","));
+
+        sb.append(rowString).append("\n");
+    }
+
+}
diff --git a/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml 
b/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml
index d6d4b79d11..72ae7c222a 100644
--- a/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml
+++ b/examples/demo/domain/src/main/java/demoapp/dom/menubars.layout.xml
@@ -297,9 +297,8 @@ For latest we use: 
https://raw.githubusercontent.com/apache/causeway/master/anto
             </mb3:section>
             <mb3:section>
                 <mb3:named>Meta Model and Features</mb3:named>
-                <mb3:serviceAction 
objectType="causeway.applib.MetaModelServiceMenu" id="downloadMetaModelXml"/>
+                <mb3:serviceAction 
objectType="causeway.applib.MetaModelServiceMenu" id="downloadMetaModel"/>
                 <mb3:serviceAction 
objectType="causeway.applib.MetaModelServiceMenu" id="downloadMetaModelCsv"/>
-                <mb3:serviceAction 
objectType="causeway.applib.MetaModelServiceMenu" id="downloadMetaModelAscii"/>
                 <mb3:serviceAction 
objectType="causeway.applib.MetaModelServiceMenu" id="downloadMetaModelDiff"/>
                 <mb3:serviceAction 
objectType="causeway.feat.ApplicationFeatureMenu" id="allNamespaces"/>
                 <mb3:serviceAction 
objectType="causeway.feat.ApplicationFeatureMenu" id="allTypes"/>
diff --git 
a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
 
b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
index 24b356d071..9c697490e6 100644
--- 
a/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
+++ 
b/regressiontests/stable-domainmodel/src/test/java/org/apache/causeway/testdomain/domainmodel/MetaModelRegressionTest.java
@@ -18,6 +18,7 @@
  */
 package org.apache.causeway.testdomain.domainmodel;
 
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 import javax.inject.Inject;
@@ -78,9 +79,10 @@ class MetaModelRegressionTest {
         // disable if rename, as the .zip file needs to be updated.
         // Assumptions.assumeThat(getClass().getName()).contains("causeway");
 
-        final Clob metaModelClob = (Clob) factoryService
+        final Clob metaModelClob = factoryService
                 .mixin(MetaModelServiceMenu.downloadMetaModel.class, 
metaModelServiceMenu)
-                .act("metamodel", namespaces(), true, ExportFormat.XML, false);
+                .act("metamodel", namespaces(), true, ExportFormat.XML, false)
+                .toClob(StandardCharsets.UTF_8);
         final String xml = metaModelClob
                 .asString();
 

Reply via email to