JAL-3690 alternative servers menu fix
[jalview.git] / src / jalview / ws / slivkaws / SlivkaWSDiscoverer.java
index 7a41431..cd296c6 100644 (file)
@@ -1,21 +1,22 @@
 package jalview.ws.slivkaws;
 
 import jalview.bin.Cache;
-import jalview.gui.AlignFrame;
+import jalview.ws.ServiceChangeListener;
 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.URL;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-
-import javax.swing.JMenu;
-
+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 uk.ac.dundee.compbio.slivkaclient.SlivkaClient;
 import uk.ac.dundee.compbio.slivkaclient.SlivkaService;
 
@@ -42,78 +43,46 @@ public class SlivkaWSDiscoverer implements WSDiscovererI
     return instance;
   }
 
-  private PropertyChangeSupport changeSupport = new PropertyChangeSupport(
-      this);
+  private Set<ServiceChangeListener> serviceListeners = new CopyOnWriteArraySet<>();
 
   @Override
-  public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
+  public void addServiceChangeListener(ServiceChangeListener l)
   {
-    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);
-
+    serviceListeners.add(l);
   }
 
-  volatile boolean ready = false;
-
-  volatile Thread discovererThread = null;
-
-  private class DiscovererThread extends Thread
+  @Override
+  public void removeServiceChangeListener(ServiceChangeListener l)
   {
-    private Thread oldThread;
-
-    DiscovererThread(Thread oldThread)
-    {
-      super();
-      this.oldThread = oldThread;
-    }
+    serviceListeners.remove(l);
+  }
 
-    @Override
-    public void run()
+  public void notifyServiceListeners(List<ServiceWithParameters> services)
+  {
+    for (var listener : serviceListeners)
     {
-      if (oldThread != null)
-      {
-        oldThread.interrupt();
-        try
-        {
-          oldThread.join();
-        } catch (InterruptedException e)
-        {
-          return;
-        } finally
-        {
-          oldThread = null;
-        }
-      }
-      ready = false;
-      reloadServices();
-      ready = !isInterrupted();
+      listener.servicesChanged(this, services);
     }
   }
 
-  Thread discoverer = null;
+  private final ExecutorService executor = Executors.newSingleThreadExecutor();
+  private Vector<Future<?>> discoveryTasks = new Vector<>();
 
-  @Override
-  public Thread startDiscoverer(PropertyChangeListener changeListener)
+  public CompletableFuture<WSDiscovererI> startDiscoverer()
   {
-    changeSupport.addPropertyChangeListener(changeListener);
-    ready = false;
-    (discovererThread = new DiscovererThread(discovererThread)).start();
-    return discovererThread;
+    CompletableFuture<WSDiscovererI> task = CompletableFuture
+            .supplyAsync(() -> {
+              reloadServices();
+              return SlivkaWSDiscoverer.this;
+            }, executor);
+    discoveryTasks.add(task);
+    return task;
   }
 
-  private void reloadServices()
+  private List<ServiceWithParameters> reloadServices()
   {
     Cache.log.info("Reloading Slivka services");
-    changeSupport.firePropertyChange("services", services, List.of());
+    notifyServiceListeners(Collections.emptyList());
     ArrayList<ServiceWithParameters> instances = new ArrayList<>();
 
     for (String url : getServiceUrls())
@@ -152,14 +121,15 @@ public class SlivkaWSDiscoverer implements WSDiscovererI
         }
       } catch (IOException e)
       {
+        e.printStackTrace();
         continue;
       }
     }
 
     services = instances;
-    changeSupport.firePropertyChange("services", List.of(), services);
-
+    notifyServiceListeners(instances);
     Cache.log.info("Slivka services reloading finished");
+    return instances;
   }
 
   @Override
@@ -171,14 +141,13 @@ public class SlivkaWSDiscoverer implements WSDiscovererI
   @Override
   public boolean hasServices()
   {
-    return ready == true && services.size() > 0;
+    return !isRunning() && services.size() > 0;
   }
 
   @Override
   public boolean isRunning()
   {
-    return discovererThread == null || discovererThread.isAlive()
-        || discovererThread.getState() == Thread.State.NEW;
+    return !discoveryTasks.stream().allMatch(Future::isDone);
   }
 
   @Override