package jalview.ws2.actions.annotation; 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.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.workers.AlignCalcWorker; import jalview.ws.params.ArgumentI; import jalview.ws2.actions.api.TaskEventListener; import jalview.ws2.actions.api.TaskI; import jalview.ws2.api.Credentials; public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableAlignCalcWorkerI { private final AnnotationAction action; private final List args; private final Credentials credentials; private TaskI currentTask = null; private TaskEventListener 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> taskListeners = new CopyOnWriteArrayList<>(); { taskListeners.add(internalTaskListener); } public AlignCalcWorkerAdapter(AlignViewportI alignViewport, AlignmentViewPanel alignPanel, AnnotationAction action, List args, Credentials credentials) { super(alignViewport, alignPanel); this.action = action; this.args = args; this.credentials = credentials; } @Override public void updateAnnotation() { } private void updateOurAnnots(List newAnnots) { List 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 listener) { taskListeners.add(listener); if (currentTask != null) currentTask.addTaskEventListener(listener); } public void removeTaskEventListener(TaskEventListener listener) { taskListeners.remove(listener); if (currentTask != null) currentTask.removeTaskEventListener(listener); } }