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 <[email protected]> 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); + } + +}
