JAL-4199 Fix interactive jobs not being stopped
[jalview.git] / src / jalview / ws2 / gui / WebServicesMenuManager.java
index c9b53a9..5fd4734 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;
 
@@ -33,7 +30,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.TaskI;
@@ -41,8 +42,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;
@@ -58,8 +57,6 @@ public class WebServicesMenuManager
     noServicesItem.setEnabled(false);
   }
 
-  private Map<String, WeakReference<TaskI<?>>> interactiveTasks = new HashMap<>();
-
   public WebServicesMenuManager(String name, AlignFrame frame)
   {
     this.frame = frame;
@@ -120,9 +117,13 @@ public class WebServicesMenuManager
 
   private void addOneshotEntries(List<WebService<?>> services, JMenu menu)
   {
-    services.sort(Comparator
-        .<WebService<?>, String> comparing(s -> s.getUrl().toString())
-        .thenComparing(WebService::getName));
+    // Workaround. Comparator methods not working in j2s
+    services.sort((ws1, ws2) -> {
+      var res = ws1.getUrl().toString().compareTo(ws2.getUrl().toString());
+      if (res == 0)
+        res = ws1.getName().compareTo(ws2.getName());
+      return res;
+    });
     URL lastHost = null;
     for (WebService<?> service : services)
     {
@@ -149,18 +150,22 @@ public class WebServicesMenuManager
                 k -> new ArrayList<>())
             .add(action);
       }
-      actionsByCategory.forEach((k, v) -> {
+      for (var entry : actionsByCategory.entrySet())
+      {
+        var category = entry.getKey();
+        var actions = entry.getValue();
         // create submenu named {subcategory} with {service} or use root menu
-        var atMenu = k.isEmpty() ? menu : new JMenu(String.format("%s with %s", k, service.getName()));
+        var atMenu = category.isEmpty() ? menu : new JMenu(String.format("%s with %s", category, service.getName()));
         if (atMenu != menu)
           menu.add(atMenu); // add only if submenu
         // sort actions by name pulling nulls to the front
-        v.sort(Comparator.comparing(
+        actions.sort(Comparator.comparing(
             ActionI::getName, Comparator.nullsFirst(Comparator.naturalOrder())));
-        for (int i = 0; i < v.size(); i++) {
-          addEntriesForAction(v.get(i), atMenu, atMenu == menu);
+        for (int i = 0; i < actions.size(); i++)
+        {
+          addEntriesForAction(actions.get(i), atMenu, atMenu == menu);
         }
-      });
+      }
     }
   }
 
@@ -291,9 +296,12 @@ public class WebServicesMenuManager
     private void buildAlternativesMenu(List<WebService<?>> services)
     {
       var menu = alternativesMenu;
-      services.sort(Comparator
-          .<WebService<?>, String> comparing(s -> s.getUrl().toString())
-          .thenComparing(s -> s.getName()));
+      services.sort((ws1, ws2) -> {
+        var res = ws1.getUrl().toString().compareTo(ws2.getUrl().toString());
+        if (res == 0)
+          res = ws1.getName().compareTo(ws2.getName());
+        return res;
+      });
       URL lastHost = null;
       for (var service : services)
       {
@@ -357,15 +365,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);
 
@@ -384,7 +385,7 @@ public class WebServicesMenuManager
                   lastPreset[0] = null;
                   arguments.clear();
                   arguments.addAll(args);
-                  cancelAndRunInteractive(action, frame.getCurrentView(),
+                  runAction(action, frame.getCurrentView(),
                       arguments, Credentials.empty());
                 }
               });
@@ -401,14 +402,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());
     }
 
@@ -423,24 +424,8 @@ public class WebServicesMenuManager
     }
   }
 
-  private void cancelInteractive(String wsName)
-  {
-    var taskRef = interactiveTasks.get(wsName);
-    if (taskRef != null && taskRef.get() != null)
-      taskRef.get().cancel();
-    interactiveTasks.put(wsName, null);
-  }
-
-  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,
@@ -450,13 +435,35 @@ 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.addTaskEventListener(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;
     }
     throw new IllegalArgumentException(
         String.format("Illegal action type %s", action.getClass().getName()));