--- /dev/null
+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);
+ }
+}