JAL-4232 Disable menu items for RNA services for proteins.
[jalview.git] / src / jalview / ws2 / gui / WebServicesMenuManager.java
index 8e2dcee..f9b8c02 100644 (file)
@@ -3,17 +3,14 @@ package jalview.ws2.gui;
 import java.awt.Color;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.lang.ref.WeakReference;
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.TreeMap;
 import java.util.concurrent.CompletionStage;
 
@@ -25,6 +22,7 @@ import javax.swing.ToolTipManager;
 import javax.swing.border.EmptyBorder;
 
 import jalview.bin.Console;
+import jalview.datamodel.AlignmentI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
@@ -34,7 +32,11 @@ import jalview.viewmodel.AlignmentViewport;
 import jalview.ws.params.ArgumentI;
 import jalview.ws.params.ParamDatastoreI;
 import jalview.ws.params.WsParamSetI;
+import jalview.ws2.actions.BaseTask;
+import jalview.ws2.actions.PollingTaskExecutor;
 import jalview.ws2.actions.alignment.AlignmentAction;
+import jalview.ws2.actions.alignment.AlignmentResult;
+import jalview.ws2.actions.annotation.AlignCalcWorkerAdapter;
 import jalview.ws2.actions.annotation.AnnotationAction;
 import jalview.ws2.actions.api.ActionI;
 import jalview.ws2.actions.api.TaskEventListener;
@@ -44,8 +46,6 @@ import jalview.ws2.api.Credentials;
 import jalview.ws2.api.WebService;
 import jalview.ws2.client.api.WebServiceProviderI;
 
-import static java.lang.String.format;
-
 public class WebServicesMenuManager
 {
   private final JMenu menu;
@@ -61,8 +61,6 @@ public class WebServicesMenuManager
     noServicesItem.setEnabled(false);
   }
 
-  private Map<String, WeakReference<TaskI<?>>> interactiveTasks = new HashMap<>();
-
   public WebServicesMenuManager(String name, AlignFrame frame)
   {
     this.frame = frame;
@@ -167,7 +165,8 @@ public class WebServicesMenuManager
         // sort actions by name pulling nulls to the front
         actions.sort(Comparator.comparing(
             ActionI::getName, Comparator.nullsFirst(Comparator.naturalOrder())));
-        for (int i = 0; i < actions.size(); i++) {
+        for (int i = 0; i < actions.size(); i++)
+        {
           addEntriesForAction(actions.get(i), atMenu, atMenu == menu);
         }
       }
@@ -176,6 +175,7 @@ public class WebServicesMenuManager
 
   private void addEntriesForAction(ActionI<?> action, JMenu menu, boolean isTopLevel)
   {
+    var enabled = isActionEnabled(action);
     var service = action.getWebService();
     String itemName;
     if (isTopLevel)
@@ -197,6 +197,7 @@ public class WebServicesMenuManager
       if (datastore.hasParameters() || datastore.hasPresets())
         text += " with defaults";
       JMenuItem item = new JMenuItem(text);
+      item.setEnabled(enabled);
       item.addActionListener(e -> {
         runAction(action, frame.getCurrentView(), Collections.emptyList(),
             Credentials.empty());
@@ -206,6 +207,7 @@ public class WebServicesMenuManager
     if (datastore.hasParameters())
     {
       JMenuItem item = new JMenuItem("Edit settings and run...");
+      item.setEnabled(enabled);
       item.addActionListener(e -> {
         openEditParamsDialog(datastore, null, null).thenAccept(args -> {
           if (args != null)
@@ -219,6 +221,7 @@ public class WebServicesMenuManager
     {
       final var presetsMenu = new JMenu(MessageManager.formatMessage(
           "label.run_with_preset_params", service.getName()));
+      presetsMenu.setEnabled(enabled);
       final int dismissDelay = ToolTipManager.sharedInstance()
           .getDismissDelay();
       final int QUICK_TOOLTIP = 1500;
@@ -343,6 +346,7 @@ public class WebServicesMenuManager
           for (ActionI<?> action : actions)
           {
             var item = new JMenuItem(action.getFullName());
+            item.setEnabled(isActionEnabled(action));
             item.addActionListener(e -> setAlternative(action));
             atMenu.add(item);
           }
@@ -370,15 +374,8 @@ public class WebServicesMenuManager
         serviceItem.removeActionListener(l);
       WebService<?> service = action.getWebService();
       serviceItem.addActionListener(e -> {
-        if (serviceItem.getState())
-        {
-          cancelAndRunInteractive(action, frame.getCurrentView(), arguments,
-              Credentials.empty());
-        }
-        else
-        {
-          cancelInteractive(service.getName());
-        }
+        runAction(action, frame.getCurrentView(), arguments,
+            Credentials.empty());
       });
       serviceItem.setSelected(true);
 
@@ -397,7 +394,7 @@ public class WebServicesMenuManager
                   lastPreset[0] = null;
                   arguments.clear();
                   arguments.addAll(args);
-                  cancelAndRunInteractive(action, frame.getCurrentView(),
+                  runAction(action, frame.getCurrentView(),
                       arguments, Credentials.empty());
                 }
               });
@@ -414,14 +411,14 @@ public class WebServicesMenuManager
           var item = new JMenuItem(preset.getName());
           item.addActionListener(e -> {
             lastPreset[0] = preset;
-            cancelAndRunInteractive(action, frame.getCurrentView(),
+            runAction(action, frame.getCurrentView(),
                 preset.getArguments(), Credentials.empty());
           });
           presetsMenu.add(item);
         }
       }
 
-      cancelAndRunInteractive(action, frame.getCurrentView(), arguments,
+      runAction(action, frame.getCurrentView(), arguments,
           Credentials.empty());
     }
 
@@ -436,24 +433,14 @@ public class WebServicesMenuManager
     }
   }
 
-  private void cancelInteractive(String wsName)
+  private boolean isActionEnabled(ActionI<?> action)
   {
-    var taskRef = interactiveTasks.get(wsName);
-    if (taskRef != null && taskRef.get() != null)
-      taskRef.get().cancel();
-    interactiveTasks.put(wsName, null);
+    var isNa = frame.getViewport().getAlignment().isNucleotide();
+    return ((isNa && action.doAllowNucleotide()) ||
+        (!isNa && action.doAllowProtein()));
   }
 
-  private void cancelAndRunInteractive(ActionI<?> action,
-      AlignmentViewport viewport, List<ArgumentI> args, Credentials credentials)
-  {
-    var wsName = action.getWebService().getName();
-    cancelInteractive(wsName);
-    var task = runAction(action, viewport, args, credentials);
-    interactiveTasks.put(wsName, new WeakReference<>(task));
-  }
-
-  private TaskI<?> runAction(ActionI<?> action, AlignmentViewport viewport,
+  private void runAction(ActionI<?> action, AlignmentViewport viewport,
       List<ArgumentI> args, Credentials credentials)
   {
     // casting and instance checks can be avoided with some effort,
@@ -463,25 +450,53 @@ public class WebServicesMenuManager
       // TODO: test if selection contains enough sequences
       var _action = (AlignmentAction) action;
       var handler = new AlignmentServiceGuiHandler(_action, frame);
-      return _action.perform(viewport, args, credentials, handler);
+      BaseTask<?, AlignmentResult> task = _action.createTask(viewport, args, credentials);
+      var executor = PollingTaskExecutor.fromPool(viewport.getServiceExecutor());
+      task.addTaskEventListener(handler);
+      var future = executor.submit(task);
+      task.setCancelAction(() -> { future.cancel(true); });
+      return;
     }
     if (action instanceof AnnotationAction)
     {
+      var calcManager = viewport.getCalcManager();
+
       var _action = (AnnotationAction) action;
+      var worker = new AlignCalcWorkerAdapter(viewport, frame.alignPanel,
+          _action, args, credentials);
       var handler = new AnnotationServiceGuiHandler(_action, frame);
-      return _action.perform(viewport, args, credentials, handler);
+      worker.setWorkerListener(handler);
+      for (var w : calcManager.getWorkers())
+      {
+        if (worker.getCalcName() != null && worker.getCalcName().equals(w.getCalcName()))
+        {
+          calcManager.cancelWorker(w);
+          calcManager.removeWorker(w);
+        }
+      }
+      if (action.getWebService().isInteractive())
+        calcManager.registerWorker(worker);
+      else
+        calcManager.startWorker(worker);
+      return;
     }
     if (action instanceof PhmmerAction)
     {
       var _action = (PhmmerAction) action;
-      var handler = new SearchServiceGuiHandler(frame);
-      return _action.perform(viewport, args, credentials, handler);
+      var handler = new SearchServiceGuiHandler(_action, frame);
+      TaskI<AlignmentI> task = _action.createTask(viewport, args, credentials);
+      var executor = PollingTaskExecutor.fromPool(viewport.getServiceExecutor());
+      task.addTaskEventListener(handler);
+      _action.perform(viewport, args, credentials, handler);
+      return;
     }
     Console.warn(String.format(
             "No known handler for action type %s. All output will be discarded.",
             action.getClass().getName()));
-    return action.perform(viewport, args, credentials,
-            TaskEventListener.nullListener());
+    var task = action.createTask(viewport, args, credentials);
+    task.addTaskEventListener(TaskEventListener.nullListener());
+    PollingTaskExecutor.fromPool(viewport.getServiceExecutor())
+      .submit(task);
   }
 
   private static CompletionStage<List<ArgumentI>> openEditParamsDialog(