}
}
- 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
- .<WebServiceI, String>comparing(o -> o.getHostName())
- .<String>thenComparing(o -> o.getName()));
- Map<String, String> 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())
{
--- /dev/null
+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<Operation> operations = new ArrayList<>();
+
+ /**
+ * Mapping of service name to the preferred url this service is hosted at.
+ */
+ Map<String, String> selectedHost = new HashMap<>();
+
+ public void addOperation(Operation op)
+ {
+ operations.add(op);
+ }
+
+ public void addAllOperations(Collection<Operation> 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<String, List<Operation>> oneshotOperations = new HashMap<>();
+ Map<String, List<Operation>> 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.<String>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<Operation> operations, JMenu submenu,
+ AlignFrame frame)
+ {
+ operations = new ArrayList<>(operations);
+ operations.sort(Comparator
+ .<Operation, String>comparing(o -> o.getHostName())
+ .<String>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<Operation> operations,
+ JMenu submenu, AlignFrame frame)
+ {
+ Map<String, List<Operation>> 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.<String>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<SelectedHostChangeListener> 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);
+ }
+ }
+
+}