JAL-1137 JAL-975 simpler menu for the AACon service - allows user to switch calculati...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Tue, 7 Aug 2012 15:46:35 +0000 (16:46 +0100)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Tue, 7 Aug 2012 15:46:35 +0000 (16:46 +0100)
src/jalview/ws/jws2/Jws2Discoverer.java
src/jalview/ws/jws2/SequenceAnnotationWSClient.java

index 96a6f6b..a727485 100644 (file)
@@ -32,9 +32,11 @@ import java.beans.PropertyChangeListener;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.Vector;
 
@@ -266,7 +268,9 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     // dynamically regenerate service list.
     populateWSMenuEntry(wsmenu, alignFrame, null);
   }
-
+  private boolean isRecalculable(String action) {
+    return (action!=null && action.equalsIgnoreCase("conservation"));
+  }
   private void populateWSMenuEntry(JMenu jws2al, final AlignFrame alignFrame, String typeFilter)
   {
     if (running || services == null || services.size() == 0)
@@ -280,13 +284,130 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
      * for moment we keep them separate.
      */
     JMenu atpoint;
-    MsaWSClient msacl = new MsaWSClient();
-    Vector hostLabels = new Vector();
+    List<Jws2Instance> enumerableServices=new ArrayList<Jws2Instance>();
     //jws2al.removeAll();
-    Hashtable<String,String> lasthostFor = new Hashtable<String,String>();
+    Map<String, Jws2Instance> preferredHosts=new HashMap<String,Jws2Instance>();
+    Map<String, List<Jws2Instance>> alternates = new HashMap<String, List<Jws2Instance>>();
+    for (Jws2Instance service : services.toArray(new Jws2Instance[0]))
+    {
+      if (!isRecalculable(service.action)) {
+        // add 'one shot' services to be displayed using the classic menu structure
+        enumerableServices.add(service);
+      } else {
+        if (!preferredHosts.containsKey(service.serviceType))
+        {
+          Jws2Instance preferredInstance = getPreferredServiceFor(alignFrame,
+                  service.serviceType);
+          if (preferredInstance != null)
+          {
+            preferredHosts.put(service.serviceType, preferredInstance);
+          }
+          else
+          {
+            preferredHosts.put(service.serviceType, service);
+          }
+        }
+        List<Jws2Instance> ph=alternates.get(service.serviceType);
+        if (preferredHosts.get(service.serviceType)!=service)
+        {
+          if (ph==null)
+          {
+            ph=new ArrayList<Jws2Instance>();
+          }
+          ph.add(service);
+          alternates.put(service.serviceType, ph);
+        }
+      }
+
+    }
+
+    // create GUI element for classic services
+    addEnumeratedServices(jws2al, alignFrame, enumerableServices);
+    // and the instantaneous services
+    for (final Jws2Instance service : preferredHosts.values())
+    {
+      atpoint = JvSwingUtils.findOrCreateMenu(jws2al,service.action);
+      JMenuItem hitm;
+      if (atpoint.getItemCount()>1) {
+        // previous service of this type already present
+        atpoint.addSeparator();
+      }
+      atpoint.add(hitm = new JMenuItem(service.getHost()));
+      hitm.setForeground(Color.blue);
+      hitm.addActionListener(new ActionListener()
+      {
+
+        @Override
+        public void actionPerformed(ActionEvent e)
+        {
+          Desktop.showUrl(service.getHost());
+        }
+      });
+      hitm.setToolTipText(JvSwingUtils
+              .wrapTooltip("Opens the JABAWS server's homepage in web browser"));
+
+      service.attachWSMenuEntry(atpoint, alignFrame);
+      if (alternates.containsKey(service.serviceType))
+      {
+        atpoint.add(hitm=new JMenu("Switch server"));
+        hitm.setToolTipText(JvSwingUtils.wrapTooltip("Choose a server for running this service"));
+        for (final Jws2Instance sv:alternates.get(service.serviceType))
+        {
+          JMenuItem itm;
+          hitm.add(itm=new JMenuItem(sv.getHost()));
+          itm.setForeground(Color.blue);
+          itm.addActionListener(new ActionListener()
+          {
+
+            @Override
+            public void actionPerformed(ActionEvent arg0)
+            {
+              new Thread(new Runnable() { 
+                public void run() {
+                  setPreferredServiceFor(alignFrame, sv.serviceType, sv.action, sv);
+                  changeSupport.firePropertyChange("services", new Vector(), services);
+                };
+              }).start();
+
+            }
+          });
+        }
+        /*hitm.addActionListener(new ActionListener()
+              {
+
+                @Override
+                public void actionPerformed(ActionEvent arg0)
+                {
+                  new Thread(new Runnable() {
+                    @Override
+                    public void run()
+                    {
+                      new SetPreferredServer(alignFrame, service.serviceType, service.action);
+                    }
+                  }).start();
+                }
+              });*/
+      }
+    }
+  }
+  /**
+   * add services using the Java 2.5/2.6/2.7 system which optionally creates submenus to index by host and service program type
+   */
+  private void addEnumeratedServices(final JMenu jws2al, final AlignFrame alignFrame, List<Jws2Instance> enumerableServices)
+  {
+      boolean byhost = Cache.getDefault("WSMENU_BYHOST", false), bytype = Cache
+              .getDefault("WSMENU_BYTYPE", false);
+      /**
+       * eventually, JWS2 services will appear under the same align/etc submenus.
+       * for moment we keep them separate.
+       */
+      JMenu atpoint;
+      MsaWSClient msacl = new MsaWSClient();
+      Vector hostLabels = new Vector();
+        Hashtable<String,String> lasthostFor = new Hashtable<String,String>();
     Hashtable<String, ArrayList<Jws2Instance>> hosts = new Hashtable<String, ArrayList<Jws2Instance>>();
     ArrayList<String> hostlist=new ArrayList<String>();
-    for (Jws2Instance service : services)
+    for (Jws2Instance service : enumerableServices)
     {
       ArrayList<Jws2Instance> hostservices = hosts.get(service.getHost());
       if (hostservices == null)
@@ -378,9 +499,7 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
          */
       }
     }
-
   }
-
   public static void main(String[] args)
   {
     if (args.length>0)
@@ -732,4 +851,71 @@ public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
     }
     return match;
   }
+  
+  Map<String, Map<String, String>> preferredServiceMap = new HashMap<String, Map<String, String>>();
+;
+
+  /**
+   * get current preferred service of the given type, or global default
+   * @param af null or a specific alignFrame 
+   * @param serviceType Jws2Instance.serviceType for service
+   * @return null if no service of this type is available, the preferred service for the serviceType and af if specified and if defined. 
+   */
+  public Jws2Instance getPreferredServiceFor(AlignFrame af,
+          String serviceType)
+  {
+    String serviceurl = null;
+    synchronized (preferredServiceMap)
+    {
+      String afid = (af == null) ? "" : af.getViewport().getSequenceSetId();
+      Map<String, String> prefmap = preferredServiceMap.get(afid);
+      if (afid.length() > 0 && prefmap == null)
+      {
+        // recover global setting, if any
+        prefmap = preferredServiceMap.get("");
+      }
+        if (prefmap != null)
+        {
+          serviceurl = prefmap.get(serviceType);
+        }
+      
+    }
+    Jws2Instance response = null;
+    for (Jws2Instance svc : services)
+    {
+      if (svc.serviceType.equals(serviceType))
+      {
+        if (serviceurl == null || serviceurl.equals(svc.getHost()))
+        {
+          response = svc;
+          break;
+        }
+      }
+    }
+    return response;
+  }
+
+  public void setPreferredServiceFor(AlignFrame af, String serviceType,
+          String serviceAction, Jws2Instance selectedServer)
+  {
+    String afid = (af == null) ? "" : af.getViewport().getSequenceSetId();
+    if (preferredServiceMap == null)
+    {
+      preferredServiceMap = new HashMap<String, Map<String, String>>();
+    }
+    Map<String, String> prefmap = preferredServiceMap.get(afid);
+    if (prefmap == null)
+    {
+      prefmap = new HashMap<String, String>();
+      preferredServiceMap.put(afid, prefmap);
+    }
+    prefmap.put(serviceType, selectedServer.getHost());
+    prefmap.put(serviceAction, selectedServer.getHost());
+  }
+
+  public void setPreferredServiceFor(String serviceType,
+          String serviceAction, Jws2Instance selectedServer)
+  {
+    setPreferredServiceFor(null, serviceType, serviceAction, selectedServer);
+  }
 }
index e629503..d72681d 100644 (file)
@@ -19,6 +19,7 @@ import javax.swing.event.MenuListener;
 import compbio.metadata.Argument;
 
 import jalview.api.AlignCalcWorkerI;
+import jalview.bin.Cache;
 import jalview.datamodel.AlignmentView;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
@@ -29,10 +30,10 @@ import jalview.ws.jws2.jabaws2.Jws2Instance;
 import jalview.ws.params.WsParamSetI;
 
 /**
- * @author jimp
+ * @author jprocter 
  * 
  */
-public class SequenceAnnotationWSClient extends Jws2Client
+public class SequenceAnnotationWSClient extends Jws2Client 
 {
 
   public static final String AAConsCalcId = "jabaws2.AACons";
@@ -51,7 +52,7 @@ public class SequenceAnnotationWSClient extends Jws2Client
     super(alignFrame, preset, null);
     initSequenceAnnotationWSClient(sh, alignFrame, preset, editParams);
   }
-  
+
   public void initSequenceAnnotationWSClient(final Jws2Instance sh,
           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
   {
@@ -82,8 +83,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
                 .getViewport()
                 .getCalcManager()
                 .registerWorker(
-                        worker = new AAConsClient(sh, alignFrame, this.preset,
-                                paramset));
+                        worker = new AAConsClient(sh, alignFrame,
+                                this.preset, paramset));
         alignFrame.getViewport().getCalcManager().startWorker(worker);
 
       }
@@ -129,7 +130,8 @@ public class SequenceAnnotationWSClient extends Jws2Client
           AlignFrame alignFrame, boolean b)
   {
     super(alignFrame, fave.getPreset(), fave.getJobArgset());
-    initSequenceAnnotationWSClient(fave.getService(), alignFrame, fave.getPreset(), b);
+    initSequenceAnnotationWSClient(fave.getService(), alignFrame,
+            fave.getPreset(), b);
   }
 
   /*
@@ -213,8 +215,6 @@ public class SequenceAnnotationWSClient extends Jws2Client
           AAeditSettings = "Change AACons Settings...",
           AAeditSettingsTooltip = "Modify settings for AACons calculations.";
 
-  private SequenceAnnotationWSClient preferredAAConsClient = null;
-
   // private final enableAAConsCalculation(final AlignFrame alignFrame, )
   private void registerAAConsWSInstance(final JMenu wsmenu,
           final Jws2Instance service, final AlignFrame alignFrame)
@@ -230,8 +230,32 @@ public class SequenceAnnotationWSClient extends Jws2Client
         _aaConsEnabled = (JCheckBoxMenuItem) item;
       }
     }
+    // is there an aaCons worker already present - if so, set it to use the
+    // given service handle
+    {
+      List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
+              .getCalcManager()
+              .getRegisteredWorkersOfClass(AAConsClient.class);
+      if (aaconsClient != null && aaconsClient.size() > 0)
+      {
+        AAConsClient worker = (AAConsClient) aaconsClient.get(0);
+        if (!worker.service.hosturl.equals(service.hosturl))
+        {
+         // javax.swing.SwingUtilities.invokeLater(new Runnable()
+          {
+         //   @Override
+         //   public void run()
+            {
+              removeCurrentAAConsWorkerFor(alignFrame);
+              buildCurrentAAConsWorkerFor(alignFrame, service);
+            }
+          }//);
+        }
+      }
+    }
 
-    // is there a service already registered ?
+    // is there a service already registered ? there shouldn't be if we are
+    // being called correctly
     if (_aaConsEnabled == null)
     {
       final JCheckBoxMenuItem aaConsEnabled = new JCheckBoxMenuItem(
@@ -312,56 +336,101 @@ public class SequenceAnnotationWSClient extends Jws2Client
       wsmenu.add(modifyParams);
 
     }
-
   }
 
   private static void showAAConsAnnotationSettingsFor(AlignFrame alignFrame)
   {
     /*
-     * preferred settings
-     * Whether AACons is automatically recalculated
-     * Which AACons server to use
-     * What parameters to use
+     * preferred settings Whether AACons is automatically recalculated Which
+     * AACons server to use What parameters to use
      */
     // could actually do a class search for this too
-    AAConsSettings fave= (AAConsSettings) alignFrame.getViewport().getCalcIdSettingsFor(AAConsCalcId);
-    if (fave==null)
+    AAConsSettings fave = (AAConsSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConsCalcId);
+    if (fave == null)
     {
       fave = createDefaultAAConsSettings();
     }
     new SequenceAnnotationWSClient(fave, alignFrame, true);
 
   }
+
   private static void buildCurrentAAConsWorkerFor(AlignFrame alignFrame)
   {
+    buildCurrentAAConsWorkerFor(alignFrame, null);
+  }
+
+  private static void buildCurrentAAConsWorkerFor(AlignFrame alignFrame,
+          Jws2Instance service)
+  {
     /*
-     * preferred settings
-     * Whether AACons is automatically recalculated
-     * Which AACons server to use
-     * What parameters to use
+     * preferred settings Whether AACons is automatically recalculated Which
+     * AACons server to use What parameters to use
      */
-    AAConsSettings fave= (AAConsSettings) alignFrame.getViewport().getCalcIdSettingsFor(AAConsCalcId);
-    if (fave==null)
+    AAConsSettings fave = (AAConsSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConsCalcId);
+    if (fave == null)
     {
-      fave = createDefaultAAConsSettings();
+      fave = createDefaultAAConsSettings(service);
+    }
+    else
+    {
+      if (service != null
+              && !fave.getService().hosturl.equals(service.hosturl))
+      {
+        Cache.log.debug("Changing AACons service to " + service.hosturl
+                + " from " + fave.getService().hosturl);
+        fave.setService(service);
+      }
     }
     new SequenceAnnotationWSClient(fave, alignFrame, false);
   }
 
   private static AAConsSettings createDefaultAAConsSettings()
   {
-    Jws2Instance service=null;
-    // set sensible defaults
-    for (Jws2Instance sv: Jws2Discoverer.getDiscoverer().getServices()) {
-      if (sv.serviceType.toString().equals(compbio.ws.client.Services.AAConWS.toString()))
+    return createDefaultAAConsSettings(null);
+  }
+
+  private static AAConsSettings createDefaultAAConsSettings(
+          Jws2Instance service)
+  {
+    if (service != null)
+    {
+      if (!service.serviceType.toString().equals(
+              compbio.ws.client.Services.AAConWS.toString()))
+      {
+        Cache.log
+                .warn("Ignoring invalid preferred service for AACons calculations (service type was "
+                        + service.serviceType + ")");
+        service = null;
+      }
+      else
       {
-        service = sv;
-        break;
+        // check service is actually in the list of currently avaialable
+        // services
+        if (!Jws2Discoverer.getDiscoverer().getServices().contains(service))
+        {
+          // it isn't ..
+          service = null;
+        }
       }
     }
-    if (service==null)
+    if (service == null)
+    {
+      // get the default service for AACons
+      service = Jws2Discoverer.getDiscoverer().getPreferredServiceFor(null,
+              compbio.ws.client.Services.AAConWS.toString());
+      /*
+       * for (Jws2Instance sv : Jws2Discoverer.getDiscoverer().getServices()) {
+       * if (sv.serviceType.toString().equals(
+       * compbio.ws.client.Services.AAConWS.toString())) { service = sv; break;
+       * } }
+       */
+    }
+    if (service == null)
     {
-      // TODO raise dialog box explaining error, and/or open the JABA preferences menu.
+      // TODO raise dialog box explaining error, and/or open the JABA
+      // preferences menu.
       throw new Error("No AACons service found.");
     }
     return new AAConsSettings(true, service, null, null);