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();