JAL-1645 Version-Rel Version 2.9 Year-Rel 2015 Licensing glob
[jalview.git] / src / jalview / ws / rest / RestJobThread.java
index 581af9a..2d5a83a 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9)
+ * Copyright (C) 2015 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.rest;
 
 import jalview.bin.Cache;
@@ -11,10 +31,12 @@ import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
 import jalview.gui.Desktop;
+import jalview.gui.PaintRefresher;
 import jalview.gui.WebserviceInfo;
 import jalview.io.NewickFile;
 import jalview.io.packed.JalviewDataset;
 import jalview.io.packed.JalviewDataset.AlignmentSet;
+import jalview.util.MessageManager;
 import jalview.ws.AWSThread;
 import jalview.ws.AWsJob;
 
@@ -22,11 +44,9 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map.Entry;
-import java.util.Vector;
 
 import org.apache.axis.transport.http.HTTPConstants;
 import org.apache.http.Header;
@@ -50,7 +70,7 @@ public class RestJobThread extends AWSThread
     SUBMIT, POLL
   }
 
-  protected RestClient restClient;;
+  protected RestClient restClient;
 
   public RestJobThread(RestClient restClient)
   {
@@ -88,8 +108,7 @@ public class RestJobThread extends AWSThread
         jobs = new RestJob[viscontigals.length];
         for (int j = 0; j < jobs.length; j++)
         {
-          int[] visc = new int[]
-          { viscontig[j * 2], viscontig[j * 2 + 1] };
+          int[] visc = new int[] { viscontig[j * 2], viscontig[j * 2 + 1] };
           if (j != 0)
           {
             jobs[j] = new RestJob(j, this, viscontigals[j], visc);
@@ -176,6 +195,7 @@ public class RestJobThread extends AWSThread
   {
     String postUrl = rj.getPostUrl();
     doHttpReq(Stage.SUBMIT, rj, postUrl);
+    wsInfo.invalidate();
   }
 
   /**
@@ -236,8 +256,10 @@ public class RestJobThread extends AWSThread
         response = httpclient.execute(request);
       } catch (ClientProtocolException he)
       {
-        rj.statMessage = "Web Protocol Exception when attempting to  "
-                + getStage(stg) + "Job. See Console output for details.";
+        rj.statMessage = "Web Protocol Exception when " + getStage(stg)
+                + "Job. <br>Problematic url was <a href=\""
+                + request.getURI() + "\">" + request.getURI()
+                + "</a><br>See Console output for details.";
         rj.setAllowedServerExceptions(0);// unrecoverable;
         rj.error = true;
         Cache.log.fatal("Unexpected REST Job " + getStage(stg)
@@ -245,8 +267,10 @@ public class RestJobThread extends AWSThread
         throw (he);
       } catch (IOException e)
       {
-        rj.statMessage = "IO Exception when attempting to  "
-                + getStage(stg) + "Job. See Console output for details.";
+        rj.statMessage = "IO Exception when " + getStage(stg)
+                + "Job. <br>Problematic url was <a href=\""
+                + request.getURI() + "\">" + request.getURI()
+                + "</a><br>See Console output for details.";
         Cache.log.warn("IO Exception for REST Job " + getStage(stg)
                 + "exception for URL " + rj.rsd.postUrl);
 
@@ -303,9 +327,22 @@ public class RestJobThread extends AWSThread
         // TODO: deal with all other HTTP response codes from server.
         Cache.log.warn("Unhandled response status when " + getStage(stg)
                 + "for " + postUrl + ": " + response.getStatusLine());
+        rj.error = true;
+        rj.setAllowedServerExceptions(0);
+        rj.setSubjobComplete(true);
+        rj.setSubmitted(true);
         try
         {
-          response.getEntity().consumeContent();
+          completeStatus(
+                  rj,
+                  response,
+                  ""
+                          + getStage(stg)
+                          + " resulted in an unexpected server response.<br/>Url concerned was <a href=\""
+                          + request.getURI()
+                          + "\">"
+                          + request.getURI()
+                          + "</a><br/>Filtered response content below:<br/>");
         } catch (IOException e)
         {
           Cache.log.debug("IOException when consuming unhandled response",
@@ -375,7 +412,7 @@ public class RestJobThread extends AWSThread
     int body = f.indexOf("<body");
     if (body > -1)
     {
-      content.delete(0, f.indexOf(">", body));
+      content.delete(0, f.indexOf(">", body) + 1);
     }
     if (body > -1 && sb.length() > 0)
     {
@@ -403,6 +440,14 @@ public class RestJobThread extends AWSThread
     {
       System.err.println("Debug RestJob: Posting Job");
       doPost((RestJob) job);
+    } catch (NoValidInputDataException erex)
+    {
+      job.setSubjobComplete(true);
+      job.setSubmitted(true);
+      ((RestJob) job).statMessage = "<br>It looks like there was a problem with the data sent to the service :<br>"
+              + erex.getMessage() + "\n";
+      ((RestJob) job).error = true;
+
     } catch (Exception ex)
     {
       job.setSubjobComplete(true);
@@ -443,6 +488,14 @@ public class RestJobThread extends AWSThread
           Cache.log.warn("Failed to finish parsing data for job "
                   + rj.getJobId());
           ex.printStackTrace();
+        } finally
+        {
+          rj.error = true;
+          rj.statMessage = "Error whilst parsing data for this job.<br>URL for job response is :<a href=\""
+                  + rj.resSet.getUrl()
+                  + "\">"
+                  + rj.resSet.getUrl()
+                  + "</a><br>";
         }
       }
     }
@@ -458,7 +511,8 @@ public class RestJobThread extends AWSThread
        */
       if (true)
       {
-        wsInfo.setViewResultsImmediatly(false);
+        // preserver current jalview behaviour
+        wsInfo.setViewResultsImmediatly(true);
       }
       else
       {
@@ -494,6 +548,8 @@ public class RestJobThread extends AWSThread
     else
     {
       // tell the user nothing was returned.
+      wsInfo.setStatus(wsInfo.STATE_STOPPED_ERROR);
+      wsInfo.setFinishedNoResults();
     }
   }
 
@@ -749,7 +805,10 @@ public class RestJobThread extends AWSThread
               destAls.add(destAl);
               destColsel.add(destCs);
               resultDest.add(AddDataTo.newAlignment);
-              throw new Error("Impl. Error! TODO: ");
+              throw new Error(
+                      MessageManager
+                              .getString("error.implementation_error")
+                              + "TODO: ");
             }
           }
           /**
@@ -786,7 +845,6 @@ public class RestJobThread extends AWSThread
                 if (sg.getName() != null)
                 {
                   exsg = groupNames.get(sg.getName());
-                  recovered = true;
                 }
                 if (exsg == null)
                 {
@@ -796,16 +854,18 @@ public class RestJobThread extends AWSThread
                   exsg.setStartRes(sg.getStartRes() + contigs[ncnt]);
                   exsg.setEndRes(sg.getEndRes() + contigs[ncnt]);
                 }
+                else
+                {
+                  recovered = true;
+                }
                 // now replace any references from the result set with
                 // corresponding refs from alignment input set.
 
                 // TODO: cope with recovering hidden sequences from
                 // resultContext
                 {
-                  Vector sqs = sg.getSequences(null);
-                  for (int sqsi = 0, iSize = sqs.size(); sqsi < iSize; sqsi++)
+                  for (SequenceI oseq : sg.getSequences(null))
                   {
-                    SequenceI oseq = (SequenceI) sqs.get(sqsi);
                     SequenceI nseq = getNewSeq(oseq, rseqs[nrj],
                             ordermap[nrj], destAl);
                     if (nseq != null)
@@ -923,6 +983,15 @@ public class RestJobThread extends AWSThread
                   visan.sequenceRef = sqass;
                   visAlAn.add(visan);
                 }
+                if (contigs[ncnt] + alan[nrj][an].annotations.length > visan.annotations.length)
+                {
+                  // increase width of annotation row
+                  Annotation[] newannv = new Annotation[contigs[ncnt]
+                          + alan[nrj][an].annotations.length];
+                  System.arraycopy(visan.annotations, 0, newannv, 0,
+                          visan.annotations.length);
+                  visan.annotations = newannv;
+                }
                 // now copy local annotation data into correct position
                 System.arraycopy(alan[nrj][an].annotations, 0,
                         visan.annotations, contigs[ncnt],
@@ -975,9 +1044,10 @@ public class RestJobThread extends AWSThread
     {
       AlignmentI destal;
       ColumnSelection destcs;
-      String alTitle = restClient.service.details.Action + " using "
-              + restClient.service.details.Name + " on "
-              + " whatever you clicked on." + "(set " + als + ")";
+      String alTitle = MessageManager.formatMessage(
+              "label.webservice_job_title_on", new String[] {
+                  restClient.service.details.Action,
+                  restClient.service.details.Name, restClient.viewTitle });
       switch (action)
       {
       case newAlignment:
@@ -985,6 +1055,8 @@ public class RestJobThread extends AWSThread
         destcs = destColsel.get(als);
         destaf = new AlignFrame(destal, destcs, AlignFrame.DEFAULT_WIDTH,
                 AlignFrame.DEFAULT_HEIGHT);
+        PaintRefresher.Refresh(destaf, destaf.getViewport()
+                .getSequenceSetId());
         // todo transfer any feature settings and colouring
         /*
          * destaf.getFeatureRenderer().transferSettings(this.featureSettings);
@@ -1004,12 +1076,14 @@ public class RestJobThread extends AWSThread
          * i++) { af.addSortByOrderMenuItem( WebServiceName + ((String)
          * names.get(i)) + " Ordering", (AlignmentOrder) alorders.get(i)); } } }
          */
+        // TODO: modify this and previous alignment's title if many alignments
+        // have been returned.
         Desktop.addInternalFrame(destaf, alTitle, AlignFrame.DEFAULT_WIDTH,
                 AlignFrame.DEFAULT_HEIGHT);
 
         break;
       case newView:
-
+        // TODO: determine title for view
         break;
       case currentView:
         break;
@@ -1183,6 +1257,8 @@ public class RestJobThread extends AWSThread
    */
   public boolean isValid()
   {
+    ArrayList<String> _warnings = new ArrayList<String>();
+    boolean validt = true;
     if (jobs != null)
     {
       for (RestJob rj : (RestJob[]) jobs)
@@ -1191,14 +1267,48 @@ public class RestJobThread extends AWSThread
         {
           // invalid input for this job
           System.err.println("Job " + rj.getJobnum()
-                  + " has invalid input.");
-          return false;
+                  + " has invalid input. ( " + rj.getStatus() + ")");
+          if (rj.hasStatus() && !_warnings.contains(rj.getStatus()))
+          {
+            _warnings.add(rj.getStatus());
+          }
+          validt = false;
         }
       }
-      return true;
     }
+    if (!validt)
+    {
+      warnings = "";
+      for (String st : _warnings)
+      {
+        if (warnings.length() > 0)
+        {
+          warnings += "\n";
+        }
+        warnings += st;
+
+      }
+    }
+    return validt;
+  }
+
+  protected String warnings;
+
+  public boolean hasWarnings()
+  {
     // TODO Auto-generated method stub
-    return false;
+    return warnings != null && warnings.length() > 0;
+  }
+
+  /**
+   * get any informative messages about why the job thread couldn't start.
+   * 
+   * @return
+   */
+  public String getWarnings()
+  {
+    return isValid() ? "Job can be started. No warnings."
+            : hasWarnings() ? warnings : "";
   }
 
 }