// License: GPL. For details, see LICENSE file. package org.wikipedia.gui; import java.awt.Component; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.gui.util.GuiHelper; import org.openstreetmap.josm.tools.Utils; import org.wikipedia.WikipediaApp; import org.wikipedia.data.WikidataEntry; public class WikidataTagCellRenderer extends DefaultTableCellRenderer { final Map<String, CompletableFuture<String>> labelCache = new ConcurrentHashMap<>(); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (column != 1 || !(value instanceof Map<?, ?> && ((Map<?, ?>) value).size() == 1)) { return null; } final String key = table.getValueAt(row, 0).toString(); if (!("wikidata".equals(key) || (key != null && key.endsWith(":wikidata")))) { return null; } final String id = ((Map<?, ?>) value).keySet().iterator().next().toString(); final JLabel component = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (WikipediaApp.WIKIDATA_PATTERN.matcher(id).matches()) { return renderValues(Collections.singleton(id), table, component); } else if (id.contains(";")) { final List<String> ids = Arrays.asList(id.split("\\s*;\\s*")); if (ids.stream().allMatch(i -> WikipediaApp.WIKIDATA_PATTERN.matcher(i).matches())) { return renderValues(ids, table, component); } } return null; } protected JLabel renderValues(Collection<String> ids, JTable table, JLabel component) { ids.forEach(id -> labelCache.computeIfAbsent(id, x -> CompletableFuture.supplyAsync(() -> WikipediaApp.getLabelForWikidata(x, Locale.getDefault()))) ); final Collection<String> texts = new ArrayList<>(ids.size()); for (String id : ids) { if (!labelCache.get(id).isDone()) { labelCache.get(id).thenRun(() -> GuiHelper.runInEDT(table::repaint)); return null; } final String label; try { label = labelCache.get(id).get(); } catch (InterruptedException | ExecutionException e) { Main.warn("Could not fetch Wikidata label for " + id); Main.warn(e); return null; } if (label == null) { return null; } texts.add(WikidataEntry.getLabelText(id, label)); } component.setText("<html>" + texts.stream().collect(Collectors.joining("; "))); component.setToolTipText("<html>" + Utils.joinAsHtmlUnorderedList(texts)); return component; } }