package jalview.ws.slivkaws; import jalview.bin.Cache; import jalview.gui.AlignFrame; import jalview.ws.WSDiscovererI; import jalview.ws.api.ServiceWithParameters; import jalview.ws.jws2.PreferredServiceRegistry; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.swing.JMenu; import uk.ac.dundee.compbio.slivkaclient.SlivkaClient; import uk.ac.dundee.compbio.slivkaclient.SlivkaService; public class SlivkaWSDiscoverer implements WSDiscovererI { private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS"; private static final String COMPBIO_SLIVKA = "https://www.compbio.dundee.ac.uk/slivka"; private static SlivkaWSDiscoverer instance = null; private List services = List.of(); private SlivkaWSDiscoverer() { } public static SlivkaWSDiscoverer getInstance() { if (instance == null) { instance = new SlivkaWSDiscoverer(); } return instance; } private PropertyChangeSupport changeSupport = new PropertyChangeSupport( this); @Override public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame) { JMenu slivkaMenu = new JMenu("Slivka"); wsmenu.add(slivkaMenu); JMenu alignmentMenu = new JMenu("Sequence Alignment"); slivkaMenu.add(alignmentMenu); JMenu disorderMenu = new JMenu("Protein sequence analysis"); slivkaMenu.add(disorderMenu); JMenu conservationMenu = new JMenu("Conservation"); slivkaMenu.add(conservationMenu); PreferredServiceRegistry.getRegistry().populateWSMenuEntry(services, changeSupport, slivkaMenu, alignFrame, null); } volatile boolean ready = false; volatile Thread discovererThread = null; private class DiscovererThread extends Thread { private Thread oldThread; DiscovererThread(Thread oldThread) { super(); this.oldThread = oldThread; } @Override public void run() { if (oldThread != null) { oldThread.interrupt(); try { oldThread.join(); } catch (InterruptedException e) { return; } finally { oldThread = null; } } ready = false; reloadServices(); ready = !isInterrupted(); } } Thread discoverer = null; @Override public Thread startDiscoverer(PropertyChangeListener changeListener) { changeSupport.addPropertyChangeListener(changeListener); ready = false; (discovererThread = new DiscovererThread(discovererThread)).start(); return discovererThread; } private void reloadServices() { Cache.log.info("Reloading Slivka services"); changeSupport.firePropertyChange("services", services, List.of()); ArrayList instances = new ArrayList<>(); for (String url : getServiceUrls()) { Cache.log.info(url); SlivkaClient client; try { client = new SlivkaClient(url); } catch (URISyntaxException e) { e.printStackTrace(); continue; } try { for (SlivkaService service : client.getServices()) { SlivkaWSInstance newinstance = null; for (String classifier : service.classifiers) { if (classifier.contains("Multiple sequence alignment")) { newinstance = new SlivkaMsaServiceInstance(client, service); } if (classifier.contains("Protein sequence analysis") && newinstance == null) { newinstance = new SlivkaAnnotationServiceInstance(client, service, false); } if (classifier .contains("Sequence alignment analysis (conservation)")) { newinstance = new SlivkaAnnotationServiceInstance(client, service, true); } } if (newinstance != null) { instances.add(newinstance); } } } catch (IOException e) { continue; } } services = instances; changeSupport.firePropertyChange("services", List.of(), services); Cache.log.info("Slivka services reloading finished"); } @Override public List getServices() { return services; } @Override public boolean hasServices() { return ready == true && services.size() > 0; } @Override public boolean isRunning() { return discovererThread == null || discovererThread.isAlive() || discovererThread.getState() == Thread.State.NEW; } @Override public void setServiceUrls(List wsUrls) { if (wsUrls != null && !wsUrls.isEmpty()) { Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls)); } else { Cache.removeProperty(SLIVKA_HOST_URLS); } } @Override public List getServiceUrls() { String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA); String[] urls = surls.split(","); ArrayList valid = new ArrayList<>(urls.length); for (String url : urls) { try { new URL(url); valid.add(url); } catch (MalformedURLException e) { Cache.log.warn("Problem whilst trying to make a URL from '" + ((url != null) ? url : "") + "'"); Cache.log.warn( "This was probably due to a malformed comma separated list" + " in the " + SLIVKA_HOST_URLS + " entry of $(HOME)/.jalview_properties)"); Cache.log.debug("Exception was ", e); } } return valid; } @Override public boolean testServiceUrl(URL url) { return getServerStatusFor(url.toString()) == STATUS_OK; } @Override public int getServerStatusFor(String url) { try { List services = new SlivkaClient(url).getServices(); return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK; } catch (IOException | URISyntaxException e) { return STATUS_INVALID; } } @Override public String getErrorMessages() { // TODO Auto-generated method stub return ""; } }