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