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 java.beans.PropertyChangeListener;
8 import java.io.IOException;
9 import java.net.MalformedURLException;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
15 import java.util.Vector;
16 import java.util.concurrent.CopyOnWriteArraySet;
17 import java.util.concurrent.ExecutorService;
18 import java.util.concurrent.Executors;
19 import java.util.concurrent.Future;
20 import java.util.concurrent.FutureTask;
22 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
23 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
25 public class SlivkaWSDiscoverer implements WSDiscovererI
27 private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
29 private static final String COMPBIO_SLIVKA = "https://www.compbio.dundee.ac.uk/slivka/";
31 private static SlivkaWSDiscoverer instance = null;
33 private List<ServiceWithParameters> services = List.of();
35 private SlivkaWSDiscoverer()
39 public static SlivkaWSDiscoverer getInstance()
43 instance = new SlivkaWSDiscoverer();
48 private Set<ServiceChangeListener> serviceListeners = new CopyOnWriteArraySet<>();
51 public void addServiceChangeListener(ServiceChangeListener l) {
52 serviceListeners.add(l);
56 public void removeServiceChangeListener(ServiceChangeListener l) {
57 serviceListeners.remove(l);
60 public void notifyServiceListeners(List<ServiceWithParameters> services) {
61 for (var listener : serviceListeners) {
62 listener.servicesChanged(this, services);
66 private final ExecutorService executor = Executors.newSingleThreadExecutor();
67 private Vector<Future<?>> discoveryTasks = new Vector<>();
69 public Future<WSDiscovererI> startDiscoverer()
71 FutureTask<WSDiscovererI> task = new FutureTask<>(this::reloadServices, this);
72 discoveryTasks.add(task);
73 executor.execute(task);
77 private List<ServiceWithParameters> reloadServices()
79 Cache.log.info("Reloading Slivka services");
80 notifyServiceListeners(Collections.emptyList());
81 ArrayList<ServiceWithParameters> instances = new ArrayList<>();
83 for (String url : getServiceUrls())
87 client = new SlivkaClient(url);
90 for (SlivkaService service : client.getServices())
92 SlivkaWSInstance newinstance = null;
93 for (String classifier : service.classifiers)
95 if (classifier.contains("Multiple sequence alignment"))
97 newinstance = new SlivkaMsaServiceInstance(client, service);
99 if (classifier.contains("Protein sequence analysis")
100 && newinstance == null)
102 newinstance = new SlivkaAnnotationServiceInstance(client,
106 .contains("Sequence alignment analysis (conservation)"))
108 newinstance = new SlivkaAnnotationServiceInstance(client,
112 if (newinstance != null)
114 instances.add(newinstance);
117 } catch (IOException e)
124 services = instances;
125 notifyServiceListeners(instances);
126 Cache.log.info("Slivka services reloading finished");
131 public List<ServiceWithParameters> getServices()
137 public boolean hasServices()
139 return !isRunning() && services.size() > 0;
143 public boolean isRunning()
145 return !discoveryTasks.stream().allMatch(Future::isDone);
149 public void setServiceUrls(List<String> wsUrls)
151 if (wsUrls != null && !wsUrls.isEmpty())
153 Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls));
157 Cache.removeProperty(SLIVKA_HOST_URLS);
162 public List<String> getServiceUrls()
164 String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA);
165 String[] urls = surls.split(",");
166 ArrayList<String> valid = new ArrayList<>(urls.length);
167 for (String url : urls)
173 } catch (MalformedURLException e)
175 Cache.log.warn("Problem whilst trying to make a URL from '"
176 + ((url != null) ? url : "<null>") + "'");
178 "This was probably due to a malformed comma separated list"
179 + " in the " + SLIVKA_HOST_URLS
180 + " entry of $(HOME)/.jalview_properties)");
181 Cache.log.debug("Exception was ", e);
188 public boolean testServiceUrl(URL url)
190 return getServerStatusFor(url.toString()) == STATUS_OK;
194 public int getServerStatusFor(String url)
198 List<?> services = new SlivkaClient(url).getServices();
199 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
200 } catch (IOException e)
202 Cache.log.error("Slivka could not retrieve services list", e);
203 return STATUS_INVALID;
208 public String getErrorMessages()
210 // TODO Auto-generated method stub