JAL-4199 Implement AlignCalcWorker adapter for annot tasks
[jalview.git] / src / jalview / ws2 / actions / annotation / AlignCalcWorkerAdapter.java
1 package jalview.ws2.actions.annotation;
2
3 import java.util.ArrayList;
4 import java.util.Collections;
5 import java.util.List;
6 import java.util.concurrent.CopyOnWriteArrayList;
7
8 import jalview.api.AlignViewportI;
9 import jalview.api.AlignmentViewPanel;
10 import jalview.api.PollableAlignCalcWorkerI;
11 import jalview.datamodel.Alignment;
12 import jalview.datamodel.AlignmentAnnotation;
13 import jalview.datamodel.AlignmentI;
14 import jalview.workers.AlignCalcWorker;
15 import jalview.ws.params.ArgumentI;
16 import jalview.ws2.actions.alignment.AlignmentResult;
17 import jalview.ws2.actions.api.JobI;
18 import jalview.ws2.actions.api.TaskEventListener;
19 import jalview.ws2.actions.api.TaskI;
20 import jalview.ws2.api.Credentials;
21 import jalview.ws2.api.JobStatus;
22
23 public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableAlignCalcWorkerI
24 {
25   private final AnnotationAction action;
26
27   private final List<ArgumentI> args;
28
29   private final Credentials credentials;
30
31   private TaskI<AnnotationResult> currentTask = null;
32
33   private TaskEventListener<AnnotationResult> internalTaskListener = new TaskEventListener<>()
34   {
35     @Override
36     public void taskCompleted(TaskI source, AnnotationResult result)
37     {
38       updateOurAnnots(result.getAnnotations());
39     }
40   };
41
42   // task event listeners managed by this worker, passed to each creates task
43   private List<TaskEventListener<AnnotationResult>> taskListeners = new CopyOnWriteArrayList<>();
44   {
45     taskListeners.add(internalTaskListener);
46   }
47
48   public AlignCalcWorkerAdapter(AlignViewportI alignViewport, AlignmentViewPanel alignPanel, AnnotationAction action,
49       List<ArgumentI> args, Credentials credentials)
50   {
51     super(alignViewport, alignPanel);
52     this.action = action;
53     this.args = args;
54     this.credentials = credentials;
55   }
56
57   @Override
58   public void updateAnnotation()
59   {
60
61   }
62
63   private void updateOurAnnots(List<AlignmentAnnotation> newAnnots)
64   {
65     List<AlignmentAnnotation> oldAnnots = ourAnnots != null ? ourAnnots : List.of();
66     AlignmentI alignment = alignViewport.getAlignment();
67     for (AlignmentAnnotation annotation : oldAnnots)
68       if (!newAnnots.contains(annotation))
69         alignment.deleteAnnotation(annotation);
70     for (AlignmentAnnotation annotation : newAnnots)
71       alignment.validateAnnotation(annotation);
72     ap.adjustAnnotationHeight();
73     ourAnnots = Collections.synchronizedList(newAnnots);
74   }
75
76   @Override
77   public synchronized void startUp() throws Throwable
78   {
79     if (alignViewport.isClosed())
80     {
81       calcMan.disableWorker(this);
82       abortAndDestroy();
83       throw new IllegalStateException("Starting calculation for closed viewport");
84     }
85     currentTask = action.createTask(alignViewport, args, credentials);
86     for (var listener : taskListeners)
87       currentTask.addTaskEventListener(listener);
88     currentTask.init();
89   }
90
91   @Override
92   public boolean poll() throws Throwable
93   {
94     return currentTask.poll();
95   }
96
97   @Override
98   public synchronized void cancel()
99   {
100     try
101     {
102       currentTask.cancel();
103     } finally
104     {
105       for (var listener : taskListeners)
106         currentTask.removeTaskEventListener(listener);
107     }
108   }
109
110   @Override
111   public synchronized void done()
112   {
113     try
114     {
115       currentTask.complete();
116     } catch (Exception e)
117     {
118     } finally
119     {
120       for (var listener : taskListeners)
121         currentTask.removeTaskEventListener(listener);
122     }
123   }
124
125   public void addTaskEventListener(TaskEventListener<AnnotationResult> listener)
126   {
127     taskListeners.add(listener);
128     if (currentTask != null)
129       currentTask.addTaskEventListener(listener);
130   }
131
132   public void removeTaskEventListener(TaskEventListener<AnnotationResult> listener)
133   {
134     taskListeners.remove(listener);
135     if (currentTask != null)
136       currentTask.removeTaskEventListener(listener);
137   }
138 }