Clover icon

Coverage Report

  1. Project Clover database Wed May 27 2026 17:16:46 BST
  2. Package jalview.ws2.client.slivka

File SlivkaWSDiscoverer.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

18
121
10
1
254
224
30
0.25
12.1
10
3

Classes

Class Line # Actions
SlivkaWSDiscoverer 22 121 30
0.9530201695.3%
 

Contributing tests

This file is covered by 434 tests. .

Source view

1    package jalview.ws2.client.slivka;
2   
3    import java.io.IOException;
4    import java.net.MalformedURLException;
5    import java.net.URI;
6    import java.net.URISyntaxException;
7    import java.net.URL;
8    import java.util.ArrayList;
9    import java.util.List;
10    import java.util.function.Function;
11   
12    import jalview.bin.Cache;
13    import jalview.bin.Console;
14    import jalview.ws.params.ParamManager;
15    import jalview.ws2.actions.alignment.AlignmentAction;
16    import jalview.ws2.actions.annotation.AnnotationAction;
17    import jalview.ws2.api.WebService;
18    import jalview.ws2.client.api.AbstractWebServiceDiscoverer;
19    import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
20    import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
21   
 
22    public class SlivkaWSDiscoverer extends AbstractWebServiceDiscoverer
23    {
24    private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
25   
26    private static final URL DEFAULT_URL;
 
27  11 toggle static
28    {
29  11 try
30    {
31  11 DEFAULT_URL = new URL("https://www.compbio.dundee.ac.uk/slivka/");
32    } catch (MalformedURLException e)
33    {
34  0 throw new AssertionError(e);
35    }
36    }
37   
38    private static SlivkaWSDiscoverer instance = null;
39   
40    private static ParamManager paramManager = null;
41   
42    private final Function<URI, SlivkaClient> clientFactory;
43   
 
44  66 toggle SlivkaWSDiscoverer(Function<URI, SlivkaClient> clientFactory)
45    {
46  66 this.clientFactory = clientFactory;
47    }
48   
 
49  9174 toggle public static SlivkaWSDiscoverer getInstance()
50    {
51  9174 if (instance == null)
52  11 instance = new SlivkaWSDiscoverer(SlivkaClient::newInstance);
53  9174 return instance;
54    }
55   
 
56  0 toggle public static void setParamManager(ParamManager manager)
57    {
58  0 paramManager = manager;
59    }
60   
 
61  14 toggle @Override
62    public int getStatusForUrl(URL url)
63    {
64  14 try
65    {
66  14 List<?> services = clientFactory.apply(url.toURI()).getServices();
67  8 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
68    } catch (URISyntaxException e)
69    {
70  0 Console.error("invalid URL " + url, e);
71  0 return STATUS_INVALID;
72    } catch (IOException e)
73    {
74  1 Console.error("slivka could not retrieve services from " + url, e);
75  1 return STATUS_INVALID;
76    }
77    }
78   
 
79  117 toggle @Override
80    protected String getUrlsPropertyKey()
81    {
82  117 return SLIVKA_HOST_URLS;
83    }
84   
 
85  102 toggle @Override
86    protected URL getDefaultUrl()
87    {
88  102 return DEFAULT_URL;
89    }
90   
 
91  142 toggle @Override
92    protected List<WebService<?>> fetchServices(URL url) throws IOException
93    {
94  142 ArrayList<WebService<?>> allServices = new ArrayList<>();
95  142 SlivkaClient slivkaClient;
96  142 try
97    {
98  142 slivkaClient = clientFactory.apply(url.toURI());
99    } catch (URISyntaxException e)
100    {
101  0 throw new MalformedURLException(e.getMessage());
102    }
103  142 for (var slivkaService : slivkaClient.getServices())
104    {
105  1342 int serviceClass = getServiceClass(slivkaService);
106  1342 if (serviceClass == SERVICE_CLASS_MSA)
107    {
108  635 var wsb = WebService.<AlignmentAction> newBuilder();
109  635 initServiceBuilder(slivkaClient, slivkaService, wsb);
110  635 wsb.category("Alignment");
111  635 wsb.interactive(false);
112  635 wsb.actionClass(AlignmentAction.class);
113  635 var msaService = wsb.build();
114   
115  635 boolean canRealign = msaService.getName().contains("lustal");
116  635 var client = new SlivkaAlignmentWSClient(slivkaClient, slivkaService);
117  635 var actionBuilder = AlignmentAction.newBuilder(client);
118  635 actionBuilder.name("Alignment");
119  635 actionBuilder.webService(msaService);
120  635 if (canRealign)
121  175 actionBuilder.subcategory("Align");
122  635 actionBuilder.minSequences(2);
123  635 msaService.addAction(actionBuilder.build());
124  635 if (canRealign)
125    {
126  175 actionBuilder.name("Re-alignment");
127  175 actionBuilder.subcategory("Realign");
128  175 actionBuilder.submitGaps(true);
129  175 msaService.addAction(actionBuilder.build());
130    }
131  635 allServices.add(msaService);
132    }
133  707 else if (serviceClass == SERVICE_CLASS_PROT_SEQ_ANALYSIS)
134    {
135  345 var wsb = WebService.<AnnotationAction> newBuilder();
136  345 initServiceBuilder(slivkaClient, slivkaService, wsb);
137  345 wsb.category("Protein Disorder");
138  345 wsb.interactive(false);
139  345 wsb.actionClass(AnnotationAction.class);
140  345 var psaService = wsb.build();
141  345 var client = new SlivkaAnnotationWSClient(slivkaClient, slivkaService);
142  345 var actionBuilder = AnnotationAction.newBuilder(client);
143  345 actionBuilder.webService(psaService);
144  345 actionBuilder.name("Analysis");
145  345 psaService.addAction(actionBuilder.build());
146  345 allServices.add(psaService);
147    }
148  362 else if (serviceClass == SERVICE_CLASS_CONSERVATION)
149    {
150  91 var wsb = WebService.<AnnotationAction> newBuilder();
151  91 initServiceBuilder(slivkaClient, slivkaService, wsb);
152  91 wsb.category("Conservation");
153  91 wsb.interactive(true);
154  91 wsb.actionClass(AnnotationAction.class);
155  91 var conService = wsb.build();
156  91 var client = new SlivkaAnnotationWSClient(slivkaClient, slivkaService);
157  91 var actionBuilder = AnnotationAction.newBuilder(client);
158  91 actionBuilder.webService(conService);
159  91 actionBuilder.name("");
160  91 actionBuilder.alignmentAnalysis(true);
161  91 actionBuilder.requireAlignedSequences(true);
162  91 actionBuilder.filterSymbols(true);
163  91 conService.addAction(actionBuilder.build());
164  91 allServices.add(conService);
165    }
166  271 else if (serviceClass == SERVICE_CLASS_RNA_SEC_STR_PRED)
167    {
168  98 var wsb = WebService.<AnnotationAction> newBuilder();
169  98 initServiceBuilder(slivkaClient, slivkaService, wsb);
170  98 wsb.category("Secondary Structure Prediction");
171  98 wsb.interactive(true);
172  98 wsb.actionClass(AnnotationAction.class);
173  98 var predService = wsb.build();
174  98 var client = new SlivkaAnnotationWSClient(slivkaClient, slivkaService);
175  98 var actionBuilder = AnnotationAction.newBuilder(client);
176  98 actionBuilder.webService(predService);
177  98 actionBuilder.name("Prediction");
178  98 actionBuilder.minSequences(2);
179  98 actionBuilder.allowNucleotide(true);
180  98 actionBuilder.allowProtein(false);
181  98 actionBuilder.alignmentAnalysis(true);
182  98 actionBuilder.requireAlignedSequences(true);
183  98 actionBuilder.filterSymbols(false);
184  98 predService.addAction(actionBuilder.build());
185  98 allServices.add(predService);
186    }
187    else
188    {
189  173 continue;
190    }
191    }
192  138 return allServices;
193    }
194   
 
195  1169 toggle private void initServiceBuilder(SlivkaClient client, SlivkaService service, WebService.Builder<?> wsBuilder)
196    {
197  1169 try
198    {
199  1169 wsBuilder.url(client.getUrl().toURL());
200    } catch (MalformedURLException e)
201    {
202  0 e.printStackTrace();
203    }
204  1169 wsBuilder.clientName("slivka");
205  1169 wsBuilder.name(service.getName());
206  1169 wsBuilder.description(service.getDescription());
207  1169 var storeBuilder = new SlivkaParamStoreFactory(service, paramManager);
208  1169 wsBuilder.paramDatastore(storeBuilder.createParamDatastore());
209    }
210   
211    static final int SERVICE_CLASS_UNSUPPORTED = -1;
212   
213    static final int SERVICE_CLASS_MSA = 1;
214   
215    static final int SERVICE_CLASS_RNA_SEC_STR_PRED = 2;
216   
217    static final int SERVICE_CLASS_CONSERVATION = 3;
218   
219    static final int SERVICE_CLASS_PROT_SEQ_ANALYSIS = 4;
220   
221    static final int SERVICE_CLASS_PROT_SEC_STR_PRED = 5;
222   
223    /**
224    * Scan service classifiers starting with operation :: analysis to decide the
225    * operation class.
226    *
227    * @return service class flag
228    */
 
229  1342 toggle private static int getServiceClass(SlivkaService service)
230    {
231  1342 for (String classifier : service.getClassifiers())
232    {
233  3069 String[] path = classifier.split("\\s*::\\s*");
234  3069 if (path.length < 3 || !path[0].equalsIgnoreCase("operation"))
235  1728 continue;
236    // classifier is operation :: *
237  1341 var tail = path[path.length - 1].toLowerCase();
238  1341 switch (tail)
239    {
240  635 case "multiple sequence alignment":
241  635 return SERVICE_CLASS_MSA;
242  98 case "rna secondary structure prediction":
243  98 return SERVICE_CLASS_RNA_SEC_STR_PRED;
244  91 case "sequence alignment analysis (conservation)":
245  91 return SERVICE_CLASS_CONSERVATION;
246  345 case "protein sequence analysis":
247  345 return SERVICE_CLASS_PROT_SEQ_ANALYSIS;
248  86 case "protein secondary structure prediction":
249  86 return SERVICE_CLASS_PROT_SEC_STR_PRED;
250    }
251    }
252  87 return SERVICE_CLASS_UNSUPPORTED;
253    }
254    }