major
#29724
PathNavigation: abstract attribute rejected by isDerived() check even though concrete overrides exist and are tracked
Problem
PathNavigation (Zeile 59-63) lehnt jedes Attribut mit isDerived()=true ab:
{{{#!java if (reference.isDerived()) {
context.error("Path-navigation references derived (computed) attribute '"
+ TLModelUtil.qualifiedName(part)
+ "'. Derived attributes do not fire change notifications and cannot be tracked"
+ " for role-rule invalidation.");
} }}}
Abstrakte Attribute auf Interfaces (z.B. tl.element:StructuredElementContainer#children) liefern isDerived()=true, weil NoStorage#isReadOnly() für abstrakte Attribute true liefert. Die Prüfung unterscheidet nicht zwischen tatsächlich berechneten Attributen (die wirklich keine Change-Notifications feuern) und abstrakten Attributen, deren konkrete Overrides auf implementierenden Klassen sehr wohl gespeichert sind und Change-Notifications feuern.
Der Code direkt danach (Zeile 66-70) sammelt genau diese konkreten Overrides bereits korrekt:
{{{#!java _relevantParts = Stream.concat(
operations.getOverrides(reference).stream()
.filter(Predicate.not(TLStructuredTypePart::isDerived)),
Stream.of(reference))
.collect(Collectors.toSet());
}}}
D.h. das Change-Tracking über die konkreten Overrides funktioniert, aber der context.error() davor verhindert das Laden der Regel.
Auswirkung
Eine Anwendung mit Rollenregeln, die über tl.element:StructuredElementContainer#children navigieren (z.B. Vererbung von Rollen entlang der Strukturhierarchie), bekommt beim Start 5+ Fehler:
ERROR: Path-navigation references derived (computed) attribute
'tl.element:StructuredElementContainer#children'.
Derived attributes do not fire change notifications
and cannot be tracked for role-rule invalidation.
Die betroffenen Regeln laden nicht, d.h. die Rollenvererbung entlang der Strukturhierarchie (Rollen abwärts zu Kindelementen, Portfolio-/Navigationsrollen aufwärts zu Elternknoten) funktioniert nicht. Die Anwendung startet zwar, aber Nicht-Admin-Benutzer sehen ggf. keine Strukturelemente.
Der Workaround wäre, die 5 abstrakten Regeln durch je eine Regel pro konkreter Container-Klasse zu ersetzen — in einer typischen Anwendung 30+ Klassen × 5 Regeln = 150+ Regeln. Das ist unverhältnismäßig und wartungsintensiv.
Lösung
Die isDerived()-Prüfung in PathNavigation soll abstrakte Attribute ausnehmen, wenn nicht-abgeleitete konkrete Overrides existieren. Vorschlag:
{{{#!java if (reference.isDerived()) {
Set<TLStructuredTypePart> concreteOverrides = operations.getOverrides(reference)
.stream()
.filter(Predicate.not(TLStructuredTypePart::isDerived))
.collect(Collectors.toSet());
if (concreteOverrides.isEmpty()) {
context.error("Path-navigation references derived (computed) attribute '"
+ TLModelUtil.qualifiedName(part)
+ "'. Derived attributes do not fire change notifications"
+ " and cannot be tracked for role-rule invalidation.");
}
} }}}
Damit bleibt der Fehler für tatsächlich berechnete Attribute ohne konkrete Overrides bestehen, aber abstrakte Interface-Attribute mit konkreten Implementierungen werden akzeptiert — das Change-Tracking über _relevantParts deckt sie bereits ab.
Betroffene Datei
com.top_logic.element.boundsec.manager.rule.PathNavigation (tl-element)