X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fws%2Fslivkaws%2FSlivkaWSDiscoverer.java;h=104560acc7b6ae18320cd72939efe5b6f9ae934a;hb=df8e2545932852b0f257a3d67b33996afdfd259b;hp=2d46c9fb62938269489025bb930c5cac7fc4fab4;hpb=857348180124be7ab86d7de1e4d3f780e65b1fdd;p=jalview.git diff --git a/src/jalview/ws/slivkaws/SlivkaWSDiscoverer.java b/src/jalview/ws/slivkaws/SlivkaWSDiscoverer.java index 2d46c9f..104560a 100644 --- a/src/jalview/ws/slivkaws/SlivkaWSDiscoverer.java +++ b/src/jalview/ws/slivkaws/SlivkaWSDiscoverer.java @@ -1,143 +1,238 @@ package jalview.ws.slivkaws; -import jalview.datamodel.AlignmentView; -import jalview.gui.AlignFrame; -import jalview.ws.WSMenuEntryProviderI; -import jalview.ws.jws2.MsaWSClient; +import jalview.bin.Cache; +import jalview.bin.Console; +import jalview.ws.ServiceChangeListener; +import jalview.ws.WSDiscovererI; +import jalview.ws.api.ServiceWithParameters; +import javajs.http.HttpClientFactory; -import java.awt.event.ActionEvent; -import java.io.IOError; import java.io.IOException; -import java.net.URISyntaxException; - -import javax.swing.JMenu; -import javax.swing.JMenuItem; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import compbio.data.msa.Category; import uk.ac.dundee.compbio.slivkaclient.SlivkaClient; +import uk.ac.dundee.compbio.slivkaclient.SlivkaService; -public class SlivkaWSDiscoverer - implements Runnable, WSMenuEntryProviderI +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 SlivkaClient client; - private SlivkaWSDiscoverer() { - try - { - client = new SlivkaClient("gjb-www-1.cluster.lifesci.dundee.ac.uk", 3203); - } catch (URISyntaxException e) - { - throw new RuntimeException(e); - } + private List services = List.of(); + + private SlivkaWSDiscoverer() + { } public static SlivkaWSDiscoverer getInstance() { - if (instance == null) { - instance = new SlivkaWSDiscoverer(); - } + if (instance == null) + { + instance = new SlivkaWSDiscoverer(); + } return instance; } + private Set serviceListeners = new CopyOnWriteArraySet<>(); + + @Override + public void addServiceChangeListener(ServiceChangeListener l) + { + serviceListeners.add(l); + } + @Override - public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame) + public void removeServiceChangeListener(ServiceChangeListener l) + { + serviceListeners.remove(l); + } + + public void notifyServiceListeners(List services) + { + for (var listener : serviceListeners) + { + listener.servicesChanged(this, services); + } + } + + private final ExecutorService executor = Executors + .newSingleThreadExecutor(); + + private Vector> discoveryTasks = new Vector<>(); + + public CompletableFuture startDiscoverer() { - JMenu submenu = new JMenu("Slivka"); + CompletableFuture task = CompletableFuture + .supplyAsync(() -> { + reloadServices(); + return SlivkaWSDiscoverer.this; + }, executor); + discoveryTasks.add(task); + return task; + } + private List reloadServices() + { + Console.info("Reloading Slivka services"); + notifyServiceListeners(Collections.emptyList()); + ArrayList instances = new ArrayList<>(); + + for (String url : getServiceUrls()) { - // clustalo menu entry - JMenuItem noParamMenuItem = new JMenuItem("ClustalO with defaults"); - SlivkaWSInstance clustalo; + SlivkaClient client = SlivkaClient.newInstance(url); + + List services; try { - clustalo = new SlivkaWSInstance(client, client.getService("clustalo")); + services = client.getServices(); } catch (IOException e) { - throw new IOError(e); + e.printStackTrace(); + continue; } - noParamMenuItem.addActionListener((ActionEvent e) -> { - AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - if (msa != null) - { - new MsaWSClient( - clustalo, alignFrame.getTitle(), msa, false, true, alignFrame.getViewport().getAlignment().getDataset(), - alignFrame - ); - } - }); - submenu.add(noParamMenuItem); - - JMenuItem parametrisedMenuItem = new JMenuItem("ClustalO with custom parameters"); - parametrisedMenuItem.addActionListener((ActionEvent evt) -> { - AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - if (msa != null) + for (SlivkaService service : services) + { + SlivkaWSInstance newInstance = null; + for (String classifier : service.classifiers) { - try - { - SlivkaParamSet paramSet = new SlivkaParamSet(clustalo.getService()); - new MsaWSClient( - clustalo, paramSet, null, true, alignFrame.getTitle(), msa, false, true, - alignFrame.getViewport().getAlignment().getDataset(), alignFrame - ); - } catch (IOException e) + String[] path = classifier.split("\\s*::\\s*"); + if (path.length >= 3 && path[0].toLowerCase().equals("operation") + && path[1].toLowerCase().equals("analysis")) { - e.printStackTrace(); + switch (path[path.length - 1].toLowerCase()) + { + case "rna secondary structure prediction": + newInstance = new RNAalifoldServiceInstance(client, + service, "Secondary Structure Prediction"); + break; + case "sequence alignment analysis (conservation)": + newInstance = new SlivkaAnnotationServiceInstance(client, + service, Category.CATEGORY_CONSERVATION); + break; + case "protein sequence analysis": + newInstance = new SlivkaAnnotationServiceInstance(client, + service, Category.CATEGORY_DISORDER); + break; + case "protein secondary structure prediction": + newInstance = new SlivkaAnnotationServiceInstance(client, + service, "Secondary Structure Prediction"); + break; + case "multiple sequence alignment": + newInstance = new SlivkaMsaServiceInstance(client, service, + Category.CATEGORY_ALIGNMENT); + break; + } } + if (newInstance != null) + break; } - }); - submenu.add(parametrisedMenuItem); + if (newInstance != null) + instances.add(newInstance); + } } + services = instances; + Console.info("Slivka services reloading finished"); + notifyServiceListeners(instances); + return instances; + } + + @Override + public List getServices() + { + return services; + } + + @Override + public boolean hasServices() + { + return !isRunning() && services.size() > 0; + } + + @Override + public boolean isRunning() + { + return !discoveryTasks.stream().allMatch(Future::isDone); + } + + @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) { - // clustalw2 menu entry - JMenuItem noParamMenuItem = new JMenuItem("ClustalW2 with defaults"); - SlivkaWSInstance clustalo; try { - clustalo = new SlivkaWSInstance(client, client.getService("clustalw")); - } catch (IOException e) + new URL(url); + valid.add(url); + } catch (MalformedURLException e) { - throw new IOError(e); + Console.warn("Problem whilst trying to make a URL from '" + + ((url != null) ? url : "") + "'"); + Console.warn( + "This was probably due to a malformed comma separated list" + + " in the " + SLIVKA_HOST_URLS + + " entry of $(HOME)/.jalview_properties)"); + Console.debug("Exception was ", e); } - noParamMenuItem.addActionListener((ActionEvent e) -> { - AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - if (msa != null) - { - new MsaWSClient( - clustalo, alignFrame.getTitle(), msa, false, true, alignFrame.getViewport().getAlignment().getDataset(), - alignFrame - ); - } - }); - submenu.add(noParamMenuItem); - - JMenuItem parametrisedMenuItem = new JMenuItem("ClustalW2 with custom parameters"); - parametrisedMenuItem.addActionListener((ActionEvent evt) -> { - AlignmentView msa = alignFrame.gatherSequencesForAlignment(); - if (msa != null) - { - try - { - SlivkaParamSet paramSet = new SlivkaParamSet(clustalo.getService()); - new MsaWSClient( - clustalo, paramSet, null, true, alignFrame.getTitle(), msa, false, true, - alignFrame.getViewport().getAlignment().getDataset(), alignFrame - ); - } catch (IOException e) - { - e.printStackTrace(); - } - } - }); - submenu.add(parametrisedMenuItem); } + return valid; + } - wsmenu.add(submenu); + @Override + public boolean testServiceUrl(URL url) + { + return getServerStatusFor(url.toString()) == STATUS_OK; } @Override - public void run() + public int getServerStatusFor(String url) { + try + { + List services = SlivkaClient.newInstance(url).getServices(); + return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK; + } catch (IOException | org.json.JSONException e) + { + Console.error("Slivka could not retrieve services list", e); + return STATUS_INVALID; + } + } + @Override + public String getErrorMessages() + { + // TODO Auto-generated method stub + return ""; } }