Clover icon

Coverage Report

  1. Project Clover database Thu Dec 4 2025 16:11:35 GMT
  2. Package jalview.ws.rest

File RestClient.java

 

Coverage histogram

../../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

36
89
25
1
462
322
47
0.53
3.56
25
1.88

Classes

Class Line # Actions
RestClient 52 89 47
0.5333333653.3%
 

Contributing tests

This file is covered by 320 tests. .

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.rest;
22   
23    import java.awt.event.ActionEvent;
24    import java.awt.event.ActionListener;
25    import java.util.Vector;
26   
27    import javax.swing.JMenu;
28    import javax.swing.JMenuItem;
29    import javax.swing.event.MenuEvent;
30    import javax.swing.event.MenuListener;
31   
32    import jalview.api.AlignmentViewPanel;
33    import jalview.bin.ApplicationSingletonProvider;
34    import jalview.bin.ApplicationSingletonProvider.ApplicationSingletonI;
35    import jalview.bin.Cache;
36    import jalview.datamodel.AlignmentView;
37    import jalview.gui.AlignFrame;
38    import jalview.gui.AlignViewport;
39    import jalview.gui.Desktop;
40    import jalview.gui.JvOptionPane;
41    import jalview.gui.WebserviceInfo;
42    import jalview.util.MessageManager;
43    import jalview.ws.WSClient;
44    import jalview.ws.WSClientI;
45    import jalview.ws.WSMenuEntryProviderI;
46    import jalview.ws.rest.clientdefs.ShmrRestClient;
47   
48    /**
49    * @author JimP
50    *
51    */
 
52    public class RestClient extends WSClient
53    implements WSClientI, WSMenuEntryProviderI, ApplicationSingletonI
54    {
 
55  11 toggle @SuppressWarnings("unused")
56    private RestClient()
57    {
58    // accessed by ApplicationSingletonProvider
59    }
60   
 
61  8121 toggle private static RestClient getInstance()
62    {
63  8121 return ApplicationSingletonProvider.getInstance(RestClient.class);
64    }
65   
66    public static final String RSBS_SERVICES = "RSBS_SERVICES";
67   
68    protected Vector<String> services = null;
69   
70    RestServiceDescription service;
71   
 
72  8132 toggle public RestClient(RestServiceDescription rsd)
73    {
74  8132 service = rsd;
75    }
76   
77    /**
78    * parent alignframe for this job
79    */
80    AlignFrame af;
81   
82    /**
83    * alignment view which provides data for job.
84    */
85    AlignViewport av;
86   
87    /**
88    * get the alignFrame for the associated input data if it exists.
89    *
90    * @return
91    */
 
92  0 toggle protected AlignFrame recoverAlignFrameForView()
93    {
94  0 return jalview.gui.Desktop.getAlignFrameFor(av);
95    }
96   
 
97  0 toggle public RestClient(RestServiceDescription service2, AlignFrame alignFrame)
98    {
99  0 this(service2, alignFrame, false);
100    }
101   
102    boolean headless = false;
103   
 
104  1 toggle public RestClient(RestServiceDescription service2, AlignFrame alignFrame,
105    boolean nogui)
106    {
107  1 service = service2;
108  1 af = alignFrame;
109  1 av = alignFrame.getViewport();
110  1 headless = nogui;
111  1 constructJob();
112    }
113   
 
114  1 toggle public void setWebserviceInfo(boolean headless)
115    {
116  1 WebServiceJobTitle = MessageManager
117    .formatMessage("label.webservice_job_title", new String[]
118    { service.details.getAction(), service.details.getName() });
119  1 WebServiceName = service.details.getName();
120  1 WebServiceReference = "No reference - go to url for more info";
121  1 if (service.details.getDescription() != null)
122    {
123  1 WebServiceReference = service.details.getDescription();
124    }
125  1 if (!headless)
126    {
127  0 wsInfo = new WebserviceInfo(WebServiceJobTitle,
128    WebServiceName + "\n" + WebServiceReference,
129    Desktop.FRAME_MAKE_VISIBLE);
130  0 wsInfo.setRenderAsHtml(true);
131    }
132   
133    }
134   
 
135  0 toggle @Override
136    public boolean isCancellable()
137    {
138    // TODO define process for cancelling rsbws jobs
139  0 return false;
140    }
141   
 
142  0 toggle @Override
143    public boolean canMergeResults()
144    {
145    // TODO process service definition to identify if the results might be
146    // mergeable
147    // TODO: change comparison for annotation merge
148  0 return false;
149    }
150   
 
151  0 toggle @Override
152    public void cancelJob()
153    {
154  0 jalview.bin.Console
155    .errPrintln("Cannot cancel this job type: " + service);
156    }
157   
 
158  8106 toggle @Override
159    public void attachWSMenuEntry(final JMenu wsmenu,
160    final AlignFrame alignFrame)
161    {
162  8106 JMenuItem submit = new JMenuItem(service.details.getName());
163  8106 submit.setToolTipText(MessageManager
164    .formatMessage("label.rest_client_submit", new String[]
165    { service.details.getAction(), service.details.getName() }));
166  8106 submit.addActionListener(new ActionListener()
167    {
168   
 
169  0 toggle @Override
170    public void actionPerformed(ActionEvent e)
171    {
172  0 new RestClient(service, alignFrame);
173    }
174   
175    });
176  8106 wsmenu.add(submit);
177    // TODO: menu listener should enable/disable entry depending upon selection
178    // state of the alignment
179  8106 wsmenu.addMenuListener(new MenuListener()
180    {
181   
 
182  0 toggle @Override
183    public void menuSelected(MenuEvent e)
184    {
185    // TODO Auto-generated method stub
186   
187    }
188   
 
189  0 toggle @Override
190    public void menuDeselected(MenuEvent e)
191    {
192    // TODO Auto-generated method stub
193   
194    }
195   
 
196  0 toggle @Override
197    public void menuCanceled(MenuEvent e)
198    {
199    // TODO Auto-generated method stub
200   
201    }
202   
203    });
204   
205    }
206   
207    /**
208    * record of initial undoredo hash for the alignFrame providing data for this
209    * job.
210    */
211    long[] undoredo = null;
212   
213    /**
214    * Compare the original input data to the data currently presented to the
215    * user. // LOGIC: compare undo/redo - if same, merge regardless (coping with
216    * any changes in hidden columns as normal) // if different undo/redo then
217    * compare region that was submitted // if same, then merge as before, if
218    * different then prompt user to open a new window.
219    *
220    * @return
221    */
 
222  0 toggle protected boolean isAlignmentModified()
223    {
224  0 if (undoredo == null || av == null || av.getAlignment() == null)
225    {
226    // always return modified if we don't have access to live GUI elements
227    // anymore.
228  0 return true;
229    }
230  0 if (av.isUndoRedoHashModified(undoredo))
231    {
232    // alignment has been modified in some way.
233  0 return true;
234    }
235    // TODO: look deeper into modification of selection state, etc that may
236    // affect RestJobThread.realiseResults(boolean merge);
237  0 return false;
238   
239    }
240   
241    /**
242    * TODO: combine to form a dataset+alignment+annotation context
243    */
244    AlignmentView _input;
245   
246    /**
247    * input data context
248    */
249    jalview.io.packed.JalviewDataset jds;
250   
251    /**
252    * informative name for results
253    */
254    public String viewTitle;
255   
 
256  1 toggle protected void constructJob()
257    {
258  1 service.setInvolvesFlags();
259    // record all aspects of alignment view so we can merge back or recreate
260    // later
261  1 undoredo = av.getUndoRedoHash();
262    /**
263    * delete ? Vector sgs = av.getAlignment().getGroups(); if (sgs!=null) {
264    * _sgs = new SequenceGroup[sgs.size()]; sgs.copyInto(_sgs); } else { _sgs =
265    * new SequenceGroup[0]; }
266    */
267  1 boolean selExists = (av.getSelectionGroup() != null)
268    && (av.getSelectionGroup().getSize() > 1);
269    // TODO: JAL-715: refactor to alignViewport methods and revise to full
270    // focus+context+dataset input data staging model
271  1 if (selExists)
272    {
273  0 if (service.partitiondata)
274    {
275  0 if (av.getAlignment().getGroups() != null
276    && av.getAlignment().getGroups().size() > 0)
277    {
278    // intersect groups with selected region
279  0 _input = new AlignmentView(av.getAlignment(),
280    av.getAlignment().getHiddenColumns(),
281    av.getSelectionGroup(), av.hasHiddenColumns(), true,
282    true);
283  0 viewTitle = MessageManager.formatMessage(
284    "label.select_visible_region_of", new String[]
285  0 { (av.hasHiddenColumns()
286    ? MessageManager.getString("label.visible")
287    : ""),
288    af.getTitle() });
289    }
290    else
291    {
292    // use selected region to partition alignment
293  0 _input = new AlignmentView(av.getAlignment(),
294    av.getAlignment().getHiddenColumns(),
295    av.getSelectionGroup(), av.hasHiddenColumns(), false,
296    true);
297    }
298  0 viewTitle = MessageManager.formatMessage(
299    "label.select_unselect_visible_regions_from", new String[]
300  0 { (av.hasHiddenColumns()
301    ? MessageManager.getString("label.visible")
302    : ""),
303    af.getTitle() });
304    }
305    else
306    {
307    // just take selected region intersection
308  0 _input = new AlignmentView(av.getAlignment(),
309    av.getAlignment().getHiddenColumns(),
310    av.getSelectionGroup(), av.hasHiddenColumns(), true, true);
311  0 viewTitle = MessageManager.formatMessage(
312    "label.select_visible_region_of", new String[]
313  0 { (av.hasHiddenColumns()
314    ? MessageManager.getString("label.visible")
315    : ""),
316    af.getTitle() });
317    }
318    }
319    else
320    {
321    // standard alignment view without selection present
322  1 _input = new AlignmentView(av.getAlignment(),
323    av.getAlignment().getHiddenColumns(), null,
324    av.hasHiddenColumns(), false, true);
325  1 viewTitle = ""
326  1 + (av.hasHiddenColumns()
327    ? (new StringBuffer(" ")
328    .append(MessageManager
329    .getString("label.visible_region_of"))
330    .toString())
331    : "")
332    + af.getTitle();
333    }
334   
335  1 RestJobThread jobsthread = new RestJobThread(this);
336   
337  1 if (jobsthread.isValid())
338    {
339  1 setWebserviceInfo(headless);
340  1 if (!headless)
341    {
342  0 wsInfo.setthisService(this);
343  0 jobsthread.setWebServiceInfo(wsInfo);
344    }
345  1 jobsthread.start();
346    }
347    else
348    {
349    // TODO: try to tell the user why the job couldn't be started.
350  0 JvOptionPane.showMessageDialog(Desktop.getDesktopPane(),
351  0 (jobsthread.hasWarnings() ? jobsthread.getWarnings()
352    : MessageManager.getString(
353    "label.job_couldnt_be_started_check_input")),
354    MessageManager
355    .getString("label.unable_start_web_service_analysis"),
356    JvOptionPane.WARNING_MESSAGE);
357    }
358    }
359   
 
360  0 toggle public AlignmentViewPanel recoverAlignPanelForView()
361    {
362  0 AlignmentViewPanel[] aps = Desktop
363    .getAlignmentPanels(av.getSequenceSetId());
364  0 for (AlignmentViewPanel alp : aps)
365    {
366  0 if (alp.getAlignViewport() == av)
367    {
368  0 return alp;
369    }
370    }
371  0 return null;
372    }
373   
 
374  0 toggle public boolean isShowResultsInNewView()
375    {
376    // TODO make this a property of the service
377  0 return true;
378    }
379   
 
380  8119 toggle public static RestClient[] getRestClients()
381    {
382  8119 return getInstance().getClients();
383    }
384   
 
385  8119 toggle private RestClient[] getClients()
386    {
387  8119 if (services == null)
388    {
389  11 services = new Vector<>();
390  11 try
391    {
392  11 String servicePrefs = Cache.getDefault(RSBS_SERVICES,
393    ShmrRestClient.makeShmmrRestClient().service.toString());
394  11 if (servicePrefs.indexOf("http://zeus.")>-1)
395    {
396  5 servicePrefs = servicePrefs.replace("http://zeus.", "https://zeus.");
397    }
398   
399  11 for (RestServiceDescription descr : RestServiceDescription
400    .parseDescriptions(servicePrefs))
401    {
402  11 String svc = descr.toString();
403  11 services.add(svc);
404    }
405    } catch (Exception ex)
406    {
407  0 jalview.bin.Console.errPrintln(
408    "Serious - RSBS descriptions in user preferences are corrupt!");
409  0 ex.printStackTrace();
410    }
411   
412    }
413  8119 RestClient[] lst = new RestClient[services.size()];
414  8119 int i = 0;
415  8119 for (String svc : services)
416    {
417  8119 lst[i++] = new RestClient(new RestServiceDescription(svc));
418    }
419  8119 return lst;
420    }
421   
 
422  8106 toggle public String getAction()
423    {
424  8106 return service.details.getAction();
425    }
426   
 
427  13 toggle public RestServiceDescription getRestDescription()
428    {
429  13 return service;
430    }
431   
 
432  11 toggle public static Vector<String> getRsbsDescriptions()
433    {
434  11 Vector<String> rsbsDescrs = new Vector<>();
435  11 for (RestClient rsbs : getRestClients())
436    {
437  11 rsbsDescrs.add(rsbs.getRestDescription().toString());
438    }
439  11 return rsbsDescrs;
440    }
441   
 
442  1 toggle public static void setRsbsServices(Vector<String> rsbsUrls)
443    {
444  1 if (rsbsUrls != null)
445    {
446   
447    // TODO: consider validating services ?
448  1 getInstance().services = new Vector<String>(rsbsUrls);
449  1 StringBuffer sprop = new StringBuffer();
450  1 for (String s : getInstance().services)
451    {
452  1 sprop.append(s);
453    }
454  1 Cache.setProperty(RSBS_SERVICES, sprop.toString());
455    }
456    else
457    {
458  0 Cache.removeProperty(RSBS_SERVICES);
459    }
460    }
461   
462    }