JAL-3878 Rename web service worker to more generic pollable task.
[jalview.git] / src / jalview / ws2 / operations / AlignmentOperation.java
index 6a1baf2..5b2f554 100644 (file)
@@ -33,6 +33,7 @@ import jalview.datamodel.SequenceI;
 import jalview.datamodel.Sequence;
 import jalview.gui.AlignFrame;
 import jalview.gui.AlignViewport;
+import jalview.gui.Desktop;
 import jalview.gui.JvSwingUtils;
 import jalview.gui.WebserviceInfo;
 import jalview.gui.WsJobParameters;
@@ -44,7 +45,7 @@ import jalview.ws2.MenuEntryProviderI;
 import jalview.ws2.ResultSupplier;
 import jalview.ws2.WSJob;
 import jalview.ws2.WSJobStatus;
-import jalview.ws2.WebServiceExecutor;
+import jalview.ws2.PollingTaskExecutor;
 import jalview.ws2.WebServiceI;
 import jalview.ws2.WebServiceInfoUpdater;
 import jalview.ws2.WebServiceWorkerI;
@@ -69,12 +70,24 @@ public class AlignmentOperation implements Operation
   }
 
   @Override
+  public String getName()
+  {
+    return service.getName();
+  }
+
+  @Override
   public String getTypeName()
   {
     return "Multiple Sequence Alignment";
   }
 
   @Override
+  public String getHostName()
+  {
+    return service.getHostName();
+  }
+
+  @Override
   public int getMinSequences()
   {
     return 2;
@@ -106,6 +119,12 @@ public class AlignmentOperation implements Operation
   }
 
   @Override
+  public boolean isInteractive()
+  {
+    return false;
+  }
+
+  @Override
   public MenuEntryProviderI getMenuBuilder()
   {
     return this::buildMenu;
@@ -137,22 +156,22 @@ public class AlignmentOperation implements Operation
     final String action = submitGaps ? "Align" : "Realign";
     final var calcName = service.getName();
 
-    final AlignmentView msa = frame.gatherSequencesForAlignment();
-    final AlignViewport viewport = frame.getViewport();
-    final AlignmentI alignment = frame.getViewport().getAlignment();
     String title = frame.getTitle();
-    WebServiceExecutor executor = frame.getViewport().getWSExecutor();
+    PollingTaskExecutor executor = frame.getViewport().getWSExecutor();
     {
       var item = new JMenuItem(MessageManager.formatMessage(
               "label.calcname_with_default_settings", calcName));
       item.setToolTipText(MessageManager
               .formatMessage("label.action_with_default_settings", action));
       item.addActionListener((event) -> {
+        final AlignmentView msa = frame.gatherSequencesForAlignment();
+        final AlignViewport viewport = frame.getViewport();
+        final AlignmentI alignment = frame.getViewport().getAlignment();
         if (msa != null)
         {
           WebServiceWorkerI worker = new AlignmentWorker(msa,
-                  Collections.emptyList(), title, submitGaps, true,
-                  alignment, viewport);
+              Collections.emptyList(), title, submitGaps, true,
+              alignment, viewport);
           executor.submit(worker);
         }
       });
@@ -166,18 +185,21 @@ public class AlignmentOperation implements Operation
       item.setToolTipText(MessageManager.getString(
               "label.view_and_change_parameters_before_alignment"));
       item.addActionListener((event) -> {
+        final AlignmentView msa = frame.gatherSequencesForAlignment();
+        final AlignViewport viewport = frame.getViewport();
+        final AlignmentI alignment = frame.getViewport().getAlignment();
         if (msa != null)
         {
           openEditParamsDialog(service, null, null)
-                  .thenAcceptAsync((arguments) -> {
-                    if (arguments != null)
-                    {
-                      WebServiceWorkerI worker = new AlignmentWorker(msa,
-                              arguments, title, submitGaps, true, alignment,
-                              viewport);
-                      executor.submit(worker);
-                    }
-                  });
+              .thenAcceptAsync((arguments) -> {
+                if (arguments != null)
+                {
+                  WebServiceWorkerI worker = new AlignmentWorker(msa,
+                      arguments, title, submitGaps, true, alignment,
+                      viewport);
+                  executor.submit(worker);
+                }
+              });
         }
       });
       parent.add(item);
@@ -216,11 +238,14 @@ public class AlignmentOperation implements Operation
                         preset.getDescription()));
         item.setToolTipText(tooltip);
         item.addActionListener((event) -> {
+          final AlignmentView msa = frame.gatherSequencesForAlignment();
+          final AlignViewport viewport = frame.getViewport();
+          final AlignmentI alignment = frame.getViewport().getAlignment();
           if (msa != null)
           {
             WebServiceWorkerI worker = new AlignmentWorker(msa,
-                    preset.getArguments(), title, submitGaps, true,
-                    alignment, viewport);
+                preset.getArguments(), title, submitGaps, true,
+                alignment, viewport);
             executor.submit(worker);
           }
         });
@@ -277,6 +302,8 @@ public class AlignmentOperation implements Operation
 
     private final AlignmentI dataset;
 
+    private final AlignViewport viewport;
+
     private final List<AlignedCodonFrame> codonFrame = new ArrayList<>();
 
     private List<ArgumentI> args = Collections.emptyList();
@@ -312,6 +339,7 @@ public class AlignmentOperation implements Operation
       this.alnTitle = alnTitle;
       this.submitGaps = submitGaps;
       this.preserveOrder = preserveOrder;
+      this.viewport = viewport;
       this.gapCharacter = viewport.getGapCharacter();
 
       String panelInfo = String.format("%s using service hosted at %s%n%s",
@@ -339,8 +367,9 @@ public class AlignmentOperation implements Operation
     }
 
     @Override
-    public void startJobs() throws IOException
+    public void start() throws IOException
     {
+      Cache.log.info(format("Starting new %s job.", service.getName()));
       String outputHeader = String.format("%s of %s%nJob details%n",
               submitGaps ? "Re-alignment" : "Alignment", alnTitle);
       SequenceI[][] conmsa = msa.getVisibleContigs('-');
@@ -357,7 +386,7 @@ public class AlignmentOperation implements Operation
         WSJob job = new WSJob(service.getProviderName(), service.getName(),
                 service.getHostName());
         job.setJobNum(wsInfo.addJobPane());
-        if (conmsa.length > 0)
+        if (conmsa.length > 1)
         {
           wsInfo.setProgressName(String.format("region %d", i),
                   job.getJobNum());
@@ -418,12 +447,12 @@ public class AlignmentOperation implements Operation
     }
 
     @Override
-    public boolean pollJobs()
+    public boolean poll()
     {
       boolean done = true;
       for (WSJob job : getJobs())
       {
-        if (!job.getStatus().isDone())
+        if (!job.getStatus().isDone() && !job.getStatus().isFailed())
         {
           Cache.log.debug(format("Polling job %s.", job));
           try
@@ -454,7 +483,7 @@ public class AlignmentOperation implements Operation
           Cache.log.debug(
                   format("Job %s status is %s", job, job.getStatus()));
         }
-        done &= job.getStatus().isDone();
+        done &= job.getStatus().isDone() || job.getStatus().isFailed();
       }
       updateWSInfoGlobalStatus();
       return done;
@@ -498,9 +527,11 @@ public class AlignmentOperation implements Operation
       Map<Long, AlignmentI> results = new LinkedHashMap<>();
       for (WSJob job : getJobs())
       {
+        if (job.getStatus().isFailed())
+          continue;
         try
         {
-          AlignmentI alignment = supplier.getResult(job);
+          AlignmentI alignment = supplier.getResult(job, dataset.getSequences(), viewport);
           if (alignment != null)
           {
             results.put(job.getUid(), alignment);
@@ -518,8 +549,9 @@ public class AlignmentOperation implements Operation
       updateWSInfoGlobalStatus();
       if (results.size() > 0)
       {
-        wsInfo.showResultsNewFrame
-                .addActionListener(evt -> displayResults(results));
+        OutputWrapper out = prepareOutput(results);
+        wsInfo.showResultsNewFrame.addActionListener(evt -> displayNewFrame(
+                new Alignment(out.aln), out.alorders, out.hidden));
         wsInfo.setResultsReady();
       }
       else
@@ -529,7 +561,24 @@ public class AlignmentOperation implements Operation
       wsInfo.removeProgressBar(progbarId);
     }
 
-    private void displayResults(Map<Long, AlignmentI> alignments)
+    private class OutputWrapper
+    {
+      AlignmentI aln;
+
+      List<AlignmentOrder> alorders;
+
+      HiddenColumns hidden;
+
+      OutputWrapper(AlignmentI aln, List<AlignmentOrder> alorders,
+              HiddenColumns hidden)
+      {
+        this.aln = aln;
+        this.alorders = alorders;
+        this.hidden = hidden;
+      }
+    }
+
+    private OutputWrapper prepareOutput(Map<Long, AlignmentI> alignments)
     {
       List<AlignmentOrder> alorders = new ArrayList<>();
       SequenceI[][] results = new SequenceI[jobs.size()][];
@@ -538,8 +587,8 @@ public class AlignmentOperation implements Operation
       {
         WSJob job = jobs.get(i);
         AlignmentI aln = alignments.get(job.getUid());
-        if (aln != null)
-        { // equivalent of job.hasResults()
+        if (aln != null) // equivalent of job.hasResults()
+        {
           /* Get the alignment including any empty sequences in the original
            * order with original ids. */
           JobInput input = inputs.get(job.getUid());
@@ -571,6 +620,7 @@ public class AlignmentOperation implements Operation
           // temporary workaround for deuniquify
           @SuppressWarnings({ "rawtypes", "unchecked" })
           Hashtable names = new Hashtable(input.sequenceNames);
+          // FIXME first call to deuniquify alters original alignment
           SeqsetUtils.deuniquify(names, result);
           alorders.add(msaOrder);
           results[i] = result;
@@ -597,8 +647,8 @@ public class AlignmentOperation implements Operation
         aln.setDataset(dataset);
 
       propagateDatasetMappings(aln);
-
-      displayNewFrame(aln, alorders, hidden);
+      return new OutputWrapper(aln, alorders, hidden);
+      // displayNewFrame(aln, alorders, hidden);
     }
 
     /*
@@ -654,6 +704,9 @@ public class AlignmentOperation implements Operation
        * If alignment was requested from one half of a SplitFrame, show in a
        * SplitFrame with the other pane similarly aligned.
        */
+
+      Desktop.addInternalFrame(frame, alnTitle, AlignFrame.DEFAULT_WIDTH,
+              AlignFrame.DEFAULT_HEIGHT);
     }
 
     private List<List<Integer>> sortOrders(List<?> alorders)
@@ -742,8 +795,8 @@ public class AlignmentOperation implements Operation
         }
         else
         {
-          String seqString = null;
-          if (seq.getEnd() >= seq.getStart()) // is it ever false?
+          String seqString = "";
+          if (seq.getEnd() >= seq.getStart())  // true if gaps only
           {
             seqString = seq.getSequenceAsString();
             if (!submitGaps)