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.io.IOException;
8 import java.net.MalformedURLException;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.List;
14 import java.util.Vector;
15 import java.util.concurrent.CompletableFuture;
16 import java.util.concurrent.CopyOnWriteArraySet;
17 import java.util.concurrent.ExecutorService;
18 import java.util.concurrent.Executors;
19 import java.util.concurrent.Future;
21 import compbio.data.msa.Category;
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)
53 serviceListeners.add(l);
57 public void removeServiceChangeListener(ServiceChangeListener l)
59 serviceListeners.remove(l);
62 public void notifyServiceListeners(List<ServiceWithParameters> services)
64 for (var listener : serviceListeners)
66 listener.servicesChanged(this, services);
70 private final ExecutorService executor = Executors
71 .newSingleThreadExecutor();
73 private Vector<Future<?>> discoveryTasks = new Vector<>();
75 public CompletableFuture<WSDiscovererI> startDiscoverer()
77 CompletableFuture<WSDiscovererI> task = CompletableFuture
80 return SlivkaWSDiscoverer.this;
82 discoveryTasks.add(task);
86 private List<ServiceWithParameters> reloadServices()
88 Cache.log.info("Reloading Slivka services");
89 notifyServiceListeners(Collections.emptyList());
90 ArrayList<ServiceWithParameters> instances = new ArrayList<>();
92 for (String url : getServiceUrls())
94 SlivkaClient client = new SlivkaClient(url);
96 List<SlivkaService> services;
99 services = client.getServices();
100 } catch (IOException e)
105 for (SlivkaService service : services)
107 SlivkaWSInstance newInstance = null;
108 for (String classifier : service.classifiers)
110 String[] path = classifier.split("\\s*::\\s*");
111 if (path.length >= 3 && path[0].toLowerCase().equals("operation")
112 && path[1].toLowerCase().equals("analysis"))
114 switch (path[path.length - 1].toLowerCase())
116 case "sequence alignment analysis (conservation)":
117 newInstance = new SlivkaAnnotationServiceInstance(client,
118 service, Category.CATEGORY_CONSERVATION);
120 case "protein sequence analysis":
121 newInstance = new SlivkaAnnotationServiceInstance(client,
122 service, Category.CATEGORY_DISORDER);
124 case "protein secondary structure prediction":
125 newInstance = new SlivkaAnnotationServiceInstance(client,
126 service, "Secondary Structure Prediction");
128 case "multiple sequence alignment":
129 newInstance = new SlivkaMsaServiceInstance(client, service,
130 Category.CATEGORY_ALIGNMENT);
134 if (newInstance != null)
137 if (newInstance != null)
138 instances.add(newInstance);
142 services = instances;
143 Cache.log.info("Slivka services reloading finished");
144 notifyServiceListeners(instances);
149 public List<ServiceWithParameters> getServices()
155 public boolean hasServices()
157 return !isRunning() && services.size() > 0;
161 public boolean isRunning()
163 return !discoveryTasks.stream().allMatch(Future::isDone);
167 public void setServiceUrls(List<String> wsUrls)
169 if (wsUrls != null && !wsUrls.isEmpty())
171 Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls));
175 Cache.removeProperty(SLIVKA_HOST_URLS);
180 public List<String> getServiceUrls()
182 String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA);
183 String[] urls = surls.split(",");
184 ArrayList<String> valid = new ArrayList<>(urls.length);
185 for (String url : urls)
191 } catch (MalformedURLException e)
193 Cache.log.warn("Problem whilst trying to make a URL from '"
194 + ((url != null) ? url : "<null>") + "'");
196 "This was probably due to a malformed comma separated list"
197 + " in the " + SLIVKA_HOST_URLS
198 + " entry of $(HOME)/.jalview_properties)");
199 Cache.log.debug("Exception was ", e);
206 public boolean testServiceUrl(URL url)
208 return getServerStatusFor(url.toString()) == STATUS_OK;
212 public int getServerStatusFor(String url)
216 List<?> services = new SlivkaClient(url).getServices();
217 return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
218 } catch (IOException e)
220 Cache.log.error("Slivka could not retrieve services list", e);
221 return STATUS_INVALID;
226 public String getErrorMessages()
228 // TODO Auto-generated method stub