package jalview.ws2.actions.annotation; import java.util.ArrayList; import java.util.Collections; import java.util.List; import jalview.analysis.AlignmentAnnotationUtils; 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 static int calcCount = 0; private final int calcNumber = calcCount++; private final AnnotationAction action; private final List args; private final Credentials credentials; private TaskI currentTask = null; private TaskEventListener taskListener = new TaskEventListener<>() { @Override public void taskCompleted(TaskI source, AnnotationResult result) { int graphGroup = alignViewport.getAlignment().getLastGraphGroup(); List annotations = new ArrayList<>(); for (AlignmentAnnotation ala : result.getAnnotations()) { if (ala.graphGroup > 0) ala.graphGroup += graphGroup; var newAnnot = alignViewport.getAlignment() .updateFromOrCopyAnnotation(ala); if (newAnnot.sequenceRef != null) { newAnnot.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.hasFeatures, result.featureColours, result.featureFilters)); } }; 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 String getCalcName() { return action.getWebService().getName(); } @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); 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); currentTask.addTaskEventListener(taskListener); currentTask.init(); listener.workerStarted(this); } @Override public boolean poll() throws Throwable { return currentTask.poll(); } @Override public synchronized void cancel() { try { currentTask.cancel(); } finally { currentTask.removeTaskEventListener(taskListener); listener.workerStopped(this); } } @Override public synchronized void done() { try { currentTask.complete(); } catch (Exception e) { } finally { currentTask.removeTaskEventListener(taskListener); listener.workerStopped(this); } } @Override public boolean isDeletable() { return true; } @Override public String toString() { return "AlignCalcWorkerAdapter-" + calcNumber + " for " + getCalcName(); } public interface WorkerListener extends java.util.EventListener { default void workerStarted(AlignCalcWorkerAdapter source) { }; default void workerStopped(AlignCalcWorkerAdapter source) { }; default void workerHasResult(AlignCalcWorkerAdapter source, AnnotationResult result) { }; static final WorkerListener NULL_LISTENER = new WorkerListener() { }; } private WorkerListener listener = WorkerListener.NULL_LISTENER; public void setWorkerListener(WorkerListener listener) { if (listener == null) listener = WorkerListener.NULL_LISTENER; this.listener = listener; } }