JAL-4199 Remove viewport reference from AnnotationTask
[jalview.git] / src / jalview / ws2 / actions / annotation / AlignCalcWorkerAdapter.java
index 7a58a89..cf693bc 100644 (file)
@@ -1,9 +1,12 @@
 package jalview.ws2.actions.annotation;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.function.Consumer;
 
+import jalview.analysis.AlignmentAnnotationUtils;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
 import jalview.api.PollableAlignCalcWorkerI;
@@ -17,6 +20,10 @@ import jalview.ws2.api.Credentials;
 
 public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableAlignCalcWorkerI
 {
+  private static int calcCount = 0;
+
+  private final int calcNumber = calcCount++;
+
   private final AnnotationAction action;
 
   private final List<ArgumentI> args;
@@ -25,21 +32,39 @@ public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableA
 
   private TaskI<AnnotationResult> currentTask = null;
 
-  private TaskEventListener<AnnotationResult> internalTaskListener = new TaskEventListener<>()
+  private TaskEventListener<AnnotationResult> taskListener = new TaskEventListener<>()
   {
     @Override
     public void taskCompleted(TaskI source, AnnotationResult result)
     {
-      updateOurAnnots(result.getAnnotations());
+      int graphGroup = alignViewport.getAlignment().getLastGraphGroup();
+      List<AlignmentAnnotation> annotations = new ArrayList<>();
+      for (AlignmentAnnotation ala : result.getAnnotations())
+      {
+        if (ala.graphGroup > 0)
+          ala.graphGroup += graphGroup;
+        var newAnnot = alignViewport.getAlignment()
+            .updateFromOrCopyAnnotation(ala);
+        if (ala.sequenceRef != null)
+        {
+          ala.sequenceRef.addAlignmentAnnotation(newAnnot);
+          newAnnot.adjustForAlignment();
+          AlignmentAnnotationUtils.replaceAnnotationOnAlignmentWith(
+              newAnnot, newAnnot.label, newAnnot.getCalcId());
+        }
+        annotations.add(newAnnot);
+      }
+      updateOurAnnots(annotations);
+      listener.workerHasResult(
+          AlignCalcWorkerAdapter.this,
+          new AnnotationResult(
+              annotations,
+              result.transferFeatures,
+              result.featureColours,
+              result.featureFilters));
     }
   };
 
-  // task event listeners managed by this worker, passed to each creates task
-  private List<TaskEventListener<AnnotationResult>> taskListeners = new CopyOnWriteArrayList<>();
-  {
-    taskListeners.add(internalTaskListener);
-  }
-
   public AlignCalcWorkerAdapter(AlignViewportI alignViewport, AlignmentViewPanel alignPanel, AnnotationAction action,
       List<ArgumentI> args, Credentials credentials)
   {
@@ -70,7 +95,6 @@ public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableA
         alignment.deleteAnnotation(annotation);
     for (AlignmentAnnotation annotation : newAnnots)
       alignment.validateAnnotation(annotation);
-    ap.adjustAnnotationHeight();
     ourAnnots = Collections.synchronizedList(newAnnots);
   }
 
@@ -84,9 +108,9 @@ public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableA
       throw new IllegalStateException("Starting calculation for closed viewport");
     }
     currentTask = action.createTask(alignViewport, args, credentials);
-    for (var listener : taskListeners)
-      currentTask.addTaskEventListener(listener);
+    currentTask.addTaskEventListener(taskListener);
     currentTask.init();
+    listener.workerStarted(this);
   }
 
   @Override
@@ -103,8 +127,8 @@ public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableA
       currentTask.cancel();
     } finally
     {
-      for (var listener : taskListeners)
-        currentTask.removeTaskEventListener(listener);
+      currentTask.removeTaskEventListener(taskListener);
+      listener.workerStopped(this);
     }
   }
 
@@ -118,28 +142,41 @@ public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableA
     {
     } finally
     {
-      for (var listener : taskListeners)
-        currentTask.removeTaskEventListener(listener);
+      currentTask.removeTaskEventListener(taskListener);
+      listener.workerStopped(this);
     }
   }
 
-  public void addTaskEventListener(TaskEventListener<AnnotationResult> listener)
+  @Override
+  public String toString()
   {
-    taskListeners.add(listener);
-    if (currentTask != null)
-      currentTask.addTaskEventListener(listener);
+    return "AlignCalcWorkerAdapter-" + calcNumber + " for " + getCalcName();
   }
 
-  public void removeTaskEventListener(TaskEventListener<AnnotationResult> listener)
+  public interface WorkerListener extends java.util.EventListener
   {
-    taskListeners.remove(listener);
-    if (currentTask != null)
-      currentTask.removeTaskEventListener(listener);
+    default void workerStarted(AlignCalcWorkerAdapter source)
+    {
+    };
+
+    default void workerStopped(AlignCalcWorkerAdapter source)
+    {
+    };
+
+    default void workerHasResult(AlignCalcWorkerAdapter source, AnnotationResult result)
+    {
+    };
+
+    static final WorkerListener NULL_LISTENER = new WorkerListener()
+    {
+    };
   }
 
-  @Override
-  public String toString()
+  private WorkerListener listener = WorkerListener.NULL_LISTENER;
+  
+  public void setWorkerListener(WorkerListener listener)
   {
-    return "AlignCalcWorkerAdapter for " + getCalcName();
+    if (listener == null) listener = WorkerListener.NULL_LISTENER;
+    this.listener = listener;
   }
 }