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 393d2a5a2b ISIS-3049: fully implement FacetHolderLayered 393d2a5a2b is described below commit 393d2a5a2b5942dc41e6bfba2aec77df15809031 Author: Andi Huber <ahu...@apache.org> AuthorDate: Tue Jun 28 22:08:33 2022 +0200 ISIS-3049: fully implement FacetHolderLayered - provides a merged view of the local and the shared list of facets --- .../metamodel/facetapi/FacetHolderAbstract.java | 16 +++--- .../metamodel/facetapi/FacetHolderLayered.java | 57 ++++++++++++++++++---- .../isis/core/metamodel/facetapi/FacetRanking.java | 7 +++ 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderAbstract.java index e53864592f..432e9ecf3e 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderAbstract.java @@ -70,14 +70,14 @@ implements FacetHolder { private final Object $lock = new Object(); @Override - public boolean containsFacet(final Class<? extends Facet> facetType) { + public final boolean containsFacet(final Class<? extends Facet> facetType) { synchronized($lock) { return snapshot.get().containsKey(facetType); } } @Override - public void addFacet(final @NonNull Facet facet) { + public final void addFacet(final @NonNull Facet facet) { synchronized($lock) { val ranking = rankingByType.computeIfAbsent(facet.facetType(), FacetRanking::new); @@ -88,15 +88,17 @@ implements FacetHolder { } } + //TODO should be made final - however, overridden by ObjectSpecificationAbstract, + // which potentially leads to inconsistent behavior with facet and facet-ranking streaming @Override - public <T extends Facet> T getFacet(final Class<T> facetType) { + public /*final*/ <T extends Facet> T getFacet(final Class<T> facetType) { synchronized($lock) { return uncheckedCast(snapshot.get().get(facetType)); } } @Override - public Stream<Facet> streamFacets() { + public final Stream<Facet> streamFacets() { synchronized($lock) { // consumers should play nice and don't take too long (as we have a lock) return snapshot.get().values().stream(); @@ -104,7 +106,7 @@ implements FacetHolder { } @Override - public int getFacetCount() { + public final int getFacetCount() { synchronized($lock) { return snapshot.get().size(); } @@ -113,12 +115,12 @@ implements FacetHolder { // -- VALIDATION SUPPORT @Override - public Stream<FacetRanking> streamFacetRankings() { + public final Stream<FacetRanking> streamFacetRankings() { return rankingByType.values().stream(); } @Override - public Optional<FacetRanking> getFacetRanking(final Class<? extends Facet> facetType) { + public final Optional<FacetRanking> getFacetRanking(final Class<? extends Facet> facetType) { return Optional.ofNullable(rankingByType.get(facetType)); } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderLayered.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderLayered.java index ba0cee8a4c..4549df9b94 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderLayered.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetHolderLayered.java @@ -18,11 +18,13 @@ */ package org.apache.isis.core.metamodel.facetapi; +import java.util.HashSet; import java.util.Optional; import java.util.stream.Stream; import org.apache.isis.applib.Identifier; import org.apache.isis.applib.services.i18n.TranslationContext; +import org.apache.isis.commons.internal.base._NullSafe; import org.apache.isis.core.metamodel.context.MetaModelContext; import org.apache.isis.core.metamodel.facets.FacetedMethod; @@ -87,7 +89,7 @@ implements FacetHolder { return shared.getFacetCount(); } // cannot simply add up shared and local - return (int)streamFacets().count(); + return (int)streamPopulatedFacetTypes().count(); } @Override @@ -110,9 +112,11 @@ implements FacetHolder { if(localFacet.semanticEquals(sharedFacet)) { return localFacet; // arbitrarily picking one } - return localFacet; // have the local win, this is safe for layout.xml stuff, but not for future use-cases + // semantic conflict + // have the local win, this is safe for layout.xml stuff, but probably not for future use-cases + return localFacet; -// // semantic conflict (unfortunately semanticEquals() is not always implemented yet) +// unfortunately semanticEquals() is not always implemented yet, otherwise we could throw ... // throw _Exceptions.illegalState("conflicting facet semantics between shared %s and local %s", // FacetUtil.toString(sharedFacet), // FacetUtil.toString(localFacet)); @@ -126,20 +130,55 @@ implements FacetHolder { @Override public Stream<Facet> streamFacets() { - //FIXME[ISIS-3049] concat with local - return shared.streamFacets(); + // optimization, not strictly required + if(local.getFacetCount()==0) { + return shared.streamFacets(); + } + return streamPopulatedFacetTypes() + .<Facet>map(facetType->getFacet(facetType)) + .filter(_NullSafe::isPresent); } @Override public Stream<FacetRanking> streamFacetRankings() { - //FIXME[ISIS-3049] concat with local - return shared.streamFacetRankings(); + // optimization, not strictly required + if(local.getFacetCount()==0) { + return shared.streamFacetRankings(); + } + return streamPopulatedFacetTypes() + .map(facetType->getFacetRanking(facetType).orElseThrow()); } @Override public Optional<FacetRanking> getFacetRanking(final Class<? extends Facet> facetType) { - //FIXME[ISIS-3049] concat with local - return shared.getFacetRanking(facetType); + val localFacetRanking = local.getFacetRanking(facetType); + val sharedFacetRanking = shared.getFacetRanking(facetType); + + if(localFacetRanking.isEmpty()) { + return sharedFacetRanking; + } + if(sharedFacetRanking.isEmpty()) { + return localFacetRanking; + } + + val combinedFacetRanking = new FacetRanking(facetType); + // arbitrarily picking order: shared first and local last, such that if in conflict local wins + combinedFacetRanking.addAll(sharedFacetRanking.get()); + combinedFacetRanking.addAll(localFacetRanking.get()); + + return Optional.of(combinedFacetRanking); + } + + // -- HELPER + + private Stream<Class<? extends Facet>> streamPopulatedFacetTypes() { + val facetTypes = new HashSet<Class<? extends Facet>>(); + Stream.concat( + shared.streamFacets(), + local.streamFacets()) + .map(Facet::facetType) + .forEach(facetTypes::add); + return facetTypes.stream(); } } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetRanking.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetRanking.java index b3bdf31ce6..cc0d8b8e92 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetRanking.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facetapi/FacetRanking.java @@ -121,6 +121,11 @@ public final class FacetRanking { return changesTopRank; } + public void addAll(final @NonNull FacetRanking facetRanking) { + facetRanking.facetsByPrecedence.asNavigableMapElseFail() + .forEach((k, facets)->facets.forEach(this::add)); + } + /** * Optionally returns the winning facet, considering the event facet (if any) and the top rank, * based on whether there was any added that has given facetType. @@ -279,4 +284,6 @@ public final class FacetRanking { } + + }