JAL-4199 Implement AlignCalcWorker adapter for annot tasks
authorMateusz Warowny <mmzwarowny@dundee.ac.uk>
Tue, 4 Jul 2023 11:31:25 +0000 (13:31 +0200)
committerMateusz Warowny <mmzwarowny@dundee.ac.uk>
Wed, 12 Jul 2023 14:25:05 +0000 (16:25 +0200)
src/jalview/ws2/actions/annotation/AlignCalcWorkerAdapter.java [new file with mode: 0644]

diff --git a/src/jalview/ws2/actions/annotation/AlignCalcWorkerAdapter.java b/src/jalview/ws2/actions/annotation/AlignCalcWorkerAdapter.java
new file mode 100644 (file)
index 0000000..7e8724a
--- /dev/null
@@ -0,0 +1,138 @@
+package jalview.ws2.actions.annotation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.PollableAlignCalcWorkerI;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
+import jalview.workers.AlignCalcWorker;
+import jalview.ws.params.ArgumentI;
+import jalview.ws2.actions.alignment.AlignmentResult;
+import jalview.ws2.actions.api.JobI;
+import jalview.ws2.actions.api.TaskEventListener;
+import jalview.ws2.actions.api.TaskI;
+import jalview.ws2.api.Credentials;
+import jalview.ws2.api.JobStatus;
+
+public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableAlignCalcWorkerI
+{
+  private final AnnotationAction action;
+
+  private final List<ArgumentI> args;
+
+  private final Credentials credentials;
+
+  private TaskI<AnnotationResult> currentTask = null;
+
+  private TaskEventListener<AnnotationResult> internalTaskListener = new TaskEventListener<>()
+  {
+    @Override
+    public void taskCompleted(TaskI source, AnnotationResult result)
+    {
+      updateOurAnnots(result.getAnnotations());
+    }
+  };
+
+  // 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)
+  {
+    super(alignViewport, alignPanel);
+    this.action = action;
+    this.args = args;
+    this.credentials = credentials;
+  }
+
+  @Override
+  public void updateAnnotation()
+  {
+
+  }
+
+  private void updateOurAnnots(List<AlignmentAnnotation> newAnnots)
+  {
+    List<AlignmentAnnotation> oldAnnots = ourAnnots != null ? ourAnnots : List.of();
+    AlignmentI alignment = alignViewport.getAlignment();
+    for (AlignmentAnnotation annotation : oldAnnots)
+      if (!newAnnots.contains(annotation))
+        alignment.deleteAnnotation(annotation);
+    for (AlignmentAnnotation annotation : newAnnots)
+      alignment.validateAnnotation(annotation);
+    ap.adjustAnnotationHeight();
+    ourAnnots = Collections.synchronizedList(newAnnots);
+  }
+
+  @Override
+  public synchronized void startUp() throws Throwable
+  {
+    if (alignViewport.isClosed())
+    {
+      calcMan.disableWorker(this);
+      abortAndDestroy();
+      throw new IllegalStateException("Starting calculation for closed viewport");
+    }
+    currentTask = action.createTask(alignViewport, args, credentials);
+    for (var listener : taskListeners)
+      currentTask.addTaskEventListener(listener);
+    currentTask.init();
+  }
+
+  @Override
+  public boolean poll() throws Throwable
+  {
+    return currentTask.poll();
+  }
+
+  @Override
+  public synchronized void cancel()
+  {
+    try
+    {
+      currentTask.cancel();
+    } finally
+    {
+      for (var listener : taskListeners)
+        currentTask.removeTaskEventListener(listener);
+    }
+  }
+
+  @Override
+  public synchronized void done()
+  {
+    try
+    {
+      currentTask.complete();
+    } catch (Exception e)
+    {
+    } finally
+    {
+      for (var listener : taskListeners)
+        currentTask.removeTaskEventListener(listener);
+    }
+  }
+
+  public void addTaskEventListener(TaskEventListener<AnnotationResult> listener)
+  {
+    taskListeners.add(listener);
+    if (currentTask != null)
+      currentTask.addTaskEventListener(listener);
+  }
+
+  public void removeTaskEventListener(TaskEventListener<AnnotationResult> listener)
+  {
+    taskListeners.remove(listener);
+    if (currentTask != null)
+      currentTask.removeTaskEventListener(listener);
+  }
+}