Skip to content

Commit 005abcc

Browse files
committed
Send matched semantic public IDs so remote rows can render icons
1 parent 43e930c commit 005abcc

4 files changed

Lines changed: 99 additions & 13 deletions

File tree

‎framework/src/main/java/dev/ikm/komet/framework/search/SearchPanelController.java‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,29 @@ public String toString() {
374374
}
375375
}
376376

377-
public record NidTextRecord(int nid, String text, boolean active, List<UUID> publicIds) {
377+
/**
378+
* A top-level search result row.
379+
*
380+
* <p>{@code publicIds} and {@code semanticPublicIds} exist for results that came from
381+
* a remote search service, where {@code nid} is meaningless — nids are assigned per
382+
* data store, so a remote row has no local entity to resolve identity from. Locally
383+
* sourced rows leave both empty and resolve everything from {@code nid} instead.
384+
*
385+
* @param nid the local nid, or 0 for a remote row
386+
* @param text display label, which may carry {@code <B>…</B>} markup
387+
* @param active whether the concept is active
388+
* @param publicIds UUIDs of the concept, for remote rows
389+
* @param semanticPublicIds UUIDs of each matched semantic, positionally aligned with
390+
* the row's description list, for remote rows
391+
*/
392+
public record NidTextRecord(int nid, String text, boolean active, List<UUID> publicIds,
393+
List<List<UUID>> semanticPublicIds) {
378394
public NidTextRecord(int nid, String text, boolean active) {
379-
this(nid, text, active, List.of());
395+
this(nid, text, active, List.of(), List.of());
396+
}
397+
398+
public NidTextRecord(int nid, String text, boolean active, List<UUID> publicIds) {
399+
this(nid, text, active, publicIds, List.of());
380400
}
381401
}
382402
}

‎kview/src/main/java/dev/ikm/komet/kview/mvvm/view/search/NextGenSearchController.java‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,14 @@ private void doSearch(ActionEvent actionEvent) {
342342
// means it cannot look the label up locally, so use the name the
343343
// service resolved -- displayName() prefers the highlighted
344344
// preferred name, matching what the local branch shows.
345+
// Positionally aligned with the semantics list built below,
346+
// so the cell can pair each row with its own identity.
347+
List<List<UUID>> semanticUuids = g.matchingSemantics().stream()
348+
.map(m -> m.publicId().stream().map(UUID::fromString).toList())
349+
.toList();
345350
SearchPanelController.NidTextRecord key =
346-
new SearchPanelController.NidTextRecord(0, g.displayName(), g.active(), uuids);
351+
new SearchPanelController.NidTextRecord(
352+
0, g.displayName(), g.active(), uuids, semanticUuids);
347353
List<LatestVersionSearchResult> semantics = g.matchingSemantics().stream()
348354
.map(m -> new LatestVersionSearchResult(
349355
new Latest<>(SemanticEntityVersion.class),

‎kview/src/main/java/dev/ikm/komet/kview/mvvm/view/search/SearchCellTopComponent.java‎

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.slf4j.Logger;
2121
import org.slf4j.LoggerFactory;
2222

23+
import java.util.ArrayList;
2324
import java.util.List;
2425
import java.util.Map;
2526
import java.util.UUID;
@@ -111,7 +112,8 @@ protected void updateItem(Object item, boolean empty) {
111112
controller.setData(entity);
112113
controller.setComponentText(highlightedTitle(topText));
113114

114-
controller.getDescriptionListViewItems().setAll(mapEntry.getValue());
115+
controller.getDescriptionListViewItems().setAll(
116+
descriptionRows(mapEntry.getValue(), List.of()));
115117

116118
if (entityVersion.active()) {
117119
controller.getRetiredHBox().getChildren().remove(controller.getRetiredLabel());
@@ -133,7 +135,8 @@ protected void updateItem(Object item, boolean empty) {
133135
controller.setData(null);
134136
controller.setRemotePublicIds(nidTextRecord.publicIds());
135137
controller.setComponentText(nidTextRecord.text());
136-
controller.getDescriptionListViewItems().setAll(mapEntry.getValue());
138+
controller.getDescriptionListViewItems().setAll(
139+
descriptionRows(mapEntry.getValue(), nidTextRecord.semanticPublicIds()));
137140
if (nidTextRecord.active()) {
138141
controller.getRetiredHBox().getChildren().remove(controller.getRetiredLabel());
139142
} else if (!controller.getRetiredHBox().getChildren().contains(controller.getRetiredLabel())) {
@@ -148,6 +151,28 @@ protected void updateItem(Object item, boolean empty) {
148151
}
149152
}
150153

154+
/**
155+
* Pairs each search result with the public ID of the semantic it matched.
156+
*
157+
* <p>The two lists arrive positionally aligned — the service returns the matches in
158+
* one order and they are carried through unchanged — so they are zipped once here
159+
* rather than having the cell look IDs up by row index. {@code semanticPublicIds} is
160+
* empty for locally sourced results, which resolve identity from their own version.
161+
*
162+
* @param results the matched semantics for one concept
163+
* @param semanticPublicIds UUIDs per result, or empty for local results
164+
* @return one row per result, in the same order
165+
*/
166+
private static List<SortResultConceptEntryController.DescriptionSemanticRow> descriptionRows(
167+
List<LatestVersionSearchResult> results, List<List<UUID>> semanticPublicIds) {
168+
List<SortResultConceptEntryController.DescriptionSemanticRow> rows = new ArrayList<>(results.size());
169+
for (int i = 0; i < results.size(); i++) {
170+
List<UUID> ids = i < semanticPublicIds.size() ? semanticPublicIds.get(i) : List.of();
171+
rows.add(new SortResultConceptEntryController.DescriptionSemanticRow(results.get(i), ids));
172+
}
173+
return rows;
174+
}
175+
151176
/**
152177
* Mark up the concept title with the same {@code <B>...</B>} convention
153178
* Lucene's highlighter uses for description-semantic snippets, so the

‎kview/src/main/java/dev/ikm/komet/kview/mvvm/view/search/SortResultConceptEntryController.java‎

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,15 @@
3030
import dev.ikm.komet.kview.events.pattern.MakePatternWindowEvent;
3131
import dev.ikm.komet.kview.mvvm.view.AbstractBasicController;
3232
import dev.ikm.komet.layout.editor.StandardEditorWindows;
33+
import dev.ikm.tinkar.common.id.PublicIds;
34+
import dev.ikm.tinkar.coordinate.stamp.calculator.Latest;
3335
import dev.ikm.tinkar.coordinate.stamp.calculator.LatestVersionSearchResult;
3436
import dev.ikm.tinkar.entity.ConceptEntity;
3537
import dev.ikm.tinkar.entity.Entity;
3638
import dev.ikm.tinkar.entity.EntityService;
3739
import dev.ikm.tinkar.entity.EntityVersion;
3840
import dev.ikm.tinkar.entity.PatternEntity;
41+
import dev.ikm.tinkar.entity.SemanticEntityVersion;
3942
import dev.ikm.tinkar.events.EvtBus;
4043
import dev.ikm.tinkar.events.EvtBusFactory;
4144
import dev.ikm.tinkar.common.service.RemoteConceptSearchService;
@@ -87,7 +90,7 @@ public class SortResultConceptEntryController extends AbstractBasicController {
8790
private Label retiredLabel;
8891

8992
@FXML
90-
private ListView<LatestVersionSearchResult> descriptionsListView;
93+
private ListView<DescriptionSemanticRow> descriptionsListView;
9194

9295
@FXML
9396
private Node dragIndicator;
@@ -143,7 +146,7 @@ public void initialize() {
143146
});
144147

145148
descriptionsListView.setFixedCellSize(LIST_VIEW_CELL_SIZE);
146-
descriptionsListView.getItems().addListener((ListChangeListener<? super LatestVersionSearchResult>) change -> updateListViewPrefHeight());
149+
descriptionsListView.getItems().addListener((ListChangeListener<? super DescriptionSemanticRow>) change -> updateListViewPrefHeight());
147150
updateListViewPrefHeight();
148151

149152
descriptionsListView.setCellFactory(param -> new DescriptionSemanticListCell());
@@ -203,7 +206,24 @@ public void setComponentText(String highlightedTopText) {
203206
HighlightedSegments.renderHighlightedInto(componentTextFlow, highlightedTopText);
204207
}
205208

206-
public ObservableList<LatestVersionSearchResult> getDescriptionListViewItems() { return descriptionsListView.getItems(); }
209+
public ObservableList<DescriptionSemanticRow> getDescriptionListViewItems() { return descriptionsListView.getItems(); }
210+
211+
/**
212+
* One row of the expanded description-semantics list.
213+
*
214+
* <p>{@code publicIds} is populated only for rows from a remote search service, whose
215+
* {@code result} carries an absent {@link Latest} because there is no local entity
216+
* behind it. It is the row's only identity in that case; locally sourced rows leave it
217+
* empty and resolve identity from the result's own version.
218+
*
219+
* @param result the search result backing this row
220+
* @param publicIds UUIDs of the matched semantic, for remote rows
221+
*/
222+
public record DescriptionSemanticRow(LatestVersionSearchResult result, List<UUID> publicIds) {
223+
public DescriptionSemanticRow(LatestVersionSearchResult result) {
224+
this(result, List.of());
225+
}
226+
}
207227

208228
@Override
209229
public void updateView() {
@@ -288,7 +308,7 @@ private void updateListViewPrefHeight() {
288308
* *
289309
**************************************************************************/
290310

291-
class DescriptionSemanticListCell extends ListCell<LatestVersionSearchResult> {
311+
class DescriptionSemanticListCell extends ListCell<DescriptionSemanticRow> {
292312
private HBox cellContainer = new HBox();
293313
private TextFlow textFlow = new TextFlow();
294314
private ImageView identicon = new ImageView();
@@ -326,17 +346,32 @@ public DescriptionSemanticListCell() {
326346
}
327347

328348
@Override
329-
protected void updateItem(LatestVersionSearchResult item, boolean empty) {
349+
protected void updateItem(DescriptionSemanticRow item, boolean empty) {
330350
if (item == null || empty) {
331351
setGraphic(null);
352+
identicon.setImage(null);
332353
currentNid = -1;
333354
} else {
334-
item.latestVersion().ifPresent(semanticEntityVersion -> {
355+
// Reset first: cells are recycled, and a remote row resolves neither the
356+
// image nor the nid, so a stale one would otherwise show the previous
357+
// row's icon and open the previous row's semantic on double-click.
358+
identicon.setImage(null);
359+
currentNid = -1;
360+
361+
LatestVersionSearchResult result = item.result();
362+
if (result.latestVersion() != null && result.latestVersion().isPresent()) {
363+
SemanticEntityVersion semanticEntityVersion = result.latestVersion().get();
335364
identicon.setImage(Identicon.generateIdenticonImage(semanticEntityVersion.publicId()));
336365
currentNid = semanticEntityVersion.nid();
337366
setUpDraggable(cellContainer, semanticEntityVersion.entity(), getDragAndDropType(semanticEntityVersion.entity()));
338-
});
339-
HighlightedSegments.renderHighlightedInto(textFlow, item.highlightedString());
367+
} else if (!item.publicIds().isEmpty()) {
368+
// Remote row: no local entity, so the public ID sent with the match is
369+
// the only identity available. Enough to draw the icon; opening and
370+
// dragging still need a real entity and stay disabled.
371+
identicon.setImage(Identicon.generateIdenticonImage(
372+
PublicIds.of(item.publicIds().toArray(new UUID[0]))));
373+
}
374+
HighlightedSegments.renderHighlightedInto(textFlow, result.highlightedString());
340375
setGraphic(cellContainer);
341376
}
342377
}

0 commit comments

Comments
 (0)