formatting
[jalview.git] / src / jalview / ws / jws2 / SequenceAnnotationWSClient.java
index 3e4cbe1..bf20cd4 100644 (file)
@@ -3,29 +3,35 @@
  */
 package jalview.ws.jws2;
 
+import jalview.api.AlignCalcWorkerI;
+import jalview.bin.Cache;
+import jalview.gui.AlignFrame;
+import jalview.gui.Desktop;
+import jalview.gui.JvSwingUtils;
+import jalview.ws.jws2.dm.AAConSettings;
+import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.ws.params.WsParamSetI;
+
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.List;
 
+import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-
-import compbio.metadata.Argument;
-
-import jalview.api.AlignCalcWorkerI;
-import jalview.datamodel.AlignmentView;
-import jalview.gui.AlignFrame;
-import jalview.gui.JvSwingUtils;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
-import jalview.ws.params.WsParamSetI;
+import javax.swing.JOptionPane;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
 
 /**
- * @author jimp
+ * @author jprocter
  * 
  */
 public class SequenceAnnotationWSClient extends Jws2Client
 {
 
+  public static final String AAConCalcId = "jabaws2.AACon";
+
   /**
    * initialise a client so its attachWSMenuEntry method can be called.
    */
@@ -38,37 +44,88 @@ public class SequenceAnnotationWSClient extends Jws2Client
           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
   {
     super(alignFrame, preset, null);
-    List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
-            .getCalcManager()
-            .getRegisteredWorkersOfClass(AAConsClient.class);
-    if (clnts == null || clnts.size() == 0)
+    initSequenceAnnotationWSClient(sh, alignFrame, preset, editParams);
+  }
+
+  public void initSequenceAnnotationWSClient(final Jws2Instance sh,
+          AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
+  {
+    if (alignFrame.getViewport().getAlignment().isNucleotide())
+    {
+      JOptionPane.showMessageDialog(Desktop.desktop, sh.serviceType
+              + " can only be used\nfor amino acid alignments.",
+              "Wrong type of sequences!", JOptionPane.WARNING_MESSAGE);
+      return;
+
+    }
+    if (sh.action.toLowerCase().contains("conservation"))
+    {
+      // Build an AACon style client - take alignment, return annotation for
+      // columns
+
+      List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
+              .getCalcManager()
+              .getRegisteredWorkersOfClass(AAConClient.class);
+      if (clnts == null || clnts.size() == 0)
+      {
+        if (!processParams(sh, editParams))
+        {
+          return;
+        }
+        AAConClient worker;
+        alignFrame
+                .getViewport()
+                .getCalcManager()
+                .registerWorker(
+                        worker = new AAConClient(sh, alignFrame,
+                                this.preset, paramset));
+        alignFrame.getViewport().getCalcManager().startWorker(worker);
+
+      }
+      else
+      {
+        AAConClient worker = (AAConClient) clnts.get(0);
+        if (editParams)
+        {
+          paramset = worker.getArguments();
+          preset = worker.getPreset();
+        }
+
+        if (!processParams(sh, editParams, true))
+        {
+          return;
+        }
+        // reinstate worker if it was blacklisted (might have happened due to
+        // invalid parameters)
+        alignFrame.getViewport().getCalcManager().workerMayRun(worker);
+        worker.updateParameters(this.preset, paramset);
+
+      }
+    }
+    if (sh.action.toLowerCase().contains("disorder"))
     {
+      // build IUPred style client. take sequences, returns annotation per
+      // sequence.
       if (!processParams(sh, editParams))
       {
         return;
       }
+
       alignFrame
               .getViewport()
               .getCalcManager()
-              .registerWorker(
-                      new AAConsClient(sh, alignFrame, preset, paramset));
+              .startWorker(
+                      new AADisorderClient(sh, alignFrame, preset, paramset));
     }
-    else
-    {
-      AAConsClient worker = (AAConsClient) clnts.get(0);
-      if (editParams)
-      {
-        paramset = worker.getArguments();
-        preset = worker.getPreset();
-      }
 
-      if (!processParams(sh, editParams, true))
-        return;
-      // reinstate worker if it was blacklisted (might have happened due to invalid parameters)
-      alignFrame.getViewport().getCalcManager().workerMayRun(worker);
-      worker.updateParameters(preset, paramset);
+  }
 
-    }
+  public SequenceAnnotationWSClient(AAConSettings fave,
+          AlignFrame alignFrame, boolean b)
+  {
+    super(alignFrame, fave.getPreset(), fave.getJobArgset());
+    initSequenceAnnotationWSClient(fave.getService(), alignFrame,
+            fave.getPreset(), b);
   }
 
   /*
@@ -80,65 +137,316 @@ public class SequenceAnnotationWSClient extends Jws2Client
   public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
           final AlignFrame alignFrame)
   {
-    if (service.serviceType.toLowerCase().contains("aaconws"))
+    if (service.serviceType.equals(compbio.ws.client.Services.AAConWS
+            .toString()))
+    {
+      registerAAConWSInstance(wsmenu, service, alignFrame);
+      return;
+    }
+    boolean hasparams = service.hasParameters();
+    // Assume name ends in WS
+    String calcName = service.serviceType.substring(0,
+            service.serviceType.length() - 2);
+
+    JMenuItem annotservice = new JMenuItem(calcName + " Defaults");
+    annotservice.addActionListener(new ActionListener()
     {
-      boolean hasparams = service.hasParameters();
-      String calcName = "AACons";
-      System.out.println("Making an aacons client!");
-      JMenuItem aacons = new JMenuItem("AACons Defaults");
-      aacons.addActionListener(new ActionListener()
+
+      @Override
+      public void actionPerformed(ActionEvent e)
       {
+        new SequenceAnnotationWSClient(service, alignFrame, null, false);
+      }
+    });
+    wsmenu.add(annotservice);
+    if (hasparams)
+    {
+      // only add these menu options if the service has user-modifiable
+      // arguments
+      annotservice = new JMenuItem("Edit settings and run ...");
+      annotservice
+              .setToolTipText("View and change parameters before running calculation");
 
-        @Override
+      annotservice.addActionListener(new ActionListener()
+      {
         public void actionPerformed(ActionEvent e)
         {
-          new SequenceAnnotationWSClient(service, alignFrame, null, false);
+          new SequenceAnnotationWSClient(service, alignFrame, null, true);
         }
       });
-      wsmenu.add(aacons);
-      if (hasparams)
+      wsmenu.add(annotservice);
+      List<WsParamSetI> presets = service.getParamStore().getPresets();
+      if (presets != null && presets.size() > 0)
       {
-        // only add these menu options if the service has user-modifiable
-        // arguments
-        aacons = new JMenuItem("Edit settings and run ...");
-        aacons.setToolTipText("View and change the parameters before alignment.");
+        JMenu presetlist = new JMenu("Run " + calcName + "with preset");
+
+        for (final WsParamSetI preset : presets)
+        {
+          final JMenuItem methodR = new JMenuItem(preset.getName());
+          methodR.setToolTipText("<html><p>"
+                  + JvSwingUtils.wrapTooltip("<strong>"
+                          + (preset.isModifiable() ? "User Preset"
+                                  : "Service Preset") + "</strong><br/>"
+                          + preset.getDescription() + "</p>") + "</html>");
+          methodR.addActionListener(new ActionListener()
+          {
+            public void actionPerformed(ActionEvent e)
+            {
+              new SequenceAnnotationWSClient(service, alignFrame, preset,
+                      false);
+            }
+
+          });
+          presetlist.add(methodR);
+        }
+        wsmenu.add(presetlist);
+      }
 
-        aacons.addActionListener(new ActionListener()
+    }
+    else
+    {
+      annotservice = new JMenuItem("View documentation");
+      if (service.docUrl != null)
+      {
+        annotservice.addActionListener(new ActionListener()
         {
-          public void actionPerformed(ActionEvent e)
+
+          @Override
+          public void actionPerformed(ActionEvent arg0)
           {
-            new SequenceAnnotationWSClient(service, alignFrame, null, true);
+            Desktop.instance.showUrl(service.docUrl);
           }
         });
-        wsmenu.add(aacons);
-        List<WsParamSetI> presets = service.getParamStore().getPresets();
-        if (presets != null && presets.size() > 0)
-        {
-          JMenu presetlist = new JMenu("Run " + calcName + "with preset");
+        annotservice.setToolTipText("<html>"
+                + JvSwingUtils.wrapTooltip("View <a href=\""
+                        + service.docUrl + "\">" + service.docUrl + "</a>")
+                + "</html>");
+        wsmenu.add(annotservice);
+      }
+    }
+  }
+
+  private final String AAconToggle = "AACon Calculations",
+          AAconToggleTooltip = "When checked, AACon calculations are updated automatically.",
+          AAeditSettings = "Change AACon Settings...",
+          AAeditSettingsTooltip = "Modify settings for AACon calculations.";
 
-          for (final WsParamSetI preset : presets)
+  private void registerAAConWSInstance(final JMenu wsmenu,
+          final Jws2Instance service, final AlignFrame alignFrame)
+  {
+    // register this in the AACon settings set
+    JCheckBoxMenuItem _aaConEnabled = null;
+    for (int i = 0; i < wsmenu.getItemCount(); i++)
+    {
+      JMenuItem item = wsmenu.getItem(i);
+      if (item instanceof JCheckBoxMenuItem
+              && item.getText().equals(AAconToggle))
+      {
+        _aaConEnabled = (JCheckBoxMenuItem) item;
+      }
+    }
+    // is there an aaCon worker already present - if so, set it to use the
+    // given service handle
+    {
+      List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
+              .getCalcManager()
+              .getRegisteredWorkersOfClass(AAConClient.class);
+      if (aaconClient != null && aaconClient.size() > 0)
+      {
+        AAConClient worker = (AAConClient) aaconClient.get(0);
+        if (!worker.service.hosturl.equals(service.hosturl))
+        {
+          // javax.swing.SwingUtilities.invokeLater(new Runnable()
           {
-            final JMenuItem methodR = new JMenuItem(preset.getName());
-            methodR.setToolTipText("<html><p>"
-                    + JvSwingUtils.wrapTooltip("<strong>"
-                            + (preset.isModifiable() ? "User Preset"
-                                    : "Service Preset") + "</strong><br/>"
-                            + preset.getDescription() + "</p>") + "</html>");
-            methodR.addActionListener(new ActionListener()
+            // @Override
+            // public void run()
             {
-              public void actionPerformed(ActionEvent e)
-              {
-                new SequenceAnnotationWSClient(service, alignFrame, preset,
-                        false);
-              }
-
-            });
-            presetlist.add(methodR);
+              removeCurrentAAConWorkerFor(alignFrame);
+              buildCurrentAAConWorkerFor(alignFrame, service);
+            }
+          }// );
+        }
+      }
+    }
+
+    // is there a service already registered ? there shouldn't be if we are
+    // being called correctly
+    if (_aaConEnabled == null)
+    {
+      final JCheckBoxMenuItem aaConEnabled = new JCheckBoxMenuItem(
+              AAconToggle);
+      wsmenu.addMenuListener(new MenuListener()
+      {
+
+        @Override
+        public void menuSelected(MenuEvent arg0)
+        {
+          wsmenu.setEnabled(!alignFrame.getViewport().getAlignment()
+                  .isNucleotide());
+          List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
+                  .getCalcManager()
+                  .getRegisteredWorkersOfClass(AAConClient.class);
+          if (aaconClient != null && aaconClient.size() > 0)
+          {
+            aaConEnabled.setSelected(true);
+          }
+          else
+          {
+            aaConEnabled.setSelected(false);
+          }
+        }
+
+        @Override
+        public void menuDeselected(MenuEvent arg0)
+        {
+          // TODO Auto-generated method stub
+
+        }
+
+        @Override
+        public void menuCanceled(MenuEvent arg0)
+        {
+          // TODO Auto-generated method stub
+
+        }
+      });
+      aaConEnabled.setToolTipText("<html><p>"
+              + JvSwingUtils.wrapTooltip(AAconToggleTooltip + "</p>")
+              + "</html>");
+      aaConEnabled.addActionListener(new ActionListener()
+      {
+        @Override
+        public void actionPerformed(ActionEvent arg0)
+        {
+          List<AlignCalcWorkerI> aaconClient = alignFrame.getViewport()
+                  .getCalcManager()
+                  .getRegisteredWorkersOfClass(AAConClient.class);
+          if (aaconClient != null && aaconClient.size() > 0)
+          {
+            removeCurrentAAConWorkerFor(alignFrame);
           }
-          wsmenu.add(presetlist);
+          else
+          {
+            buildCurrentAAConWorkerFor(alignFrame);
+
+          }
+        }
+
+      });
+      wsmenu.add(aaConEnabled);
+      JMenuItem modifyParams = new JMenuItem(AAeditSettings);
+      modifyParams.setToolTipText("<html><p>"
+              + JvSwingUtils.wrapTooltip(AAeditSettingsTooltip + "</p>")
+              + "</html>");
+      modifyParams.addActionListener(new ActionListener()
+      {
+
+        @Override
+        public void actionPerformed(ActionEvent arg0)
+        {
+          showAAConAnnotationSettingsFor(alignFrame);
         }
+      });
+      wsmenu.add(modifyParams);
+
+    }
+  }
+
+  private static void showAAConAnnotationSettingsFor(AlignFrame alignFrame)
+  {
+    /*
+     * preferred settings Whether AACon is automatically recalculated Which
+     * AACon server to use What parameters to use
+     */
+    // could actually do a class search for this too
+    AAConSettings fave = (AAConSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConCalcId);
+    if (fave == null)
+    {
+      fave = createDefaultAAConSettings();
+    }
+    new SequenceAnnotationWSClient(fave, alignFrame, true);
+
+  }
+
+  private static void buildCurrentAAConWorkerFor(AlignFrame alignFrame)
+  {
+    buildCurrentAAConWorkerFor(alignFrame, null);
+  }
+
+  private static void buildCurrentAAConWorkerFor(AlignFrame alignFrame,
+          Jws2Instance service)
+  {
+    /*
+     * preferred settings Whether AACon is automatically recalculated Which
+     * AACon server to use What parameters to use
+     */
+    AAConSettings fave = (AAConSettings) alignFrame.getViewport()
+            .getCalcIdSettingsFor(AAConCalcId);
+    if (fave == null)
+    {
+      fave = createDefaultAAConSettings(service);
+    }
+    else
+    {
+      if (service != null
+              && !fave.getService().hosturl.equals(service.hosturl))
+      {
+        Cache.log.debug("Changing AACon service to " + service.hosturl
+                + " from " + fave.getService().hosturl);
+        fave.setService(service);
       }
+    }
+    new SequenceAnnotationWSClient(fave, alignFrame, false);
+  }
+
+  private static AAConSettings createDefaultAAConSettings()
+  {
+    return createDefaultAAConSettings(null);
+  }
 
+  private static AAConSettings createDefaultAAConSettings(
+          Jws2Instance service)
+  {
+    if (service != null)
+    {
+      if (!service.serviceType.toString().equals(
+              compbio.ws.client.Services.AAConWS.toString()))
+      {
+        Cache.log
+                .warn("Ignoring invalid preferred service for AACon calculations (service type was "
+                        + service.serviceType + ")");
+        service = null;
+      }
+      else
+      {
+        // 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)
+    {
+      // get the default service for AACon
+      service = Jws2Discoverer.getDiscoverer().getPreferredServiceFor(null,
+              compbio.ws.client.Services.AAConWS.toString());
     }
+    if (service == null)
+    {
+      // TODO raise dialog box explaining error, and/or open the JABA
+      // preferences menu.
+      throw new Error("No AACon service found.");
+    }
+    return new AAConSettings(true, service, null, null);
+  }
+
+  private static void removeCurrentAAConWorkerFor(AlignFrame alignFrame)
+  {
+    alignFrame.getViewport().getCalcManager()
+            .removeRegisteredWorkersOfClass(AAConClient.class);
   }
 }