Merge commit 'alpha/update_2_12_for_2_11_2_series_merge^2' into HEAD
[jalview.git] / src / jalview / ws / jws2 / SequenceAnnotationWSClient.java
index 46c04e5..39217bb 100644 (file)
@@ -1,37 +1,50 @@
-/**
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
  * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
  */
 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.AAConsSettings;
-import jalview.ws.jws2.jabaws2.Jws2Instance;
+import jalview.util.MessageManager;
+import jalview.ws.api.ServiceWithParameters;
+import jalview.ws.params.AutoCalcSetting;
 import jalview.ws.params.WsParamSetI;
+import jalview.ws.uimodel.AlignAnalysisUIText;
 
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.util.List;
+import java.util.Locale;
+
 
-import javax.swing.JCheckBoxMenuItem;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
-import javax.swing.JOptionPane;
-import javax.swing.event.MenuEvent;
-import javax.swing.event.MenuListener;
 
 /**
- * @author jprocter 
+ * @author jprocter
  * 
  */
-public class SequenceAnnotationWSClient extends Jws2Client 
+public class SequenceAnnotationWSClient extends Jws2Client
 {
-
-  public static final String AAConsCalcId = "jabaws2.AACons";
-
   /**
    * initialise a client so its attachWSMenuEntry method can be called.
    */
@@ -40,90 +53,127 @@ public class SequenceAnnotationWSClient extends Jws2Client
     // TODO Auto-generated constructor stub
   }
 
-  public SequenceAnnotationWSClient(final Jws2Instance sh,
+  public SequenceAnnotationWSClient(final ServiceWithParameters sh,
           AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
   {
     super(alignFrame, preset, null);
     initSequenceAnnotationWSClient(sh, alignFrame, preset, editParams);
   }
 
-  public void initSequenceAnnotationWSClient(final Jws2Instance sh,
-          AlignFrame alignFrame, WsParamSetI preset, boolean editParams)
+  // dan think. Do I need to change this method to run RNAalifold through the
+  // GUI
+
+  private void initSequenceAnnotationWSClient(final ServiceWithParameters sh,
+      AlignFrame alignFrame, final WsParamSetI preset, boolean editParams)
   {
-    if (alignFrame.getViewport().getAlignment().isNucleotide())
+    // dan changed! dan test. comment out if conditional
+    // if (alignFrame.getViewport().getAlignment().isNucleotide())
+    // {
+    // JvOptionPane.showMessageDialog(Desktop.desktop, sh.serviceType
+    // + " can only be used\nfor amino acid alignments.",
+    // "Wrong type of sequences!", JvOptionPane.WARNING_MESSAGE);
+    // return;
+    //
+    // }
+    AlignAnalysisUIText aaui = sh.getAlignAnalysisUI();
+    if (aaui != null)
     {
-      JOptionPane.showMessageDialog(Desktop.desktop, sh.serviceType
-              + " can only be used\nfor amino acid alignments.",
-              "Wrong type of sequences!", JOptionPane.WARNING_MESSAGE);
-      return;
+      Class clientClass = aaui.getClient();
 
-    }
-    if (sh.action.toLowerCase().contains("conservation"))
-    {
-      // Build an AACons style client - take alignment, return annotation for
+      // Build an AACon style client - take alignment, return annotation for
       // columns
 
       List<AlignCalcWorkerI> clnts = alignFrame.getViewport()
-              .getCalcManager()
-              .getRegisteredWorkersOfClass(AAConsClient.class);
-      if (clnts == null || clnts.size() == 0)
+          .getCalcManager()
+          .getWorkersOfClass(SeqAnnotationServiceCalcWorker.class);
+
+      SeqAnnotationServiceCalcWorker tmpworker = null;
+      if (clnts != null)
       {
-        if (!processParams(sh, editParams))
+        for (AlignCalcWorkerI _worker : clnts)
         {
-          return;
+          tmpworker = (SeqAnnotationServiceCalcWorker) _worker;
+          if (tmpworker.hasService()
+              && tmpworker.getService().getClass().equals(clientClass))
+          {
+            break;
+          }
+          tmpworker = null;
         }
-        AAConsClient worker;
-        alignFrame
-                .getViewport()
-                .getCalcManager()
-                .registerWorker(
-                        worker = new AAConsClient(sh, alignFrame,
-                                this.preset, paramset));
-        alignFrame.getViewport().getCalcManager().startWorker(worker);
+      }
+      final var worker = tmpworker;
+      if (worker == null)
+      {
+        processParams(sh, editParams).thenAccept((startJob) -> {
+          if (startJob)
+          {
+            final SeqAnnotationServiceCalcWorker worker_;
+            try
+            {
+              worker_ = new SeqAnnotationServiceCalcWorker(sh, alignFrame, this.preset,
+                  paramset);
+            } catch (Exception x)
+            {
+              x.printStackTrace();
+              throw new Error(
+                  MessageManager.getString("error.implementation_error"),
+                  x);
+            }
+            alignFrame.getViewport().getCalcManager().registerWorker(worker_);
+                // also starts the worker
+            startSeqAnnotationWorker(sh, alignFrame, preset, editParams);
+          }
+        });
 
       }
       else
       {
-        AAConsClient worker = (AAConsClient) clnts.get(0);
+        WsParamSetI preset_;
         if (editParams)
         {
           paramset = worker.getArguments();
-          preset = worker.getPreset();
+          preset_ = worker.getPreset();
         }
+        else
+        {
+          preset_ = preset;
+        }
+        processParams(sh, editParams, true).thenAccept((startJob) -> {
+          if (startJob)
+          {
+            // reinstate worker if it was blacklisted (might have happened due
+            // to
+            // invalid parameters)
+            alignFrame.getViewport().getCalcManager().enableWorker(worker);
+            worker.updateParameters(this.preset, paramset);
+            startSeqAnnotationWorker(sh, alignFrame, preset_, editParams);
+          }
+        });
 
-        if (!processParams(sh, editParams, true))
+        if (!processParams(sh, editParams, true).toCompletableFuture().join())
         {
           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"))
+    if (sh.action.toLowerCase(Locale.ROOT).contains("disorder"))
     {
       // build IUPred style client. take sequences, returns annotation per
       // sequence.
-      if (!processParams(sh, editParams))
-      {
-        return;
-      }
-
-      alignFrame
-              .getViewport()
-              .getCalcManager()
-              .startWorker(
-                      new AADisorderClient(sh, alignFrame, preset, paramset));
+      processParams(sh, editParams).thenAccept((startJob) -> {
+        if (startJob)
+        {
+          alignFrame.getViewport().getCalcManager().startWorker(
+              new SeqAnnotationServiceCalcWorker(sh, alignFrame, preset, paramset));
+        }
+      });
     }
-
   }
 
-  public SequenceAnnotationWSClient(AAConsSettings fave,
+  public SequenceAnnotationWSClient(AutoCalcSetting fave,
           AlignFrame alignFrame, boolean b)
   {
-    super(alignFrame, fave.getPreset(), fave.getJobArgset());
+    super(alignFrame, fave.getPreset(), fave.getArgumentSet());
     initSequenceAnnotationWSClient(fave.getService(), alignFrame,
             fave.getPreset(), b);
   }
@@ -134,64 +184,81 @@ public class SequenceAnnotationWSClient extends Jws2Client
    * @see jalview.ws.jws2.Jws2Client#attachWSMenuEntry(javax.swing.JMenu,
    * jalview.ws.jws2.jabaws2.Jws2Instance, jalview.gui.AlignFrame)
    */
-  public void attachWSMenuEntry(JMenu wsmenu, final Jws2Instance service,
+  @Override
+  public void attachWSMenuEntry(JMenu wsmenu,
+          final ServiceWithParameters service,
           final AlignFrame alignFrame)
   {
-    if (service.serviceType.equals(compbio.ws.client.Services.AAConWS
-            .toString()))
+    if (Jws2ClientFactory.registerAAConWSInstance(wsmenu,
+            service, alignFrame))
     {
-      registerAAConsWSInstance(wsmenu, service, alignFrame);
+      // Alignment dependent analysis calculation WS gui
       return;
     }
     boolean hasparams = service.hasParameters();
-    // Assume name ends in WS
-    String calcName = service.serviceType.substring(0,
-            service.serviceType.length() - 2);
+    String calcName = service.getName();
+    if (calcName.endsWith("WS"))
+    {
+      // Remove "WS" suffix
+      calcName = calcName.substring(0, calcName.length() - 2);
+    }
 
-    JMenuItem aacons = new JMenuItem(calcName + " Defaults");
-    aacons.addActionListener(new ActionListener()
+    JMenuItem annotservice = new JMenuItem(MessageManager.formatMessage(
+            "label.calcname_with_default_settings", new String[]
+            { calcName }));
+    annotservice.addActionListener(new ActionListener()
     {
 
       @Override
       public void actionPerformed(ActionEvent e)
       {
-        new SequenceAnnotationWSClient(service, alignFrame, null, false);
+        new SequenceAnnotationWSClient(service, alignFrame,
+                null, false);
       }
     });
-    wsmenu.add(aacons);
+    wsmenu.add(annotservice);
     if (hasparams)
     {
       // only add these menu options if the service has user-modifiable
       // arguments
-      aacons = new JMenuItem("Edit settings and run ...");
-      aacons.setToolTipText("View and change parameters before running calculation");
+      annotservice = new JMenuItem(
+              MessageManager.getString("label.edit_settings_and_run"));
+      annotservice.setToolTipText(MessageManager.getString(
+              "label.view_and_change_parameters_before_running_calculation"));
 
-      aacons.addActionListener(new ActionListener()
+      annotservice.addActionListener(new ActionListener()
       {
+        @Override
         public void actionPerformed(ActionEvent e)
         {
-          new SequenceAnnotationWSClient(service, alignFrame, null, true);
+          new SequenceAnnotationWSClient(service, alignFrame,
+                  null, true);
         }
       });
-      wsmenu.add(aacons);
+      wsmenu.add(annotservice);
       List<WsParamSetI> presets = service.getParamStore().getPresets();
       if (presets != null && presets.size() > 0)
       {
-        JMenu presetlist = new JMenu("Run " + calcName + "with preset");
+        JMenu presetlist = new JMenu(MessageManager
+                .formatMessage("label.run_with_preset", new String[]
+                { calcName }));
 
         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.setToolTipText(JvSwingUtils.wrapTooltip(true, "<strong>"
+                  + (preset.isModifiable()
+                          ? MessageManager.getString("label.user_preset")
+                          : MessageManager
+                                  .getString("label.service_preset"))
+                  + "</strong><br/>" + preset.getDescription()));
           methodR.addActionListener(new ActionListener()
           {
+            @Override
             public void actionPerformed(ActionEvent e)
             {
-              new SequenceAnnotationWSClient(service, alignFrame, preset,
+              new SequenceAnnotationWSClient(service,
+                      alignFrame, preset,
                       false);
             }
 
@@ -201,256 +268,29 @@ public class SequenceAnnotationWSClient extends Jws2Client
         wsmenu.add(presetlist);
       }
 
-    } else {
-      aacons = new JMenuItem("View documentation");
-      if (service.docUrl!=null)
-      {
-        aacons.addActionListener(new ActionListener()
-        {
-          
-          @Override
-          public void actionPerformed(ActionEvent arg0)
-          {
-            Desktop.instance.showUrl(service.docUrl);
-          }
-        });
-        aacons.setToolTipText("<html>"+JvSwingUtils.wrapTooltip("View <a href=\""+service.docUrl+"\">"+service.docUrl+"</a>")+"</html>");
-        wsmenu.add(aacons);
-      }
-    }
-  }
-
-  private final String AAconsToggle = "AACons Calculations",
-          AAconsToggleTooltip = "When checked, AACons calculations are updated automatically.",
-          AAeditSettings = "Change AACons Settings...",
-          AAeditSettingsTooltip = "Modify settings for AACons calculations.";
-
-  // private final enableAAConsCalculation(final AlignFrame alignFrame, )
-  private void registerAAConsWSInstance(final JMenu wsmenu,
-          final Jws2Instance service, final AlignFrame alignFrame)
-  {
-    // register this in the AACons settings set
-    JCheckBoxMenuItem _aaConsEnabled = null;
-    for (int i = 0; i < wsmenu.getItemCount(); i++)
-    {
-      JMenuItem item = wsmenu.getItem(i);
-      if (item instanceof JCheckBoxMenuItem
-              && item.getText().equals(AAconsToggle))
-      {
-        _aaConsEnabled = (JCheckBoxMenuItem) item;
-      }
     }
-    // is there an aaCons worker already present - if so, set it to use the
-    // given service handle
+    else
     {
-      List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
-              .getCalcManager()
-              .getRegisteredWorkersOfClass(AAConsClient.class);
-      if (aaconsClient != null && aaconsClient.size() > 0)
+      annotservice = new JMenuItem(
+              MessageManager.getString("label.view_documentation"));
+      if (service != null && service.hasDocumentationUrl())
       {
-        AAConsClient worker = (AAConsClient) aaconsClient.get(0);
-        if (!worker.service.hosturl.equals(service.hosturl))
+        annotservice.addActionListener(new ActionListener()
         {
-         // javax.swing.SwingUtilities.invokeLater(new Runnable()
-          {
-         //   @Override
-         //   public void run()
-            {
-              removeCurrentAAConsWorkerFor(alignFrame);
-              buildCurrentAAConsWorkerFor(alignFrame, service);
-            }
-          }//);
-        }
-      }
-    }
-
-    // is there a service already registered ? there shouldn't be if we are
-    // being called correctly
-    if (_aaConsEnabled == null)
-    {
-      final JCheckBoxMenuItem aaConsEnabled = new JCheckBoxMenuItem(
-              AAconsToggle);
-      wsmenu.addMenuListener(new MenuListener()
-      {
 
-        @Override
-        public void menuSelected(MenuEvent arg0)
-        {
-          wsmenu.setEnabled(!alignFrame.getViewport().getAlignment()
-                  .isNucleotide());
-          List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
-                  .getCalcManager()
-                  .getRegisteredWorkersOfClass(AAConsClient.class);
-          if (aaconsClient != null && aaconsClient.size() > 0)
-          {
-            aaConsEnabled.setSelected(true);
-          }
-          else
-          {
-            aaConsEnabled.setSelected(false);
-          }
-        }
-
-        @Override
-        public void menuDeselected(MenuEvent arg0)
-        {
-          // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        public void menuCanceled(MenuEvent arg0)
-        {
-          // TODO Auto-generated method stub
-
-        }
-      });
-      aaConsEnabled.setToolTipText("<html><p>"
-              + JvSwingUtils.wrapTooltip(AAconsToggleTooltip + "</p>")
-              + "</html>");
-      aaConsEnabled.addActionListener(new ActionListener()
-      {
-        @Override
-        public void actionPerformed(ActionEvent arg0)
-        {
-          // aaConsEnabled.setSelected(!aaConsEnabled.isSelected());
-          List<AlignCalcWorkerI> aaconsClient = alignFrame.getViewport()
-                  .getCalcManager()
-                  .getRegisteredWorkersOfClass(AAConsClient.class);
-          if (aaconsClient != null && aaconsClient.size() > 0)
-          {
-            removeCurrentAAConsWorkerFor(alignFrame);
-          }
-          else
+          @Override
+          public void actionPerformed(ActionEvent arg0)
           {
-            buildCurrentAAConsWorkerFor(alignFrame);
-
+            Desktop.getInstance().showUrl(service.getDocumentationUrl());
           }
-        }
-
-      });
-      wsmenu.add(aaConsEnabled);
-      JMenuItem modifyParams = new JMenuItem(AAeditSettings);
-      modifyParams.setToolTipText("<html><p>"
-              + JvSwingUtils.wrapTooltip(AAeditSettingsTooltip + "</p>")
-              + "</html>");
-      modifyParams.addActionListener(new ActionListener()
-      {
-
-        @Override
-        public void actionPerformed(ActionEvent arg0)
-        {
-          showAAConsAnnotationSettingsFor(alignFrame);
-        }
-      });
-      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
-     */
-    // could actually do a class search for this too
-    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
-     */
-    AAConsSettings fave = (AAConsSettings) alignFrame.getViewport()
-            .getCalcIdSettingsFor(AAConsCalcId);
-    if (fave == null)
-    {
-      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()
-  {
-    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
-      {
-        // check service is actually in the list of currently avaialable
-        // services
-        if (!Jws2Discoverer.getDiscoverer().getServices().contains(service))
-        {
-          // it isn't ..
-          service = null;
-        }
+        });
+        annotservice.setToolTipText(
+                JvSwingUtils.wrapTooltip(true, MessageManager.formatMessage(
+                        "label.view_service_doc_url", new String[]
+                        { service.getDocumentationUrl(),
+                            service.getDocumentationUrl() })));
+        wsmenu.add(annotservice);
       }
     }
-    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.
-      throw new Error("No AACons service found.");
-    }
-    return new AAConsSettings(true, service, null, null);
-  }
-
-  private static void removeCurrentAAConsWorkerFor(AlignFrame alignFrame)
-  {
-    alignFrame.getViewport().getCalcManager()
-            .removeRegisteredWorkersOfClass(AAConsClient.class);
-    // AAConsClient.removeAAConsAnnotation(alignFrame.alignPanel);
-
   }
 }