Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 14:43:25 GMT
  2. Package jalview.ws

File AWSThread.java

 

Coverage histogram

../../img/srcFileCovDistChart3.png
52% of files have more coverage

Code metrics

34
79
9
1
353
205
31
0.39
8.78
9
3.44

Classes

Class Line # Actions
AWSThread 43 79 31
0.270491827%
 

Contributing tests

This file is covered by 1 test. .

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. See the GNU General Public License for more details.
16    *
17    * You should have received a copy of the GNU General Public License
18    * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.ws;
22   
23    import jalview.bin.Console;
24    import jalview.datamodel.AlignedCodonFrame;
25    import jalview.datamodel.Alignment;
26    import jalview.datamodel.AlignmentI;
27    import jalview.datamodel.AlignmentView;
28    import jalview.datamodel.SequenceI;
29    import jalview.gui.AlignFrame;
30    import jalview.gui.WebserviceInfo;
31    import jalview.util.MessageManager;
32    import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
33   
34    import java.util.ArrayList;
35    import java.util.List;
36   
37    import static java.lang.String.format;
38   
39    import java.awt.event.ActionEvent;
40    import java.awt.event.ActionListener;
41    import javax.swing.Timer;
42   
 
43    public abstract class AWSThread
44    {
45   
46    private javax.swing.Timer timer;
47   
48    /**
49    * view that this job was associated with
50    */
51    protected AlignmentI currentView = null;
52   
53    /**
54    * feature settings from view that job was associated with
55    */
56    protected FeatureRendererSettings featureSettings = null;
57   
58    /**
59    * metadata about this web service
60    */
61    protected WebserviceInfo wsInfo = null;
62   
63    /**
64    * original input data for this job
65    */
66    protected AlignmentView input = null;
67   
68    /**
69    * dataset sequence relationships to be propagated onto new results
70    */
71    protected List<AlignedCodonFrame> codonframe = null;
72   
73    /**
74    * are there jobs still running in this thread.
75    *
76    * fixme: initialize with an empty array?
77    */
78    protected boolean jobComplete = false;
79   
80    /**
81    * one or more jobs being managed by this thread.
82    */
83    protected AWsJob[] jobs = null;
84   
85    /**
86    * full name of service
87    */
88    protected String WebServiceName = null;
89   
90    protected char defGapChar = '-';
91   
92    /**
93    * header prepended to all output from job
94    */
95    protected String OutputHeader;
96   
97    /**
98    * only used when reporting a web service out of memory error - the job ID
99    * will be concatenated to the URL
100    */
101    protected String WsUrl = null;
102   
103    /*
104    * The AlignFrame from which the service was requested.
105    */
106    private AlignFrame alignFrame;
107   
 
108  1 toggle public void start()
109    {
110  1 if (jobs == null)
111    {
112  0 jobComplete = true;
113  0 Console.debug(
114    "WebServiceJob poll loop finished with no jobs created.");
115  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
116  0 wsInfo.appendProgressText(
117    MessageManager.getString("info.no_jobs_ran"));
118  0 wsInfo.setFinishedNoResults();
119  0 return;
120    }
121  1 timer = new Timer(5000, new ActionListener()
122    {
123   
 
124  1 toggle @Override
125    public void actionPerformed(ActionEvent e)
126    {
127   
128  1 JobStateSummary jstate = new JobStateSummary();
129  1 for (final AWsJob job : jobs)
130    {
131  1 if (!job.submitted && job.hasValidInput())
132    {
133  1 StartJob(job);
134    }
135  1 Console.debug(format(
136  1 "Job %s is %ssubmitted", job, job.submitted ? "" : "not "));
137  1 if (job.submitted && !job.subjobComplete)
138    {
139  0 Console.debug(format(
140    "Polling Job %s Result state was:%s(ServerError=%b)",
141    job, job.getState(), job.isServerError()));
142  0 try
143    {
144  0 pollJob(job);
145  0 if (!job.hasResponse())
146  0 throw new Exception("Timed out when communicating with server. Try again later.");
147    else
148  0 Console.debug(format("Job %s Result state:%s(ServerError=%b)",
149    job, job.getState(), job.isServerError()));
150    } catch (Exception exc)
151    {
152    // Deal with Transaction exceptions
153  0 wsInfo.appendProgressText(job.jobnum, MessageManager
154    .formatMessage("info.server_exception", WebServiceName,
155    exc.getMessage()));
156    // always output the exception's stack trace to the log
157  0 Console.warn(format("%s job(%s) Server exception.",
158    WebServiceName, job.jobnum));
159  0 exc.printStackTrace();
160   
161  0 if (job.allowedServerExceptions > 0)
162    {
163  0 job.allowedServerExceptions--;
164    }
165    else
166    {
167  0 Console.warn(format("Dropping job %s %s", job, job.jobId));
168  0 job.subjobComplete = true;
169  0 wsInfo.setStatus(job.jobnum, WebserviceInfo.STATE_STOPPED_SERVERERROR);
170    }
171    } catch (OutOfMemoryError oomerror)
172    {
173  0 jobComplete = true;
174  0 job.subjobComplete = true;
175  0 job.clearResponse();
176  0 wsInfo.setStatus(job.jobnum, WebserviceInfo.STATE_STOPPED_ERROR);
177  0 Console.error(format("Out of memory when retrieving Job %s id:%s/%s",
178    job, WsUrl, job.jobId), oomerror);
179  0 new jalview.gui.OOMWarning("retrieving result for " + WebServiceName, oomerror);
180  0 System.gc();
181    }
182    }
183  1 jstate.updateJobPanelState(wsInfo, OutputHeader, job);
184    }
185    // Decide on overall state based on collected jobs[] states
186  0 updateGlobalStatus(jstate);
187  0 if (jobComplete)
188    {
189  0 timer.stop();
190    // jobs should never be null at this point
191  0 parseResult(); // tidy up and make results available to user
192   
193    }
194    }
195    });
196  1 timer.setInitialDelay(0);
197  1 timer.start();
198    }
199   
 
200  0 toggle protected void updateGlobalStatus(JobStateSummary jstate)
201    {
202  0 if (jstate.running > 0)
203    {
204  0 wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
205    }
206  0 else if (jstate.queuing > 0)
207    {
208  0 wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
209    }
210    else
211    {
212  0 jobComplete = true;
213  0 if (jstate.finished > 0)
214    {
215  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
216    }
217  0 else if (jstate.error > 0)
218    {
219  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
220    }
221  0 else if (jstate.serror > 0)
222    {
223  0 wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
224    }
225    }
226    }
227   
228   
 
229  0 toggle public void interrupt()
230    {
231  0 timer.stop();
232    }
233   
234    /**
235    * query web service for status of job. on return, job.result must not be null
236    * - if it is then it will be assumed that the job status query timed out and
237    * a server exception will be logged.
238    *
239    * @param job
240    * @throws Exception
241    * will be logged as a server exception for this job
242    */
243    public abstract void pollJob(AWsJob job) throws Exception;
244   
245    /**
246    * submit job to web service
247    *
248    * @param job
249    */
250    public abstract void StartJob(AWsJob job);
251   
252    /**
253    * process the set of AWsJob objects into a set of results, and tidy up.
254    */
255    public abstract void parseResult();
256   
257    /**
258    * helper function to conserve dataset references to sequence objects returned
259    * from web services 1. Propagates AlCodonFrame data from
260    * <code>codonframe</code> to <code>al</code> TODO: refactor to datamodel
261    *
262    * @param al
263    */
 
264  0 toggle public void propagateDatasetMappings(Alignment al)
265    {
266  0 if (codonframe != null)
267    {
268  0 SequenceI[] alignment = al.getSequencesArray();
269  0 for (int sq = 0; sq < alignment.length; sq++)
270    {
271  0 for (AlignedCodonFrame acf : codonframe)
272    {
273  0 final SequenceI seq = alignment[sq];
274  0 if (acf != null && acf.involvesSequence(seq))
275    {
276  0 al.addCodonFrame(acf);
277  0 break;
278    }
279    }
280    }
281    }
282    }
283   
284   
285    /**
286    *
287    * @return gap character to use for any alignment generation
288    */
 
289  0 toggle public char getGapChar()
290    {
291  0 return defGapChar;
292    }
293   
294    /**
295    *
296    * @param alignFrame
297    * reference for copying mappings across
298    * @param wsinfo
299    * gui attachment point
300    * @param input
301    * input data for the calculation
302    * @param webServiceName
303    * name of service
304    * @param wsUrl
305    * url of the service being invoked
306    */
 
307  0 toggle public AWSThread(AlignFrame alignFrame, WebserviceInfo wsinfo,
308    AlignmentView input, String webServiceName, String wsUrl)
309    {
310  0 this(alignFrame, wsinfo, input, wsUrl);
311  0 WebServiceName = webServiceName;
312    }
313   
314    /**
315    * Extracts additional info from alignment view's context.
316    *
317    * @param alframe
318    * - reference for copying mappings and display styles across
319    * @param wsinfo2
320    * - gui attachment point - may be null
321    * @param alview
322    * - input data for the calculation
323    * @param wsurl2
324    * - url of the service being invoked
325    */
 
326  2 toggle public AWSThread(AlignFrame alframe, WebserviceInfo wsinfo2,
327    AlignmentView alview, String wsurl2)
328    {
329  2 super();
330  2 this.alignFrame = alframe;
331  2 currentView = alframe.getCurrentView().getAlignment();
332  2 featureSettings = alframe.getFeatureRenderer().getSettings();
333  2 defGapChar = alframe.getViewport().getGapCharacter();
334  2 this.wsInfo = wsinfo2;
335  2 this.input = alview;
336  2 WsUrl = wsurl2;
337  2 if (alframe != null)
338    {
339  2 List<AlignedCodonFrame> cf = alframe.getViewport().getAlignment()
340    .getCodonFrames();
341  2 if (cf != null)
342    {
343  2 codonframe = new ArrayList<>();
344  2 codonframe.addAll(cf);
345    }
346    }
347    }
348   
 
349  0 toggle protected AlignFrame getRequestingAlignFrame()
350    {
351  0 return this.alignFrame;
352    }
353    }