Clover icon

Coverage Report

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

File SlivkaWSDiscoverer.java

 

Coverage histogram

../../../img/srcFileCovDistChart0.png
60% of files have more coverage

Code metrics

14
75
15
1
238
209
33
0.44
5
15
2.2

Classes

Class Line # Actions
SlivkaWSDiscoverer 28 75 33
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    package jalview.ws.slivkaws;
2   
3    import jalview.bin.Cache;
4    import jalview.bin.Console;
5    import jalview.ws.ServiceChangeListener;
6    import jalview.ws.WSDiscovererI;
7    import jalview.ws.api.ServiceWithParameters;
8    import javajs.http.HttpClientFactory;
9   
10    import java.io.IOException;
11    import java.net.MalformedURLException;
12    import java.net.URL;
13    import java.util.ArrayList;
14    import java.util.Collections;
15    import java.util.List;
16    import java.util.Set;
17    import java.util.Vector;
18    import java.util.concurrent.CompletableFuture;
19    import java.util.concurrent.CopyOnWriteArraySet;
20    import java.util.concurrent.ExecutorService;
21    import java.util.concurrent.Executors;
22    import java.util.concurrent.Future;
23   
24    import compbio.data.msa.Category;
25    import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
26    import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
27   
 
28    public class SlivkaWSDiscoverer implements WSDiscovererI
29    {
30    private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
31   
32    private static final String COMPBIO_SLIVKA = "https://www.compbio.dundee.ac.uk/slivka/";
33   
34    private static SlivkaWSDiscoverer instance = null;
35   
36    private List<ServiceWithParameters> services = List.of();
37   
 
38  0 toggle private SlivkaWSDiscoverer()
39    {
40    }
41   
 
42  0 toggle public static SlivkaWSDiscoverer getInstance()
43    {
44  0 if (instance == null)
45    {
46  0 instance = new SlivkaWSDiscoverer();
47    }
48  0 return instance;
49    }
50   
51    private Set<ServiceChangeListener> serviceListeners = new CopyOnWriteArraySet<>();
52   
 
53  0 toggle @Override
54    public void addServiceChangeListener(ServiceChangeListener l)
55    {
56  0 serviceListeners.add(l);
57    }
58   
 
59  0 toggle @Override
60    public void removeServiceChangeListener(ServiceChangeListener l)
61    {
62  0 serviceListeners.remove(l);
63    }
64   
 
65  0 toggle public void notifyServiceListeners(List<ServiceWithParameters> services)
66    {
67  0 for (var listener : serviceListeners)
68    {
69  0 listener.servicesChanged(this, services);
70    }
71    }
72   
73    private final ExecutorService executor = Executors
74    .newSingleThreadExecutor();
75   
76    private Vector<Future<?>> discoveryTasks = new Vector<>();
77   
 
78  0 toggle public CompletableFuture<WSDiscovererI> startDiscoverer()
79    {
80  0 CompletableFuture<WSDiscovererI> task = CompletableFuture
81    .supplyAsync(() -> {
82  0 reloadServices();
83  0 return SlivkaWSDiscoverer.this;
84    }, executor);
85  0 discoveryTasks.add(task);
86  0 return task;
87    }
88   
 
89  0 toggle private List<ServiceWithParameters> reloadServices()
90    {
91  0 Console.info("Reloading Slivka services");
92  0 notifyServiceListeners(Collections.emptyList());
93  0 ArrayList<ServiceWithParameters> instances = new ArrayList<>();
94   
95  0 for (String url : getServiceUrls())
96    {
97  0 SlivkaClient client = SlivkaClient.newInstance(url);
98   
99  0 List<SlivkaService> services;
100  0 try
101    {
102  0 services = client.getServices();
103    } catch (IOException e)
104    {
105  0 e.printStackTrace();
106  0 continue;
107    }
108  0 for (SlivkaService service : services)
109    {
110  0 SlivkaWSInstance newInstance = null;
111  0 for (String classifier : service.classifiers)
112    {
113  0 String[] path = classifier.split("\\s*::\\s*");
114  0 if (path.length >= 3 && path[0].toLowerCase().equals("operation")
115    && path[1].toLowerCase().equals("analysis"))
116    {
117  0 switch (path[path.length - 1].toLowerCase())
118    {
119  0 case "rna secondary structure prediction":
120  0 newInstance = new RNAalifoldServiceInstance(client,
121    service, "Secondary Structure Prediction");
122  0 break;
123  0 case "sequence alignment analysis (conservation)":
124  0 newInstance = new SlivkaAnnotationServiceInstance(client,
125    service, Category.CATEGORY_CONSERVATION);
126  0 break;
127  0 case "protein sequence analysis":
128  0 newInstance = new SlivkaAnnotationServiceInstance(client,
129    service, Category.CATEGORY_DISORDER);
130  0 break;
131  0 case "protein secondary structure prediction":
132  0 newInstance = new SlivkaAnnotationServiceInstance(client,
133    service, "Secondary Structure Prediction");
134  0 break;
135  0 case "multiple sequence alignment":
136  0 newInstance = new SlivkaMsaServiceInstance(client, service,
137    Category.CATEGORY_ALIGNMENT);
138  0 break;
139    }
140    }
141  0 if (newInstance != null)
142  0 break;
143    }
144  0 if (newInstance != null)
145  0 instances.add(newInstance);
146    }
147    }
148   
149  0 services = instances;
150  0 Console.info("Slivka services reloading finished");
151  0 notifyServiceListeners(instances);
152  0 return instances;
153    }
154   
 
155  0 toggle @Override
156    public List<ServiceWithParameters> getServices()
157    {
158  0 return services;
159    }
160   
 
161  0 toggle @Override
162    public boolean hasServices()
163    {
164  0 return !isRunning() && services.size() > 0;
165    }
166   
 
167  0 toggle @Override
168    public boolean isRunning()
169    {
170  0 return !discoveryTasks.stream().allMatch(Future::isDone);
171    }
172   
 
173  0 toggle @Override
174    public void setServiceUrls(List<String> wsUrls)
175    {
176  0 if (wsUrls != null && !wsUrls.isEmpty())
177    {
178  0 Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls));
179    }
180    else
181    {
182  0 Cache.removeProperty(SLIVKA_HOST_URLS);
183    }
184    }
185   
 
186  0 toggle @Override
187    public List<String> getServiceUrls()
188    {
189  0 String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA);
190  0 String[] urls = surls.split(",");
191  0 ArrayList<String> valid = new ArrayList<>(urls.length);
192  0 for (String url : urls)
193    {
194  0 try
195    {
196  0 new URL(url);
197  0 valid.add(url);
198    } catch (MalformedURLException e)
199    {
200  0 Console.warn("Problem whilst trying to make a URL from '"
201  0 + ((url != null) ? url : "<null>") + "'");
202  0 Console.warn(
203    "This was probably due to a malformed comma separated list"
204    + " in the " + SLIVKA_HOST_URLS
205    + " entry of $(HOME)/.jalview_properties)");
206  0 Console.debug("Exception was ", e);
207    }
208    }
209  0 return valid;
210    }
211   
 
212  0 toggle @Override
213    public boolean testServiceUrl(URL url)
214    {
215  0 return getServerStatusFor(url.toString()) == STATUS_OK;
216    }
217   
 
218  0 toggle @Override
219    public int getServerStatusFor(String url)
220    {
221  0 try
222    {
223  0 List<?> services = SlivkaClient.newInstance(url).getServices();
224  0 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
225    } catch (IOException | org.json.JSONException e)
226    {
227  0 Console.error("Slivka could not retrieve services list", e);
228  0 return STATUS_INVALID;
229    }
230    }
231   
 
232  0 toggle @Override
233    public String getErrorMessages()
234    {
235    // TODO Auto-generated method stub
236  0 return "";
237    }
238    }