critical
#29080
Unerwünschte Zeilenobjekte in Tabellen bei Änderungen aus anderen Session
Aufgrund der aktuellen Implementierung von receiveModelChangedEvent und receiveModelCreatedEvent in der TableComponent kann es vorkommen, dass in einer Tabelle unerwünschte Zeilenobjekte auftauchen, nachdem diese Zeilenobjekte vorher in einer anderen Session geändert oder angelegt wurden.
Dies sorgt dafür, dass Benutzer auf diese Weise Elemente zu sehen bekommen, die sie (aus Berechtigungsgründen) gar nicht sehen dürfen.
**Beispielsituation:**
- Man hat einen Baum, der Projektelemente anzeigt.
- Die Selektion des Baumes dient als Modell für eine Tabelle, die z.B. die Komponenten des selektierten Projektelements anzeigt.
- Die Tabelle hat einen Editor / Dialog, in dem die in der Tabelle selektierte Komponente angezeigt wird.
**Ablauf:**
- Benutzer 1 selektiert ein Projektelement und sieht in der Tabelle (nur) die Komponenten zum selektierten Projektelement.
- Benutzer 2 selektiert ein anderes Projektelement, selektiert dort eine Komponente und ändert diese im Editor / Dialog.
- Benutzer 1 aktualisiert die GUI (z.B. durch F5 oder Spaltenverschiebung in der Tabelle oder durch einen Klick innerhalb der Tabelle, ohne dadurch das Modell im Baum zu ändern.)
- Fehler: Die von Benutzer 2 geänderte Komponente taucht plötzlich in der Tabelle von Benutzer 1 auf, obwohl diese gar nicht zu dem aktuell selektierten Projektelement gehört.
- Eine Umselektion im Projektebaum "repariert" die Tabelle wieder, bis erneut in einer anderen Session eine Komponente geändert (oder angelegt) wird.
**Ursache:**
Das Problem liegt an der Implementierung / Konfiguration und unterschiedlichen Auslegung der Methode supportsListElement im ListModelBuilder.
- Wird ein Element geändert oder angelegt, wird supportsListElement an der Tabelle für dieses Element aufgerufen. Falls das Element "unterstützt" wird, fügt die Tabelle dieses Element direkt der Liste der Zeilenobjekte ohne weitere Prüfungen hinzu, anstatt den ModelBuilder erneut aufzurufen.
- In der Praxis sind die Methoden meist in der Form element instanceof MyType implementiert, wodurch jedes Objekt dieses Typs in der Liste hinzugefügt wird, unabhängig, ob diese zur Selektion des Masters passt oder zu sonstigen in ModelBuilder implementierten (fachlichen) Filtern.
- Wird im Editor / Dialog durch ein Goto oder Bookmarklink eine Komponente als Modell gesetzt, versucht die Tabelle, diese Komponente als Selektion zu setzen und sich ein dazu passendes Model zu setzen. Hierbei wird auch supportsListElement geprüft, diesmal jedoch mit einer anderen Semantik, die genau diese übliche Implementierung von element instanceof MyType erwartet.
**Lösung:**
In den entsprechenden receive-Methoden der TableComponent muss statt addRow() ein invalidate() aufgerufen werden, so dass der ModelBuilder auf normalen Weg berechnet, welche Komponenten nach der Änderung nun dargestellt werden sollen und welche nicht.
Das Ganze muss auch bei anderen receive-Methoden implementierenden Klassen geprüft werden, z.B. TreeTableComponent, GridComponent, ...
Umsetzung
- Wenn Objekt-Typen in der Tabelle angegeben werden, wird automatisch ein instanceOf check durchgeführt. Nur Elemente die den instanceOf check überstehen werden an die ListModelBuilder#supportsListElement-API übergeben.
- Es wurde eine neue ElementUpdate-Konstante com.top_logic.mig.html.ElementUpdate.UNKNOWN eingeführt. Wenn diese in ListModelBuilder#supportsListElement zurückgegeben wird, dann wird die Tabelle invalidiert und die Liste neu erstellt.
- ListModelByExpression wurde angepasst, so dass wenn kein Script supportsElement gesetzt ist, immer ElementUpdate.UNKNOWN zurückgegeben wird. Neue Tabellen/Grids werden ohne supportsElement erstellt um zu verhindern, dass der Entwickler "elements" anpasst, aber "suportsElement" vergisst.
Code-Migration
- Wenn bei einem Objekt unklar ist, ob es in die Liste aufgenommen werden soll oder aus der Liste entfernt werden soll, muss der ListModelBuilder in ListModelBuilder#supportsListElement ElementUpdate.UNKNOWN zurückgeben.
- InApp-Tabellen und Grids müssen überprüft werden. Wenn die Tabelle/Grid alle Objekte eines Typs anzeigt, muss "true" zurückgegeben werden. Wenn die Tabelle/Grid die Liste neu aufbauen soll, wenn ein Element des unterstützten Typs erstellt wird, muss "supportsElement" leer gelassen werden.