JAL-6386 update slivka client for j2s compatibility
[jalview.git] / src / jalview / ws / slivkaws / SlivkaWSDiscoverer.java
1 package jalview.ws.slivkaws;
2
3 import jalview.bin.Cache;
4 import jalview.gui.AlignFrame;
5 import jalview.ws.WSDiscovererI;
6 import jalview.ws.api.ServiceWithParameters;
7 import jalview.ws.jws2.PreferredServiceRegistry;
8
9 import java.beans.PropertyChangeListener;
10 import java.beans.PropertyChangeSupport;
11 import java.io.IOException;
12 import java.net.MalformedURLException;
13 import java.net.URL;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import javax.swing.JMenu;
18
19 import uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
20 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
21
22 public class SlivkaWSDiscoverer implements WSDiscovererI
23 {
24   private static final String SLIVKA_HOST_URLS = "SLIVKAHOSTURLS";
25
26   private static final String COMPBIO_SLIVKA = "https://www.compbio.dundee.ac.uk/slivka/";
27
28   private static SlivkaWSDiscoverer instance = null;
29
30   private List<ServiceWithParameters> services = List.of();
31
32   private SlivkaWSDiscoverer()
33   {
34   }
35
36   public static SlivkaWSDiscoverer getInstance()
37   {
38     if (instance == null)
39     {
40       instance = new SlivkaWSDiscoverer();
41     }
42     return instance;
43   }
44
45   private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
46       this);
47
48   @Override
49   public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
50   {
51     JMenu slivkaMenu = new JMenu("Slivka");
52     wsmenu.add(slivkaMenu);
53
54     JMenu alignmentMenu = new JMenu("Sequence Alignment");
55     slivkaMenu.add(alignmentMenu);
56     JMenu disorderMenu = new JMenu("Protein sequence analysis");
57     slivkaMenu.add(disorderMenu);
58     JMenu conservationMenu = new JMenu("Conservation");
59     slivkaMenu.add(conservationMenu);
60     PreferredServiceRegistry.getRegistry().populateWSMenuEntry(services,
61         changeSupport, slivkaMenu, alignFrame, null);
62
63   }
64
65   volatile boolean ready = false;
66
67   volatile Thread discovererThread = null;
68
69   private class DiscovererThread extends Thread
70   {
71     private Thread oldThread;
72
73     DiscovererThread(Thread oldThread)
74     {
75       super();
76       this.oldThread = oldThread;
77     }
78
79     @Override
80     public void run()
81     {
82       if (oldThread != null)
83       {
84         oldThread.interrupt();
85         try
86         {
87           oldThread.join();
88         } catch (InterruptedException e)
89         {
90           return;
91         } finally
92         {
93           oldThread = null;
94         }
95       }
96       ready = false;
97       reloadServices();
98       ready = !isInterrupted();
99     }
100   }
101
102   Thread discoverer = null;
103
104   @Override
105   public Thread startDiscoverer(PropertyChangeListener changeListener)
106   {
107     changeSupport.addPropertyChangeListener(changeListener);
108     ready = false;
109     (discovererThread = new DiscovererThread(discovererThread)).start();
110     return discovererThread;
111   }
112
113   private void reloadServices()
114   {
115     Cache.log.info("Reloading Slivka services");
116     changeSupport.firePropertyChange("services", services, List.of());
117     ArrayList<ServiceWithParameters> instances = new ArrayList<>();
118
119     for (String url : getServiceUrls())
120     {
121       Cache.log.info(url);
122       SlivkaClient client;
123       client = new SlivkaClient(url);
124       try
125       {
126         for (SlivkaService service : client.getServices())
127         {
128           SlivkaWSInstance newinstance = null;
129           for (String classifier : service.classifiers)
130           {
131             if (classifier.contains("Multiple sequence alignment"))
132             {
133               newinstance = new SlivkaMsaServiceInstance(client, service);
134             }
135             if (classifier.contains("Protein sequence analysis")
136                 && newinstance == null)
137             {
138               newinstance = new SlivkaAnnotationServiceInstance(client,
139                   service, false);
140             }
141             if (classifier
142                 .contains("Sequence alignment analysis (conservation)"))
143             {
144               newinstance = new SlivkaAnnotationServiceInstance(client,
145                   service, true);
146             }
147           }
148           if (newinstance != null)
149           {
150             instances.add(newinstance);
151           }
152         }
153       } catch (IOException e)
154       {
155         continue;
156       }
157     }
158
159     services = instances;
160     changeSupport.firePropertyChange("services", List.of(), services);
161
162     Cache.log.info("Slivka services reloading finished");
163   }
164
165   @Override
166   public List<ServiceWithParameters> getServices()
167   {
168     return services;
169   }
170
171   @Override
172   public boolean hasServices()
173   {
174     return ready == true && services.size() > 0;
175   }
176
177   @Override
178   public boolean isRunning()
179   {
180     return discovererThread == null || discovererThread.isAlive()
181         || discovererThread.getState() == Thread.State.NEW;
182   }
183
184   @Override
185   public void setServiceUrls(List<String> wsUrls)
186   {
187     if (wsUrls != null && !wsUrls.isEmpty())
188     {
189       Cache.setProperty(SLIVKA_HOST_URLS, String.join(",", wsUrls));
190     }
191     else
192     {
193       Cache.removeProperty(SLIVKA_HOST_URLS);
194     }
195   }
196
197   @Override
198   public List<String> getServiceUrls()
199   {
200     String surls = Cache.getDefault(SLIVKA_HOST_URLS, COMPBIO_SLIVKA);
201     String[] urls = surls.split(",");
202     ArrayList<String> valid = new ArrayList<>(urls.length);
203     for (String url : urls)
204     {
205       try
206       {
207         new URL(url);
208         valid.add(url);
209       } catch (MalformedURLException e)
210       {
211         Cache.log.warn("Problem whilst trying to make a URL from '"
212             + ((url != null) ? url : "<null>") + "'");
213         Cache.log.warn(
214             "This was probably due to a malformed comma separated list"
215                 + " in the " + SLIVKA_HOST_URLS
216                 + " entry of $(HOME)/.jalview_properties)");
217         Cache.log.debug("Exception was ", e);
218       }
219     }
220     return valid;
221   }
222
223   @Override
224   public boolean testServiceUrl(URL url)
225   {
226     return getServerStatusFor(url.toString()) == STATUS_OK;
227   }
228
229   @Override
230   public int getServerStatusFor(String url)
231   {
232     try
233     {
234       List<?> services = new SlivkaClient(url).getServices();
235       return services.isEmpty() ? STATUS_NO_SERVICES : STATUS_OK;
236     } catch (IOException e)
237     {
238       Cache.log.error("Slivka could not retrieve services list", e);
239       return STATUS_INVALID;
240     }
241   }
242
243   @Override
244   public String getErrorMessages()
245   {
246     // TODO Auto-generated method stub
247     return "";
248   }
249 }