You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/09/08 07:37:09 UTC
[isis] 02/02: ISIS-3206: [Metamodel] refactor shadow facet generation logic into a MetaModelAnnotator
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
commit d210fd999bef8d783b1b51b623b55f8e103166ee
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Sep 8 09:37:01 2022 +0200
ISIS-3206: [Metamodel] refactor shadow facet generation logic into a
MetaModelAnnotator
- yet requires update of Inspect MM View
---
.../services/metamodel/MetaModelAnnotator.java | 17 +++
.../services/metamodel/MetaModelExporter.java | 143 +------------------
.../metamodel/MetaModelServiceDefault.java | 13 +-
.../ShadowedFactetAttributeAnnotator.java | 92 +++++++++++++
.../services/metamodel/TitleAnnotator.java | 9 +-
.../core/metamodel/services/metamodel/_Util.java | 153 +++++++++++++++++++++
6 files changed, 273 insertions(+), 154 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelAnnotator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelAnnotator.java
index 637d2e6fd5..c134506299 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelAnnotator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelAnnotator.java
@@ -30,9 +30,13 @@ import org.apache.isis.schema.metamodel.v2.Action;
import org.apache.isis.schema.metamodel.v2.Collection;
import org.apache.isis.schema.metamodel.v2.DomainClassDto;
import org.apache.isis.schema.metamodel.v2.Facet;
+import org.apache.isis.schema.metamodel.v2.MetamodelElement;
+import org.apache.isis.schema.metamodel.v2.MetamodelElement.Annotations;
import org.apache.isis.schema.metamodel.v2.Param;
import org.apache.isis.schema.metamodel.v2.Property;
+import lombok.val;
+
/**
* SPI that allows to add arbitrary meta data as
* {@link org.apache.isis.schema.metamodel.v2.Annotation}s
@@ -58,6 +62,19 @@ public interface MetaModelAnnotator {
void annotate(Collection collectionType, OneToManyAssociation collection);
+ /**
+ * creates and adds to its parent
+ */
+ default <T extends MetamodelElement> T createAnnotation(final T t, final String name, final String value) {
+ val titleAnnot = new org.apache.isis.schema.metamodel.v2.Annotation();
+ titleAnnot.setName(name);
+ titleAnnot.setValue(value);
+ val annots = new Annotations();
+ t.setAnnotations(annots);
+ annots.getAsList().add(titleAnnot);
+ return t;
+ }
+
public interface ExporterConfig {
default String abbrev(final @Nullable Class<?> cls) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
index a1132ce04b..62290553f7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelExporter.java
@@ -18,20 +18,14 @@
*/
package org.apache.isis.core.metamodel.services.metamodel;
-import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
-import java.util.function.BiConsumer;
-import java.util.regex.Pattern;
-import org.apache.isis.applib.services.commanddto.processor.CommandDtoProcessor;
import org.apache.isis.applib.services.metamodel.Config;
-import org.apache.isis.applib.spec.Specification;
import org.apache.isis.commons.collections.Can;
-import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.collections._Maps;
import org.apache.isis.core.metamodel.facetapi.Facet;
@@ -41,7 +35,6 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.spec.feature.MixedIn;
import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
-import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
import org.apache.isis.core.metamodel.spec.feature.OneToOneActionParameter;
import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
@@ -397,46 +390,14 @@ class MetaModelExporter {
return facetType;
}
- private void visitNonNullAttributes(final Facet facet, final BiConsumer<String, String> visitor) {
- facet.visitAttributes((key, attributeObj)->{
- if(attributeObj == null) {
- return;
- }
- String str = asStr(attributeObj);
- visitor.accept(key, str);
- });
- }
+
private void addFacetAttributes(
final Facet facet,
final org.apache.isis.schema.metamodel.v2.Facet facetType,
final Config config) {
-
- visitNonNullAttributes(facet, (key, str)->
+ _Util.visitNonNullAttributes(facet, (key, str)->
addAttribute(facetType, key, str));
-
- if(config.isIncludeShadowedFacets()) {
- facet.getSharedFacetRanking()
- .ifPresent(ranking->{
- ranking.getTopRank(facet.facetType())
- .stream()
- // skip the winner, as its not shadowed
- .skip(1)
- //.filter(shadowedFacet->shadowedFacet.equals(facet))
- .forEach(shadowedFacet->{
- visitNonNullAttributes(shadowedFacet, (key, str)->{
- if(key.equals("precedence")) {
- return; // skip
- }
- addAttribute(facetType, key, String.format("%s (shadowed %s)",
- str,
- shadowedFacet.getClass().getName()));
- });
- });
- });
-
- }
-
sortFacetAttributes(facetType.getAttr());
}
@@ -491,107 +452,7 @@ class MetaModelExporter {
return specification.getBeanSort().isValue();
}
- private String asStr(final Object attributeObj) {
- String str;
- if(attributeObj instanceof Method) {
- str = asStr((Method) attributeObj);
- } else if(attributeObj instanceof String) {
- str = asStr((String) attributeObj);
- } else if(attributeObj instanceof Enum) {
- str = asStr((Enum<?>) attributeObj);
- } else if(attributeObj instanceof Class) {
- str = asStr((Class<?>) attributeObj);
- } else if(attributeObj instanceof Specification) {
- str = asStr((Specification) attributeObj);
- } else if(attributeObj instanceof Facet) {
- str = asStr((Facet) attributeObj);
- } else if(attributeObj instanceof MetaModelExportSupport) {
- str = asStr((MetaModelExportSupport) attributeObj);
- } else if(attributeObj instanceof Pattern) {
- str = asStr((Pattern) attributeObj);
- } else if(attributeObj instanceof CommandDtoProcessor) {
- str = asStr((CommandDtoProcessor) attributeObj);
- } else if(attributeObj instanceof ObjectSpecification) {
- str = asStr((ObjectSpecification) attributeObj);
- } else if(attributeObj instanceof ObjectMember) {
- str = asStr((ObjectMember) attributeObj);
- } else if(attributeObj instanceof List) {
- str = asStr((List<?>) attributeObj);
- } else if(attributeObj instanceof Object[]) {
- str = asStr((Object[]) attributeObj);
- } else {
- str = "" + attributeObj;
- }
- return str;
- }
-
- private String asStr(final String attributeObj) {
- return _Strings.emptyToNull(attributeObj);
- }
-
- private String asStr(final Specification attributeObj) {
- return attributeObj.getClass().getName();
- }
-
- private String asStr(final ObjectSpecification attributeObj) {
- return attributeObj.getFullIdentifier();
- }
-
- private String asStr(final MetaModelExportSupport attributeObj) {
- return attributeObj.toMetamodelString();
- }
-
- private String asStr(final CommandDtoProcessor attributeObj) {
- return attributeObj.getClass().getName();
- }
-
- private String asStr(final Pattern attributeObj) {
- return attributeObj.pattern();
- }
-
- private String asStr(final Facet attributeObj) {
- return attributeObj.getClass().getName();
- }
-
- private String asStr(final ObjectMember attributeObj) {
- return attributeObj.getId();
- }
-
- private String asStr(final Class<?> attributeObj) {
- return attributeObj.getCanonicalName();
- }
-
- private String asStr(final Enum<?> attributeObj) {
- return attributeObj.name();
- }
-
- private String asStr(final Method attributeObj) {
- return attributeObj.toGenericString();
- }
-
- private String asStr(final Object[] list) {
- if(list.length == 0) {
- return null; // skip
- }
- List<String> strings = _Lists.newArrayList();
- for (final Object o : list) {
- String s = asStr(o);
- strings.add(s);
- }
- return String.join(";", strings);
- }
- private String asStr(final List<?> list) {
- if(list.isEmpty()) {
- return null; // skip
- }
- List<String> strings = _Lists.newArrayList();
- for (final Object o : list) {
- String s = asStr(o);
- strings.add(s);
- }
- return String.join(";", strings);
- }
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
index 331ec60c34..8f94c18df8 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/MetaModelServiceDefault.java
@@ -42,7 +42,6 @@ import org.apache.isis.applib.services.metamodel.Config;
import org.apache.isis.applib.services.metamodel.DomainMember;
import org.apache.isis.applib.services.metamodel.DomainModel;
import org.apache.isis.applib.services.metamodel.MetaModelService;
-import org.apache.isis.commons.collections.Can;
import org.apache.isis.commons.internal.base._Strings;
import org.apache.isis.commons.internal.collections._Lists;
import org.apache.isis.commons.internal.exceptions._Exceptions;
@@ -226,11 +225,15 @@ public class MetaModelServiceDefault implements MetaModelService {
/*TODO[ISIS-3206] refactor: ideally config would provide the list, but unfortunately
* MetaModelAnnotator type is not know to Config, which lives in applib.
*/
- val annotators = config.isIncludeTitleAnnotations()
- ? (Iterable) Can.<MetaModelAnnotator>of(new TitleAnnotator(new ExporterConfig(){}))
- : Can.empty();
+ val metaModelAnnotators = _Lists.<MetaModelAnnotator>newArrayList();
+ if(config.isIncludeTitleAnnotations()) {
+ metaModelAnnotators.add(new TitleAnnotator(new ExporterConfig(){}));
+ }
+ if(config.isIncludeShadowedFacets()) {
+ metaModelAnnotators.add(new ShadowedFactetAttributeAnnotator(new ExporterConfig(){}));
+ }
- return new MetaModelExporter(specificationLoader, annotators)
+ return new MetaModelExporter(specificationLoader, metaModelAnnotators)
.exportMetaModel(config);
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/ShadowedFactetAttributeAnnotator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/ShadowedFactetAttributeAnnotator.java
new file mode 100644
index 0000000000..eeb987bb38
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/ShadowedFactetAttributeAnnotator.java
@@ -0,0 +1,92 @@
+/*
+ * 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.core.metamodel.services.metamodel;
+
+import java.util.Optional;
+
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectActionParameter;
+import org.apache.isis.core.metamodel.spec.feature.OneToManyAssociation;
+import org.apache.isis.core.metamodel.spec.feature.OneToOneAssociation;
+import org.apache.isis.schema.metamodel.v2.Action;
+import org.apache.isis.schema.metamodel.v2.Collection;
+import org.apache.isis.schema.metamodel.v2.DomainClassDto;
+import org.apache.isis.schema.metamodel.v2.Facet;
+import org.apache.isis.schema.metamodel.v2.FacetAttr;
+import org.apache.isis.schema.metamodel.v2.Param;
+import org.apache.isis.schema.metamodel.v2.Property;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.experimental.Accessors;
+
+@RequiredArgsConstructor
+public class ShadowedFactetAttributeAnnotator implements MetaModelAnnotator {
+
+ @Getter(onMethod_={@Override}) @Accessors(fluent=true)
+ private final ExporterConfig config;
+
+ @Override
+ public void annotate(final DomainClassDto domainClass, final ObjectSpecification specification) {}
+ @Override
+ public void annotate(final Action actionType, final ObjectAction action) {}
+ @Override
+ public void annotate(final Param parameterType, final ObjectActionParameter parameter) {}
+ @Override
+ public void annotate(final Property propertyType, final OneToOneAssociation property) {}
+ @Override
+ public void annotate(final Collection collectionType, final OneToManyAssociation collection) {}
+
+ @Override
+ public void annotate(final Facet facetType, final org.apache.isis.core.metamodel.facetapi.Facet facet) {
+ facet.getSharedFacetRanking()
+ .ifPresent(ranking->{
+ ranking.getTopRank(facet.facetType())
+ .stream()
+ // skip the winner, as its not shadowed
+ .skip(1)
+ //.filter(shadowedFacet->shadowedFacet.equals(facet))
+ .forEach(shadowedFacet->{
+ _Util.visitNonNullAttributes(shadowedFacet, (attributeName, str)->{
+ if(attributeName.equals("precedence")) {
+ return; // skip
+ }
+ addAttributeAnnotation(facetType, attributeName, String.format("%s (shadowed %s)",
+ str,
+ shadowedFacet.getClass().getName()));
+ });
+ });
+ });
+ }
+
+ // -- HELPER
+
+ private void addAttributeAnnotation(final Facet facetType, final String attributeName, final String annotation) {
+ lookupByName(facetType, attributeName)
+ .ifPresent(facetAttr->{
+ createAnnotation(facetAttr, "@shadowed", annotation);
+ });
+ }
+
+ private Optional<FacetAttr> lookupByName(final Facet facetType, final String attributeName) {
+ return Optional.empty();
+ }
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/TitleAnnotator.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/TitleAnnotator.java
index 2357707368..d2dfe7ef6d 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/TitleAnnotator.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/TitleAnnotator.java
@@ -30,7 +30,6 @@ import org.apache.isis.schema.metamodel.v2.Collection;
import org.apache.isis.schema.metamodel.v2.DomainClassDto;
import org.apache.isis.schema.metamodel.v2.Facet;
import org.apache.isis.schema.metamodel.v2.MetamodelElement;
-import org.apache.isis.schema.metamodel.v2.MetamodelElement.Annotations;
import org.apache.isis.schema.metamodel.v2.Param;
import org.apache.isis.schema.metamodel.v2.Property;
@@ -118,13 +117,7 @@ public class TitleAnnotator implements MetaModelAnnotator {
}
private <T extends MetamodelElement> T titleAnnotation(final T t, final String title) {
- val titleAnnot = new org.apache.isis.schema.metamodel.v2.Annotation();
- titleAnnot.setName("@title");
- titleAnnot.setValue(title);
- val annots = new Annotations();
- t.setAnnotations(annots);
- annots.getAsList().add(titleAnnot);
- return t;
+ return createAnnotation(t, "@title", title);
}
private String titleSuffix(final boolean isMixedIn) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/_Util.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/_Util.java
new file mode 100644
index 0000000000..73e18a2002
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/metamodel/_Util.java
@@ -0,0 +1,153 @@
+/*
+ * 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.core.metamodel.services.metamodel;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.regex.Pattern;
+
+import org.apache.isis.applib.services.commanddto.processor.CommandDtoProcessor;
+import org.apache.isis.applib.spec.Specification;
+import org.apache.isis.commons.internal.base._Strings;
+import org.apache.isis.commons.internal.collections._Lists;
+import org.apache.isis.core.metamodel.facetapi.Facet;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+class _Util {
+
+ void visitNonNullAttributes(final Facet facet, final BiConsumer<String, String> visitor) {
+ facet.visitAttributes((key, attributeObj)->{
+ if(attributeObj == null) {
+ return;
+ }
+ String str = asStr(attributeObj);
+ visitor.accept(key, str);
+ });
+ }
+
+ String asStr(final Object attributeObj) {
+ String str;
+ if(attributeObj instanceof Method) {
+ str = asStr((Method) attributeObj);
+ } else if(attributeObj instanceof String) {
+ str = asStr((String) attributeObj);
+ } else if(attributeObj instanceof Enum) {
+ str = asStr((Enum<?>) attributeObj);
+ } else if(attributeObj instanceof Class) {
+ str = asStr((Class<?>) attributeObj);
+ } else if(attributeObj instanceof Specification) {
+ str = asStr((Specification) attributeObj);
+ } else if(attributeObj instanceof Facet) {
+ str = asStr((Facet) attributeObj);
+ } else if(attributeObj instanceof MetaModelExportSupport) {
+ str = asStr((MetaModelExportSupport) attributeObj);
+ } else if(attributeObj instanceof Pattern) {
+ str = asStr((Pattern) attributeObj);
+ } else if(attributeObj instanceof CommandDtoProcessor) {
+ str = asStr((CommandDtoProcessor) attributeObj);
+ } else if(attributeObj instanceof ObjectSpecification) {
+ str = asStr((ObjectSpecification) attributeObj);
+ } else if(attributeObj instanceof ObjectMember) {
+ str = asStr((ObjectMember) attributeObj);
+ } else if(attributeObj instanceof List) {
+ str = asStr((List<?>) attributeObj);
+ } else if(attributeObj instanceof Object[]) {
+ str = asStr((Object[]) attributeObj);
+ } else {
+ str = "" + attributeObj;
+ }
+ return str;
+ }
+
+ // -- HELPER
+
+ private String asStr(final String attributeObj) {
+ return _Strings.emptyToNull(attributeObj);
+ }
+
+ private String asStr(final Specification attributeObj) {
+ return attributeObj.getClass().getName();
+ }
+
+ private String asStr(final ObjectSpecification attributeObj) {
+ return attributeObj.getFullIdentifier();
+ }
+
+ private String asStr(final MetaModelExportSupport attributeObj) {
+ return attributeObj.toMetamodelString();
+ }
+
+ private String asStr(final CommandDtoProcessor attributeObj) {
+ return attributeObj.getClass().getName();
+ }
+
+ private String asStr(final Pattern attributeObj) {
+ return attributeObj.pattern();
+ }
+
+ private String asStr(final Facet attributeObj) {
+ return attributeObj.getClass().getName();
+ }
+
+ private String asStr(final ObjectMember attributeObj) {
+ return attributeObj.getId();
+ }
+
+ private String asStr(final Class<?> attributeObj) {
+ return attributeObj.getCanonicalName();
+ }
+
+ private String asStr(final Enum<?> attributeObj) {
+ return attributeObj.name();
+ }
+
+ private String asStr(final Method attributeObj) {
+ return attributeObj.toGenericString();
+ }
+
+ private String asStr(final Object[] list) {
+ if(list.length == 0) {
+ return null; // skip
+ }
+ List<String> strings = _Lists.newArrayList();
+ for (final Object o : list) {
+ String s = asStr(o);
+ strings.add(s);
+ }
+ return String.join(";", strings);
+ }
+
+ private String asStr(final List<?> list) {
+ if(list.isEmpty()) {
+ return null; // skip
+ }
+ List<String> strings = _Lists.newArrayList();
+ for (final Object o : list) {
+ String s = asStr(o);
+ strings.add(s);
+ }
+ return String.join(";", strings);
+ }
+
+}