cf693bc10704b76999daeaabd0b0e25034f3abf0
[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 import java.util.function.Consumer;
8
9 import jalview.analysis.AlignmentAnnotationUtils;
10 import jalview.api.AlignViewportI;
11 import jalview.api.AlignmentViewPanel;
12 import jalview.api.PollableAlignCalcWorkerI;
13 import jalview.datamodel.AlignmentAnnotation;
14 import jalview.datamodel.AlignmentI;
15 import jalview.workers.AlignCalcWorker;
16 import jalview.ws.params.ArgumentI;
17 import jalview.ws2.actions.api.TaskEventListener;
18 import jalview.ws2.actions.api.TaskI;
19 import jalview.ws2.api.Credentials;
20
21 public class AlignCalcWorkerAdapter extends AlignCalcWorker implements PollableAlignCalcWorkerI
22 {
23   private static int calcCount = 0;
24
25   private final int calcNumber = calcCount++;
26
27   private final AnnotationAction action;
28
29   private final List<ArgumentI> args;
30
31   private final Credentials credentials;
32
33   private TaskI<AnnotationResult> currentTask = null;
34
35   private TaskEventListener<AnnotationResult> taskListener = new TaskEventListener<>()
36   {
37     @Override
38     public void taskCompleted(TaskI source, AnnotationResult result)
39     {
40       int graphGroup = alignViewport.getAlignment().getLastGraphGroup();
41       List<AlignmentAnnotation> annotations = new ArrayList<>();
42       for (AlignmentAnnotation ala : result.getAnnotations())
43       {
44         if (ala.graphGroup > 0)
45           ala.graphGroup += graphGroup;
46         var newAnnot = alignViewport.getAlignment()
47             .updateFromOrCopyAnnotation(ala);
48         if (ala.sequenceRef != null)
49         {
50           ala.sequenceRef.addAlignmentAnnotation(newAnnot);
51           newAnnot.adjustForAlignment();
52           AlignmentAnnotationUtils.replaceAnnotationOnAlignmentWith(
53               newAnnot, newAnnot.label, newAnnot.getCalcId());
54         }
55         annotations.add(newAnnot);
56       }
57       updateOurAnnots(annotations);
58       listener.workerHasResult(
59           AlignCalcWorkerAdapter.this,
60           new AnnotationResult(
61               annotations,
62               result.transferFeatures,
63               result.featureColours,
64               result.featureFilters));
65     }
66   };
67
68   public AlignCalcWorkerAdapter(AlignViewportI alignViewport, AlignmentViewPanel alignPanel, AnnotationAction action,
69       List<ArgumentI> args, Credentials credentials)
70   {
71     super(alignViewport, alignPanel);
72     this.action = action;
73     this.args = args;
74     this.credentials = credentials;
75   }
76
77   @Override
78   public String getCalcName()
79   {
80     return action.getWebService().getName();
81   }
82
83   @Override
84   public void updateAnnotation()
85   {
86
87   }
88
89   private void updateOurAnnots(List<AlignmentAnnotation> newAnnots)
90   {
91     List<AlignmentAnnotation> oldAnnots = ourAnnots != null ? ourAnnots : List.of();
92     AlignmentI alignment = alignViewport.getAlignment();
93     for (AlignmentAnnotation annotation : oldAnnots)
94       if (!newAnnots.contains(annotation))
95         alignment.deleteAnnotation(annotation);
96     for (AlignmentAnnotation annotation : newAnnots)
97       alignment.validateAnnotation(annotation);
98     ourAnnots = Collections.synchronizedList(newAnnots);
99   }
100
101   @Override
102   public synchronized void startUp() throws Throwable
103   {
104     if (alignViewport.isClosed())
105     {
106       calcMan.disableWorker(this);
107       abortAndDestroy();
108       throw new IllegalStateException("Starting calculation for closed viewport");
109     }
110     currentTask = action.createTask(alignViewport, args, credentials);
111     currentTask.addTaskEventListener(taskListener);
112     currentTask.init();
113     listener.workerStarted(this);
114   }
115
116   @Override
117   public boolean poll() throws Throwable
118   {
119     return currentTask.poll();
120   }
121
122   @Override
123   public synchronized void cancel()
124   {
125     try
126     {
127       currentTask.cancel();
128     } finally
129     {
130       currentTask.removeTaskEventListener(taskListener);
131       listener.workerStopped(this);
132     }
133   }
134
135   @Override
136   public synchronized void done()
137   {
138     try
139     {
140       currentTask.complete();
141     } catch (Exception e)
142     {
143     } finally
144     {
145       currentTask.removeTaskEventListener(taskListener);
146       listener.workerStopped(this);
147     }
148   }
149
150   @Override
151   public String toString()
152   {
153     return "AlignCalcWorkerAdapter-" + calcNumber + " for " + getCalcName();
154   }
155
156   public interface WorkerListener extends java.util.EventListener
157   {
158     default void workerStarted(AlignCalcWorkerAdapter source)
159     {
160     };
161
162     default void workerStopped(AlignCalcWorkerAdapter source)
163     {
164     };
165
166     default void workerHasResult(AlignCalcWorkerAdapter source, AnnotationResult result)
167     {
168     };
169
170     static final WorkerListener NULL_LISTENER = new WorkerListener()
171     {
172     };
173   }
174
175   private WorkerListener listener = WorkerListener.NULL_LISTENER;
176   
177   public void setWorkerListener(WorkerListener listener)
178   {
179     if (listener == null) listener = WorkerListener.NULL_LISTENER;
180     this.listener = listener;
181   }
182 }