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/causeway.git
The following commit(s) were added to refs/heads/master by this push:
new f69448c1b3 CAUSEWAY-3686: refining VetReason reduce algorithm
f69448c1b3 is described below
commit f69448c1b3e7b4cc631cdcdaf0b5c0874ace72b1
Author: Andi Huber <[email protected]>
AuthorDate: Thu Feb 8 15:46:54 2024 +0100
CAUSEWAY-3686: refining VetReason reduce algorithm
- this should fix quite some ban-icons appearing, where we don't really
want them
---
.../causeway/core/metamodel/consent/Consent.java | 80 +++++++++++++++++++---
.../authorization/AuthorizationFacetAbstract.java | 2 +-
2 files changed, 71 insertions(+), 11 deletions(-)
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
index cefaee11fa..391180a5b6 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/consent/Consent.java
@@ -38,15 +38,46 @@ public interface Consent {
@lombok.Value @Accessors(fluent=true)
public static class VetoReason implements Serializable {
private static final long serialVersionUID = 1L;
+ /**
+ * Introduced to help pick a winner when merging 2 {@link
VetoReason}(s).
+ * <p>
+ * PROGRAMMING_MODEL always wins over SECURITY.
+ */
+ public enum VetoOriging {
+ /**
+ * Veto originates from security mechanism.
+ * <p>
+ * In other words: the user is not authorized to either view or
change the feature.
+ */
+ SECURITY,
+ /**
+ * Veto originates from programming model, either implicit or
explicit see {@link UiHint}.
+ */
+ PROGRAMMING_MODEL;
+ public boolean isSecurity() { return this==SECURITY; }
+ public boolean isProgrammingModel() { return
this==PROGRAMMING_MODEL; }
+ /** reduce to max ordinal */
+ static VetoOriging reduceToMaxOrdinal(final VetoOriging a, final
VetoOriging b) {
+ return b.ordinal()>a.ordinal() ? b : a;
+ }
+ }
/**
* Introduced to help decide whether or not to display a 'ban' icon
* in the UI, with a tooltip showing the disabled reason.
*/
public enum UiHint {
/**
- * When prototyping, icon rendering can be suppressed via config
option.
+ * Reason is <b>implicit</b> by programming model,
+ * reason text is generic and rather of interest to the developer
+ * than the end-user.
+ * <p>
+ * Show only when prototyping. However, when prototyping, can be
suppressed via config option.
*/
NO_ICON_UNLESS_PROTOTYPING,
+ /**
+ * Reason is <b>explicit</b> either by programming model or
authentication mechanism,
+ * reason text is designated to reach the end-user.
+ */
SHOW_BAN_ICON;
public boolean isNoIconUnlessPrototying() { return
this==NO_ICON_UNLESS_PROTOTYPING; }
public boolean isShowBanIcon() { return this==SHOW_BAN_ICON; }
@@ -55,28 +86,57 @@ public interface Consent {
return b.ordinal()>a.ordinal() ? b : a;
}
}
+ private final VetoOriging vetoOriging;
private final UiHint uiHint;
private final @NonNull String string;
- public static VetoReason explicit(final String reason) {
+ private static VetoReason of(
+ final @NonNull VetoOriging vetoOriging,
+ final @NonNull UiHint uiHint,
+ final String reason) {
_Assert.assertTrue(_Strings.isNotEmpty(reason));
- return new VetoReason(UiHint.SHOW_BAN_ICON, reason);
+ return new VetoReason(vetoOriging, uiHint, reason);
+ }
+ public static VetoReason unauthorized(final String reason) {
+ return of(VetoOriging.SECURITY, UiHint.SHOW_BAN_ICON, reason);
+ }
+ public static VetoReason explicit(final String reason) {
+ return of(VetoOriging.PROGRAMMING_MODEL, UiHint.SHOW_BAN_ICON,
reason);
}
private static VetoReason inferred(final String reason) {
- _Assert.assertTrue(_Strings.isNotEmpty(reason));
- return new VetoReason(UiHint.NO_ICON_UNLESS_PROTOTYPING, reason);
+ return of(VetoOriging.PROGRAMMING_MODEL,
UiHint.NO_ICON_UNLESS_PROTOTYPING, reason);
}
public Optional<VetoReason> toOptional() {
return Optional.of(this);
}
+ /**
+ * {@code Pi}: origin=PROGRAMMING_MODEL, nature=implicit
(NO_ICON_UNLESS_PROTOTYPING)<br>
+ * {@code Pe}: origin=PROGRAMMING_MODEL, nature=explicit
(SHOW_BAN_ICON)<br>
+ * {@code S(e)}: origin=SECURITY, nature=explicit (SHOW_BAN_ICON)<br>
+ * <p>
+ * {@code Pi ৹ Pi := pick any or concat}<br>
+ * {@code Pe ৹ Pe := pick any or concat}<br>
+ * {@code S(e) ৹ S(e) := pick any or concat}<br>
+ * <br>
+ * {@code Pi ৹ Pe := Pe}<br>
+ * {@code Pi ৹ S(e) := Pi}<br>
+ * {@code Pe ৹ S(e) := Pi}<br>
+ * In other words: winner picking is driven by <i>origin</i> first and
<i>nature</i> second.
+ */
public VetoReason reduce(final VetoReason other) {
+ // arbitrarily shifting left by 4 so reserving some room for more
UiHint enum values
+ final int thisScore = (this.vetoOriging.ordinal()<<4) +
this.uiHint.ordinal();
+ final int otherScore = (other.vetoOriging.ordinal()<<4) +
other.uiHint.ordinal();
+
final List<String> mergedText = new ArrayList<>(2);
- switch(_Ints.compare(this.uiHint.ordinal(),
other.uiHint.ordinal())) {
- case -1: mergedText.add(other.string); break;
- case 0: mergedText.add(this.string);
mergedText.add(other.string); break;
- case 1: mergedText.add(this.string); break;
+ final List<UiHint> winnerUiHint = new ArrayList<>(1);
+ switch(_Ints.compare(thisScore, otherScore)) {
+ case -1: winnerUiHint.add(other.uiHint);
mergedText.add(other.string); break;
+ case 0: winnerUiHint.add(this.uiHint);
mergedText.add(this.string); mergedText.add(other.string); break;
+ case 1: winnerUiHint.add(this.uiHint);
mergedText.add(this.string); break;
}
return new VetoReason(
- UiHint.reduceToMaxOrdinal(this.uiHint, other.uiHint),
+ VetoOriging.reduceToMaxOrdinal(this.vetoOriging,
other.vetoOriging),
+ winnerUiHint.get(0),
mergedText.stream().collect(Collectors.joining("; ")));
}
// -- PREDEFINED REASONS
diff --git
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java
index 066001442a..b9c1ed64ab 100644
---
a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java
+++
b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/postprocessors/allbutparam/authorization/AuthorizationFacetAbstract.java
@@ -87,7 +87,7 @@ implements AuthorizationFacet {
log.debug("disables[{}] -> {}", ic.getIdentifier(), disables);
}
- return Optional.ofNullable(disables).map(VetoReason::explicit);
+ return Optional.ofNullable(disables).map(VetoReason::unauthorized);
}
}