1 package jalview.ws.slivkaws;
3 import jalview.bin.Cache;
4 import jalview.ws.ServiceChangeListener;
5 import jalview.ws.WSDiscovererI;
6 import jalview.ws.api.ServiceWithParameters;
7 import javajs.http.HttpClientFactory;
9 import java.io.IOException;
10 import java.net.MalformedURLException;
12 import java.util.ArrayList;
13 import java.util.Collections;
14 import java.util.List;
16 import java.util.Vector;
17 import java.util.concurrent.CompletableFuture;
18 import java.util.concurrent.CopyOnWriteArraySet;
19 import java.util.concurrent.ExecutorService;
20 import java.util.concurrent.Executors;
21 import java.util.concurrent.Future;
23 import compbio.data.msa.Category;
24 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
25 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
27 public class SlivkaWSDiscoverer implements WSDiscovererI
29 private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
31 private static final String COMPBIO_SLIVKA = "https://www.compbio.dundee.ac.uk/slivka/";
33 private static SlivkaWSDiscoverer instance = null;
35 private List<ServiceWithParameters> services = List.of();
37 private SlivkaWSDiscoverer()
41 public static SlivkaWSDiscoverer getInstance()
45 instance = new SlivkaWSDiscoverer();
50 private Set<ServiceChangeListener> serviceListeners = new CopyOnWriteArraySet<>();
53 public void addServiceChangeListener(ServiceChangeListener l)
55 serviceListeners.add(l);
59 public void removeServiceChangeListener(ServiceChangeListener l)
61 serviceListeners.remove(l);
64 public void notifyServiceListeners(List<ServiceWithParameters> services)
66 for (var listener : serviceListeners)
68 listener.servicesChanged(this, services);
72 private final ExecutorService executor = Executors
73 .newSingleThreadExecutor();
75 private Vector<Future<?>> discoveryTasks = new Vector<>();
77 public CompletableFuture<WSDiscovererI> startDiscoverer()
79 CompletableFuture<WSDiscovererI> task = CompletableFuture
82 return SlivkaWSDiscoverer.this;
84 discoveryTasks.add(task);
88 private List<ServiceWithParameters> reloadServices()
90 Cache.log.info("Reloading Slivka services");
91 notifyServiceListeners(Collections.emptyList());
92 ArrayList<ServiceWithParameters> instances = new ArrayList<>();
94 for (String url : getServiceUrls())
96 SlivkaClient client = new SlivkaClient(url);
98 List<SlivkaService> services;
101 services = client.getServices();
102 } catch (IOException e)
107 for (SlivkaService service : services)
109 SlivkaWSInstance newInstance = null;
110 for (String classifier : service.classifiers)
112 String[] path = classifier.split("\\s*::\\s*");
113 if (path.length >= 3 && path[0].toLowerCase().equals("operation")
114 && path[1].toLowerCase().equals("analysis"))
116 switch (path[path.length - 1].toLowerCase())
118 case "rna secondary structure prediction":
119 newInstance = new RNAalifoldServiceInstance(client,
120 service, "Secondary Structure Prediction");
122 case "sequence alignment analysis (conservation)":
123 newInstance = new SlivkaAnnotationServiceInstance(client,
124 service, Category.CATEGORY_CONSERVATION);
126 case "protein sequence analysis":
127 newInstance = new SlivkaAnnotationServiceInstance(client,
128 service, Category.CATEGORY_DISORDER);
130 case "protein secondary structure prediction":
131 newInstance = new SlivkaJPredServiceInstance(client,
132 service, "Secondary Structure Prediction");
134 case "multiple sequence alignment":
135 newInstance = new SlivkaMsaServiceInstance(client, service,
136 Category.CATEGORY_ALIGNMENT);
140 if (newInstance != null)
143 if (newInstance != null)
144 instances.add(newInstance);
148 services = instances;
149 Cache.log.info("Slivka services reloading finished");
150 notifyServiceListeners(instances);
155 public List<ServiceWithParameters> getServices()
161 public boolean hasServices()
163 return !isRunning() && services.size() > 0;
167 public boolean isRunning()
169 return !discoveryTasks.stream().allMatch(Future::isDone);
173 public void setServiceUrls(List<String> wsUrls)
175 if (wsUrls != null && !wsUrls.isEmpty())
177 Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls));
181 Cache.removeProperty(SLIVKA_HOST_URLS);
186 public List<String> getServiceUrls()
188 String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA);
189 String[] urls = surls.split(",");
190 ArrayList<String> valid = new ArrayList<>(urls.length);
191 for (String url : urls)
197 } catch (MalformedURLException e)
199 Cache.log.warn("Problem whilst trying to make a URL from '"
200 + ((url != null) ? url : "<null>") + "'");
202 "This was probably due to a malformed comma separated list"
203 + " in the " + SLIVKA_HOST_URLS
204 + " entry of $(HOME)/.jalview_properties)");
205 Cache.log.debug("Exception was ", e);
212 public boolean testServiceUrl(URL url)
214 return getServerStatusFor(url.toString()) == STATUS_OK;
218 public int getServerStatusFor(String url)
222 List<?> services = new SlivkaClient(url).getServices();
223 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
224 } catch (IOException | org.json.JSONException e)
226 Cache.log.error("Slivka could not retrieve services list", e);
227 return STATUS_INVALID;
232 public String getErrorMessages()
234 // TODO Auto-generated method stub