JAL-3878 Add javadocs to created classes and reformat code.
[jalview.git] / src / jalview / ws2 / PollingTaskExecutor.java
1 package jalview.ws2;
2
3 import java.util.List;
4 import java.util.concurrent.CopyOnWriteArrayList;
5 import java.util.concurrent.Executors;
6 import java.util.concurrent.ScheduledExecutorService;
7 import java.util.concurrent.TimeUnit;
8
9 import jalview.bin.Cache;
10
11 /**
12  * An object that executes submitted {@link PollableTaskI} tasks using
13  * {@link SchedulekExecutorservice}. The task is first started using its
14  * {@link PollableTaskI#start} method and then repeatedly polled every second
15  * with {@link PollableTaskI#poll}.
16  * 
17  * The {@link PollingTaskExecutor} automates the process of running tasks and
18  * provides convenient interface to listen to events associated with task
19  * execution.
20  * 
21  * @author mmwarowny
22  *
23  */
24 public class PollingTaskExecutor
25 {
26   private ScheduledExecutorService executor = Executors
27       .newSingleThreadScheduledExecutor();
28
29   /**
30    * Submit the task for execution. Calls task's {@code start} method and, if
31    * started successfully, schedules next poll after one second.
32    * 
33    * @param task
34    *          task to submit
35    */
36   public void submit(final PollableTaskI task)
37   {
38     executor.submit(() -> {
39       try
40       {
41         task.start();
42         wsThreadSupport.submitted(task);
43       } catch (Exception e)
44       {
45         Cache.log.error("Failed to submit web service jobs.", e);
46         wsThreadSupport.submissionFailed(task, e);
47         return;
48       }
49       executor.schedule(() -> poll(task), 1, TimeUnit.SECONDS);
50     });
51   }
52
53   /**
54    * Poll the task by calling it's {@code poll} method. If not finished, the
55    * next poll is scheduled to happen after one second, otherwise task's
56    * {@code done} method is called immediately.
57    * 
58    * @param task
59    *          task to poll
60    */
61   private void poll(PollableTaskI task)
62   {
63     boolean done;
64     try
65     {
66       done = task.poll();
67     } catch (Exception e)
68     {
69       Cache.log.error("Failed to poll task.", e);
70       wsThreadSupport.pollFailed(task, e);
71       return;
72     }
73     if (!done)
74     {
75       executor.schedule(() -> poll(task), 1, TimeUnit.SECONDS);
76     }
77     else
78     {
79       task.done();
80       wsThreadSupport.done(task);
81     }
82   }
83
84   private WebServiceThreadSupport wsThreadSupport = new WebServiceThreadSupport();
85
86   /**
87    * Add listener of the task related events.
88    * 
89    * @param listener
90    *          listener to add
91    */
92   public void addThreadListener(PollableTaskListenerI listener)
93   {
94     wsThreadSupport.addListener(listener);
95   }
96
97   /**
98    * @param listener
99    *          listener to be removed
100    */
101   public void removeThreadListener(PollableTaskListenerI listener)
102   {
103     wsThreadSupport.removeListener(listener);
104   }
105
106   public void shutdown()
107   {
108     executor.shutdownNow();
109   }
110
111 }
112
113 class WebServiceThreadSupport implements PollableTaskListenerI
114 {
115   List<PollableTaskListenerI> listeners = new CopyOnWriteArrayList<>();
116
117   @Override
118   public void submitted(PollableTaskI task)
119   {
120     for (var listener : listeners)
121       listener.submitted(task);
122   }
123
124   @Override
125   public void submissionFailed(PollableTaskI task, Exception e)
126   {
127     for (var listener : listeners)
128       listener.submissionFailed(task, e);
129   }
130
131   @Override
132   public void pollFailed(PollableTaskI task, Exception e)
133   {
134     for (var listener : listeners)
135       listener.pollFailed(task, e);
136   }
137
138   @Override
139   public void cancelled(PollableTaskI task)
140   {
141     for (var listener : listeners)
142       listener.cancelled(task);
143   }
144
145   @Override
146   public void done(PollableTaskI task)
147   {
148     for (var listener : listeners)
149       listener.done(task);
150   }
151
152   public void addListener(PollableTaskListenerI listener)
153   {
154     if (!listeners.contains(listener))
155     {
156       listeners.add(listener);
157     }
158   }
159
160   public void removeListener(PollableTaskListenerI listener)
161   {
162     listeners.remove(listener);
163   }
164 }