From 9c661277be76b954869d645e121d39224713e7b9 Mon Sep 17 00:00:00 2001 From: Mateusz Warowny Date: Wed, 20 Oct 2021 18:05:05 +0200 Subject: [PATCH] JAL-3878 Create WebServiceMenuBuilder which will replace PreferredServiceRegistry --- src/jalview/gui/AlignFrame.java | 35 ++--- src/jalview/gui/WebServicesMenuBuilder.java | 201 +++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 26 deletions(-) create mode 100644 src/jalview/gui/WebServicesMenuBuilder.java diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 9fb6ee5..3d00450 100644 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -4726,35 +4726,18 @@ public class AlignFrame extends GAlignFrame } } - private void buildWebServicesMenu(WebServiceDiscoverer discoverer, JMenu menu) + private void buildWebServicesMenu(WebServiceDiscoverer discoverer, final JMenu menu) { if (discoverer.hasServices()) { - var services = new ArrayList<>(discoverer.getServices()); - services.sort(Comparator - .comparing(o -> o.getHostName()) - .thenComparing(o -> o.getName())); - Map lastHostForOperation = new HashMap<>(); - for (final WebServiceI service : services) - { - var host = service.getHostName(); - for (Operation op : service.getOperations()) - { - JMenu atpoint = JvSwingUtils.findOrCreateMenu(menu, op.getTypeName()); - String lastHost = lastHostForOperation.get(op.getTypeName()); - if (lastHost != host) { - if (lastHost != null) - atpoint.addSeparator(); - var menuItem = new JMenuItem(host); - menuItem.setForeground(Color.blue); - menuItem.addActionListener(e -> Desktop.showUrl(host)); - atpoint.add(menuItem); - lastHostForOperation.put(op.getTypeName(), host); - } - atpoint.addSeparator(); - op.getMenuBuilder().buildMenu(atpoint, this); - } - } + var builder = new WebServicesMenuBuilder(); + for (var service : discoverer.getServices()) + builder.addAllOperations(service.getOperations()); + builder.addSelectedHostChangeListener((name, op) -> { + menu.removeAll(); + builder.buildMenu(menu, this); + }); + builder.buildMenu(menu, this); } if (discoverer.isRunning()) { diff --git a/src/jalview/gui/WebServicesMenuBuilder.java b/src/jalview/gui/WebServicesMenuBuilder.java new file mode 100644 index 0000000..2a17bf4 --- /dev/null +++ b/src/jalview/gui/WebServicesMenuBuilder.java @@ -0,0 +1,201 @@ +package jalview.gui; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.swing.JMenu; +import javax.swing.JMenuItem; + +import jalview.gui.AlignFrame; +import jalview.gui.Desktop; +import jalview.util.MessageManager; +import jalview.ws2.WebServiceI; +import jalview.ws2.operations.Operation; + +public class WebServicesMenuBuilder +{ + @FunctionalInterface + public static interface SelectedHostChangeListener + { + public void selectedHostChanged(String opName, Operation op); + } + + List operations = new ArrayList<>(); + + /** + * Mapping of service name to the preferred url this service is hosted at. + */ + Map selectedHost = new HashMap<>(); + + public void addOperation(Operation op) + { + operations.add(op); + } + + public void addAllOperations(Collection operations) + { + this.operations.addAll(operations); + } + + public void removeOperation(Operation op) + { + operations.remove(op); + } + + public void clearOperations() + { + operations.clear(); + } + + public void buildMenu(JMenu atMenu, AlignFrame frame) + { + Map> oneshotOperations = new HashMap<>(); + Map> interactiveOperations = new HashMap<>(); + for (Operation op : operations) + { + var mapping = op.isInteractive() ? interactiveOperations : oneshotOperations; + if (!mapping.containsKey(op.getTypeName())) + mapping.put(op.getTypeName(), new ArrayList<>()); + mapping.get(op.getTypeName()).add(op); + } + var keysSet = new HashSet<>(oneshotOperations.keySet()); + keysSet.addAll(interactiveOperations.keySet()); + var keys = new ArrayList<>(keysSet); + keys.sort(Comparator.naturalOrder()); + for (String opType : keys) + { + var submenu = new JMenu(opType); + var oneshot = oneshotOperations.get(opType); + if (oneshot != null) + addOneshotOperations(oneshot, submenu, frame); + var interactive = interactiveOperations.get(opType); + if (interactive != null) + { + if (oneshot != null) + submenu.addSeparator(); + addInteractiveOperations(interactive, submenu, frame); + } + atMenu.add(submenu); + } + } + + private void addOneshotOperations(List operations, JMenu submenu, + AlignFrame frame) + { + operations = new ArrayList<>(operations); + operations.sort(Comparator + .comparing(o -> o.getHostName()) + .thenComparing(o -> o.getName())); + String lastHost = null; + for (final Operation op : operations) + { + String host = op.getHostName(); + if (lastHost != host) + { + if (lastHost != null) + submenu.addSeparator(); + var menuItem = new JMenuItem(host); + menuItem.setForeground(Color.blue); + menuItem.addActionListener(e -> Desktop.showUrl(host)); + submenu.add(menuItem); + lastHost = host; + } + submenu.addSeparator(); + op.getMenuBuilder().buildMenu(submenu, frame); + } + } + + private void addInteractiveOperations(List operations, + JMenu submenu, AlignFrame frame) + { + Map> groupedOperations = new HashMap<>(); + for (Operation op : operations) + { + if (!groupedOperations.containsKey(op.getName())) + groupedOperations.put(op.getName(), new ArrayList<>()); + groupedOperations.get(op.getName()).add(op); + } + var keys = new ArrayList<>(groupedOperations.keySet()); + keys.sort(Comparator.naturalOrder()); + for (String opName : keys) + { + var ops = groupedOperations.get(opName); + var selectedHost = getSelectedHost(opName); + Operation selectedOperation = null; + for (var op : ops) + { + if (op.getHostName().equals(selectedHost)) + { + selectedOperation = op; + break; + } + } + if (selectedOperation == null || selectedHost == null) + selectedOperation = ops.get(0); + { + final var hostName = selectedOperation.getHostName(); + var hostItem = new JMenuItem(hostName); + hostItem.setForeground(Color.blue); + hostItem.addActionListener(e -> Desktop.showUrl(hostName)); + submenu.add(hostItem); + } + selectedOperation.getMenuBuilder().buildMenu(submenu, frame); + if (ops.size() > 1) + { + JMenuItem alternatesMenu = new JMenuItem(MessageManager.getString("label.switch_server")); + submenu.add(alternatesMenu); + alternatesMenu.setToolTipText(JvSwingUtils.wrapTooltip(false, + MessageManager.getString("label.choose_jabaws_server"))); + for (final Operation op : ops) + { + if (op == selectedOperation) continue; + var hostItem = new JMenuItem(op.getHostName()); + hostItem.setForeground(Color.blue); + hostItem.addActionListener(e -> { + setSelectedHost(op.getName(), op.getHostName()); + fireSelectedHostChanged(op.getName(), op); + }); + submenu.add(hostItem); + } + } + } + } + + public String getSelectedHost(String serviceName) + { + return selectedHost.getOrDefault(serviceName, null); + } + + public void setSelectedHost(WebServiceI service) + { + setSelectedHost(service.getName(), service.getHostName()); + } + + public void setSelectedHost(String serviceName, String hostName) + { + selectedHost.put(serviceName, hostName); + } + + List hostChangeListeners = new CopyOnWriteArrayList<>(); + + public void addSelectedHostChangeListener(SelectedHostChangeListener l) + { + hostChangeListeners.add(l); + } + + private void fireSelectedHostChanged(String opName, Operation op) + { + for (var listener : hostChangeListeners) + { + listener.selectedHostChanged(opName, op); + } + } + +} -- 1.7.10.2