tidied the exceptions and ws server error behaviour
[jalview.git] / src / jalview / ws / MsaWSClient.java
index 1fa9dac..faf2faf 100755 (executable)
@@ -16,24 +16,17 @@ import vamsas.objects.*;
 
 
 public class MsaWSClient
+    extends WSClient
 {
-  int jobsRunning = 0;
-  ext.vamsas.MuscleWS server;
-  WebserviceInfo wsInfo;
-  /**
-   * MsaWSClient
-   *
-   * @param msa SequenceI[]
-   */
-
-  String WebServiceName;
-  String WebServiceJobTitle;
-  String WebServiceReference;
-  String WsURL;
+    /**
+     * server is a WSDL2Java generated stub for an archetypal MsaWSI service.
+     */
+    ext.vamsas.MuscleWS server;
+
   private boolean setWebService(String MsaWSName) {
-    if (MsaWServices.info.contains(MsaWSName.toUpperCase())) {
+    if (MsaWServices.info.containsKey(MsaWSName)) {
       WebServiceName = MsaWSName;
-      String[] wsinfo = (String[]) MsaWServices.info.get(MsaWSName.toUpperCase());
+      String[] wsinfo = (String[]) MsaWServices.info.get(MsaWSName);
       WsURL = wsinfo[0];
       WebServiceJobTitle = wsinfo[1];
       WebServiceReference = wsinfo[2];
@@ -43,11 +36,8 @@ public class MsaWSClient
     }
   }
 
-//  public MsaWSClient(String MsaWSName, SequenceI[] msa) {
-//    MsaWSClient(MsaWSName, msa, true);
-//  }
 
-  public MsaWSClient(String MsaWSName, SequenceI[] msa, boolean preserveOrder)
+  public MsaWSClient(String MsaWSName, String altitle, SequenceI[] msa, boolean submitGaps, boolean preserveOrder)
   {
     if (setWebService(MsaWSName)==false) {
       JOptionPane.showMessageDialog(Desktop.desktop, "The Multiple Sequence Alignment Service named "+MsaWSName+" is unknown",
@@ -57,13 +47,13 @@ public class MsaWSClient
 
     wsInfo = new jalview.gui.WebserviceInfo(WebServiceJobTitle, WebServiceReference);
 
-    wsInfo.setProgressText("Job details\n");
+    wsInfo.setProgressText(((submitGaps) ? "Re-alignment" : "Alignment")+" of "+altitle+"\nJob details\n");
 
     // TODO: MuscleWS transmuted to generic MsaWS client
     MuscleWSServiceLocator loc = new MuscleWSServiceLocator(); // Default
     try {
-      this.server = (MuscleWS) loc.getMuscleWS(// JBPNote will be set from properties
-      new java.net.URL(WsURL));
+      this.server = (MuscleWS) loc.getMuscleWS(new java.net.URL(WsURL));
+      ((MuscleWSSoapBindingStub) this.server).setTimeout(60000); // One minute timeout
     }
     catch (Exception ex) {
       wsInfo.setProgressText("Serious! "+WebServiceName+" Service location failed\nfor URL :"
@@ -71,8 +61,8 @@ public class MsaWSClient
       wsInfo.setStatus(wsInfo.ERROR);
       ex.printStackTrace();
     }
-
-    MsaWSThread musclethread = new MsaWSThread(msa);
+    loc.getEngine().setOption("axis","1");
+    MsaWSThread musclethread = new MsaWSThread(WebServiceName+" alignment of "+altitle, msa, submitGaps, preserveOrder);
     wsInfo.setthisService(musclethread);
     musclethread.start();
   }
@@ -89,21 +79,40 @@ public class MsaWSClient
 
     String OutputHeader;
     vamsas.objects.simple.MsaResult result = null;
+
     vamsas.objects.simple.SequenceSet seqs = new vamsas.objects.simple.
         SequenceSet();
+
+    Hashtable SeqNames = null;
+    boolean submitGaps = false,// default is to strip gaps from sequences
+        preserveOrder = true; // and always store and recover sequence order
+
     String jobId;
+    String alTitle; // name which will be used to form new alignment window.
     int allowedServerExceptions = 3; // thread dies if too many exceptions.
-    MsaWSThread(SequenceI[] msa)
+    MsaWSThread(String title, SequenceI[] msa, boolean subgaps, boolean presorder)
     {
+      alTitle = title;
+      submitGaps = subgaps;
+      preserveOrder = presorder;
+
       OutputHeader = wsInfo.getProgressText();
+      SeqNames = new Hashtable();
       vamsas.objects.simple.Sequence[] seqarray = new vamsas.objects.simple.
           Sequence[msa.length];
+
       for (int i = 0; i < msa.length; i++)
       {
+        String newname = jalview.analysis.SeqsetUtils.unique_name(i);
+        // uniquify as we go
+        // TODO: JBPNote: this is a ubiquitous transformation - set of jalview seq objects to vamsas sequences with name preservation
+        SeqNames.put(newname, jalview.analysis.SeqsetUtils.SeqCharacterHash(msa[i]));
         seqarray[i] = new vamsas.objects.simple.Sequence();
-        seqarray[i].setId(msa[i].getName());
-        seqarray[i].setSeq(AlignSeq.extractGaps("-. ", msa[i].getSequence()));
+        seqarray[i].setId(newname);
+        seqarray[i].setSeq((submitGaps) ? msa[i].getSequence()
+                           : AlignSeq.extractGaps(jalview.util.Comparison.GapChars, msa[i].getSequence()));
       }
+
       this.seqs = new vamsas.objects.simple.SequenceSet();
       this.seqs.setSeqs(seqarray);
     }
@@ -111,7 +120,7 @@ public class MsaWSClient
     boolean jobComplete = false;
 
     public void cancelJob() {
-      if (!jobComplete) {
+      if (jobId!=null && !jobId.equals("") && !jobComplete) {
         String cancelledMessage="";
         try {
           vamsas.objects.simple.WsJobId cancelledJob = server.cancel(jobId);
@@ -139,6 +148,11 @@ public class MsaWSClient
           exc.printStackTrace();
         }
         wsInfo.setProgressText(OutputHeader + cancelledMessage+"\n");
+      } else {
+        if (!jobComplete)
+        {
+          wsInfo.setProgressText(OutputHeader + "Server cannot cancel this job because it has not been submitted properly. just close the window.\n");
+        }
       }
     }
 
@@ -151,12 +165,13 @@ public class MsaWSClient
       {
         try
         {
-          result = server.getResult(jobId);
+          if ((result = server.getResult(jobId))==null)
+            throw(new Exception("Timed out when communicating with server\nTry again later.\n"));
 
-         if( result.isRunning() )
-           wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
-         else if( result.isQueued() )
-           wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
+          if (result.isRunning())
+            wsInfo.setStatus(WebserviceInfo.STATE_RUNNING);
+          else if (result.isQueued())
+            wsInfo.setStatus(WebserviceInfo.STATE_QUEUING);
 
           if (result.isFinished())
           {
@@ -166,44 +181,80 @@ public class MsaWSClient
           }
           else
           {
-            wsInfo.setProgressText(OutputHeader + "\n" + result.getStatus());
+            if (result.getStatus() != null)
+              wsInfo.setProgressText(OutputHeader + "\n" + result.getStatus());
             if (! (result.isJobFailed() || result.isServerError()))
             {
               Thread.sleep(5000);
               //  System.out.println("I'm alive "+seqid+" "+jobid);
             }
+            else
+            {
+              break;
+            }
           }
         }
         catch (Exception ex)
         {
           allowedServerExceptions--;
-          wsInfo.appendProgressText("\n"+ServiceName+" Server exception!\n" + ex.getMessage());
-          ex.printStackTrace();
+          wsInfo.appendProgressText("\n" + ServiceName + " Server exception!\n" +
+                                    ex.getMessage());
+          System.err.println(ServiceName + " Server exception: " +
+                                    ex.getMessage());
+          //          ex.printStackTrace(); JBPNote Debug
+          try
+          {
+            if (allowedServerExceptions>0)
+              Thread.sleep(5000);
+          }
+          catch (InterruptedException ex1)
+          {
+          }
+
         }
       }
-
-      if (! (result!=null && (result.isJobFailed() || result.isServerError())))
-        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
+      if (allowedServerExceptions == 0)
+      {
+        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+      }
       else
-        wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+      {
+        if (! (result != null && (result.isJobFailed() || result.isServerError())))
+          wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_OK);
+        else
+        {
+          if (result.isFailed())
+            wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_ERROR);
+          if (result.isServerError())
+            wsInfo.setStatus(WebserviceInfo.STATE_STOPPED_SERVERERROR);
+        }
+      }
     }
-
     void StartJob()
     {
       try
       {
         vamsas.objects.simple.WsJobId jobsubmit = server.align(seqs);
-        if (jobsubmit.getStatus()==1) {
-          System.out.println(jobId=jobsubmit.getJobId());
+        if (jobsubmit!=null && jobsubmit.getStatus()==1) {
+          jobId=jobsubmit.getJobId();
+          System.out.println(WsURL+" Job Id '"+jobId+"'");
         } else {
+          if (jobsubmit == null) {
+            throw new Exception("Server at "+WsURL+" returned null object, it probably cannot be contacted. Try again later ?");
+          }
           throw new Exception(jobsubmit.getJobId());
         }
       }
       catch (Exception e)
       {
-        System.out.println(ServiceName + " Client: Failed to submit the prediction\n" +
+        // TODO: JBPNote catch timeout or other fault types explicitly
+        // For unexpected errors
+        System.err.println(WebServiceName + " Client: Failed to submit the sequences for alignment.\n"+WsURL+" : " +
                            e.toString() + "\n");
-        e.printStackTrace();
+        this.allowedServerExceptions=0;
+        wsInfo.setStatus(wsInfo.STATE_STOPPED_SERVERERROR);
+        wsInfo.appendProgressText("Server problems! "+e.toString()+"\nFailed to submit sequences for alignment. Just close the window\n");
+        // e.printStackTrace(); // TODO: JBPNote DEBUG
       }
     }
 
@@ -247,13 +298,22 @@ public class MsaWSClient
 
         wsInfo.setProgressText(OutputHeader);
         if (seqs!=null) {
-          Alignment al;
-          al = new Alignment(seqs);
+          AlignmentOrder msaorder = new AlignmentOrder(seqs);
+
+          if (preserveOrder) {
+            jalview.analysis.AlignmentSorter.recoverOrder(seqs);
+          }
+
+          jalview.analysis.SeqsetUtils.deuniquify(SeqNames, seqs);
+
+          Alignment al = new Alignment(seqs);
 
           // TODO: JBPNote Should also rename the query sequence sometime...
           AlignFrame af = new AlignFrame(al);
+          af.addSortByOrderMenuItem(ServiceName+" Ordering", msaorder);
+
           Desktop.addInternalFrame(af,
-                                   ServiceName + " Alignment",
+                                   alTitle,
                                    AlignFrame.NEW_WINDOW_WIDTH,
                                    AlignFrame.NEW_WINDOW_HEIGHT);
         }