Merge commit 'alpha/update_2_12_for_2_11_2_series_merge^2' into HEAD
[jalview.git] / src / jalview / ws / rest / RestJobThread.java
index ee971f5..cff127b 100644 (file)
  */
 package jalview.ws.rest;
 
+import java.util.Locale;
+
 import jalview.bin.Cache;
 import jalview.datamodel.Alignment;
 import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.AlignmentOrder;
 import jalview.datamodel.Annotation;
-import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenColumns;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
 import jalview.gui.AlignFrame;
@@ -59,8 +61,6 @@ import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.entity.mime.HttpMultipartMode;
 import org.apache.http.entity.mime.MultipartEntity;
 import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.protocol.BasicHttpContext;
-import org.apache.http.protocol.HttpContext;
 import org.apache.http.util.EntityUtils;
 
 public class RestJobThread extends AWSThread
@@ -90,8 +90,8 @@ public class RestJobThread extends AWSThread
     {
       jobs = new RestJob[1];
       jobs[0] = new RestJob(0, this,
-              restClient._input.getVisibleAlignment(restClient.service
-                      .getGapCharacter()),
+              restClient._input.getVisibleAlignment(
+                      restClient.service.getGapCharacter()),
               restClient._input.getVisibleContigs());
       // need a function to get a range on a view/alignment and return both
       // annotation, groups and selection subsetted to just that region.
@@ -101,15 +101,14 @@ public class RestJobThread extends AWSThread
     {
       int[] viscontig = restClient._input.getVisibleContigs();
       AlignmentI[] viscontigals = restClient._input
-              .getVisibleContigAlignments(restClient.service
-                      .getGapCharacter());
+              .getVisibleContigAlignments(
+                      restClient.service.getGapCharacter());
       if (viscontigals != null && viscontigals.length > 0)
       {
         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);
@@ -174,9 +173,13 @@ public class RestJobThread extends AWSThread
   private String getStage(Stage stg)
   {
     if (stg == Stage.SUBMIT)
+    {
       return "submitting ";
+    }
     if (stg == Stage.POLL)
+    {
       return "checking status of ";
+    }
 
     return (" being confused about ");
   }
@@ -213,9 +216,6 @@ public class RestJobThread extends AWSThread
   protected void doHttpReq(Stage stg, RestJob rj, String postUrl)
           throws Exception
   {
-    StringBuffer respText = new StringBuffer();
-    // con.setContentHandlerFactory(new
-    // jalview.ws.io.mime.HttpContentHandler());
     HttpRequestBase request = null;
     String messages = "";
     if (stg == Stage.SUBMIT)
@@ -230,8 +230,8 @@ public class RestJobThread extends AWSThread
       {
         if (input.getValue().validFor(rj))
         {
-          postentity.addPart(input.getKey(), input.getValue()
-                  .formatForInput(rj));
+          postentity.addPart(input.getKey(),
+                  input.getValue().formatForInput(rj));
         }
         else
         {
@@ -250,7 +250,6 @@ public class RestJobThread extends AWSThread
     {
       DefaultHttpClient httpclient = new DefaultHttpClient();
 
-      HttpContext localContext = new BasicHttpContext();
       HttpResponse response = null;
       try
       {
@@ -284,42 +283,19 @@ public class RestJobThread extends AWSThread
         Cache.log.debug("Processing result set.");
         processResultSet(rj, response, request);
         break;
+
       case 202:
-        rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
-                + "<a href="
-                + rj.getJobId()
-                + "\">"
-                + rj.getJobId()
-                + "</a><br>";
-        rj.running = true;
+        markJobAsRunning(rj);
         break;
+
+      case 201:
+        // Created - redirect may be present. Fallthrough to 302
       case 302:
-        Header[] loc;
-        if (!rj.isSubmitted()
-                && (loc = response
-                        .getHeaders(HTTPConstants.HEADER_LOCATION)) != null
-                && loc.length > 0)
-        {
-          if (loc.length > 1)
-          {
-            Cache.log
-                    .warn("Ignoring additional "
-                            + (loc.length - 1)
-                            + " location(s) provided in response header ( next one is '"
-                            + loc[1].getValue() + "' )");
-          }
-          rj.setJobId(loc[0].getValue());
-          rj.setSubmitted(true);
-        }
+        extractJobId(rj, response);
         completeStatus(rj, response);
         break;
       case 500:
-        // Failed.
-        rj.setSubmitted(true);
-        rj.setAllowedServerExceptions(0);
-        rj.setSubjobComplete(true);
-        rj.error = true;
-        rj.running = false;
+        markAsFailed(rj, response);
         completeStatus(rj, response, "" + getStage(stg)
                 + "failed. Reason below:\n");
         break;
@@ -334,16 +310,10 @@ public class RestJobThread extends AWSThread
         rj.setSubmitted(true);
         try
         {
-          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/>");
+          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",
@@ -354,6 +324,64 @@ public class RestJobThread extends AWSThread
     }
   }
 
+  private void markAsFailed(RestJob rj, HttpResponse response)
+  {
+    // Failed.
+    rj.setSubmitted(true);
+    rj.setAllowedServerExceptions(0);
+    rj.setSubjobComplete(true);
+    rj.error = true;
+    rj.running = false;
+  }
+
+  /**
+   * set the jobRunning flag and post a link to the physical result page encoded
+   * in rj.getJobId()
+   * 
+   * @param rj
+   */
+  private void markJobAsRunning(RestJob rj)
+  {
+    rj.statMessage = "<br>Job submitted successfully. Results available at this URL:\n"
+            + "<a href="
+            + rj.getJobId()
+            + "\">"
+            + rj.getJobId()
+            + "</a><br>";
+    rj.running = true;
+  }
+
+  /**
+   * extract the job ID URL from the redirect page. Does nothing if job is
+   * already running.
+   * 
+   * @param rj
+   * @param response
+   */
+  private void extractJobId(RestJob rj, HttpResponse response)
+  {
+    Header[] loc;
+    if (!rj.isSubmitted())
+    {
+
+      // redirect URL - typical for IBIVU type jobs.
+      if ((loc = response.getHeaders(HTTPConstants.HEADER_LOCATION)) != null
+              && loc.length > 0)
+      {
+        if (loc.length > 1)
+        {
+          Cache.log
+                  .warn("Ignoring additional "
+                          + (loc.length - 1)
+                          + " location(s) provided in response header ( next one is '"
+                          + loc[1].getValue() + "' )");
+        }
+        rj.setJobId(loc[0].getValue());
+        rj.setSubmitted(true);
+      }
+    }
+  }
+
   /**
    * job has completed. Something valid should be available from con
    * 
@@ -409,7 +437,7 @@ public class RestJobThread extends AWSThread
      */
     String f;
     StringBuffer content = new StringBuffer(f = EntityUtils.toString(en));
-    f = f.toLowerCase();
+    f = f.toLowerCase(Locale.ROOT);
     int body = f.indexOf("<body");
     if (body > -1)
     {
@@ -481,21 +509,19 @@ public class RestJobThread extends AWSThread
 
         } catch (Error ex)
         {
-          Cache.log.warn("Failed to finish parsing data for job "
-                  + rj.getJobId());
+          Cache.log.warn(
+                  "Failed to finish parsing data for job " + rj.getJobId());
           ex.printStackTrace();
         } catch (Exception ex)
         {
-          Cache.log.warn("Failed to finish parsing data for job "
-                  + rj.getJobId());
+          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()
+                  + rj.resSet.getUrl() + "\">" + rj.resSet.getUrl()
                   + "</a><br>";
         }
       }
@@ -585,12 +611,12 @@ public class RestJobThread extends AWSThread
     /**
      * alignment panels derived from each alignment set returned by service.
      */
-    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<jalview.gui.AlignmentPanel>();
+    ArrayList<jalview.gui.AlignmentPanel> destPanels = new ArrayList<>();
     /**
      * list of instructions for how to process each distinct alignment set
      * returned by the job set
      */
-    ArrayList<AddDataTo> resultDest = new ArrayList<AddDataTo>();
+    ArrayList<AddDataTo> resultDest = new ArrayList<>();
     /**
      * when false, zeroth pane is panel derived from input deta.
      */
@@ -609,9 +635,9 @@ public class RestJobThread extends AWSThread
     boolean vsepjobs = restClient.service.isVseparable();
     // total number of distinct alignment sets generated by job set.
     int numAlSets = 0, als = 0;
-    List<AlignmentI> destAls = new ArrayList<AlignmentI>();
-    List<jalview.datamodel.ColumnSelection> destColsel = new ArrayList<jalview.datamodel.ColumnSelection>();
-    List<List<NewickFile>> trees = new ArrayList<List<NewickFile>>();
+    List<AlignmentI> destAls = new ArrayList<>();
+    List<jalview.datamodel.HiddenColumns> destColsel = new ArrayList<>();
+    List<List<NewickFile>> trees = new ArrayList<>();
 
     do
     {
@@ -670,7 +696,7 @@ public class RestJobThread extends AWSThread
 
               if (alset.trees != null)
               {
-                trees.add(new ArrayList<NewickFile>(alset.trees));
+                trees.add(new ArrayList<>(alset.trees));
               }
               else
               {
@@ -698,8 +724,8 @@ public class RestJobThread extends AWSThread
        */
       int vrestjob = 0;
       // Destination alignments for all result data.
-      ArrayList<SequenceGroup> visgrps = new ArrayList<SequenceGroup>();
-      Hashtable<String, SequenceGroup> groupNames = new Hashtable<String, SequenceGroup>();
+      ArrayList<SequenceGroup> visgrps = new ArrayList<>();
+      Hashtable<String, SequenceGroup> groupNames = new Hashtable<>();
       ArrayList<AlignmentAnnotation> visAlAn = null;
       for (nvertsep = 0; nvertsep < nvertseps; nvertsep++)
       {
@@ -716,7 +742,7 @@ public class RestJobThread extends AWSThread
           RestJob rj = (RestJob) jobs[nrj];
           int contigs[] = input.getVisibleContigs();
           AlignmentI destAl = null;
-          jalview.datamodel.ColumnSelection destCs = null;
+          jalview.datamodel.HiddenColumns destHCs = null;
           // Resolve destAl for this data.
           if (als == 0 && rj.isInputContextModified())
           {
@@ -732,10 +758,10 @@ public class RestJobThread extends AWSThread
               if (!restClient.isAlignmentModified() && merge)
               {
                 destAl = restClient.av.getAlignment();
-                destCs = restClient.av.getColumnSelection();
-                resultDest
-                        .add(restClient.isShowResultsInNewView() ? AddDataTo.newView
-                                : AddDataTo.currentView);
+                destHCs = restClient.av.getAlignment().getHiddenColumns();
+                resultDest.add(restClient.isShowResultsInNewView()
+                        ? AddDataTo.newView
+                        : AddDataTo.currentView);
                 destPanels.add(restClient.recoverAlignPanelForView());
               }
               else
@@ -743,15 +769,15 @@ public class RestJobThread extends AWSThread
                 newAlignment = true;
                 // recreate the input alignment data
                 Object[] idat = input
-                        .getAlignmentAndColumnSelection(gapCharacter);
+                        .getAlignmentAndHiddenColumns(gapCharacter);
                 destAl = new Alignment((SequenceI[]) idat[0]);
-                destCs = (ColumnSelection) idat[1];
+                destHCs = (HiddenColumns) idat[1];
                 resultDest.add(AddDataTo.newAlignment);
                 // but do not add to the alignment panel list - since we need to
                 // create a whole new alignFrame set.
               }
               destAls.add(destAl);
-              destColsel.add(destCs);
+              destColsel.add(destHCs);
             }
           }
           else
@@ -764,13 +790,13 @@ public class RestJobThread extends AWSThread
               {
                 // TODO: decide if multiple multiple alignments returned by
                 // non-vseparable services are allowed.
-                Cache.log
-                        .warn("dealing with multiple alignment products returned by non-vertically separable service.");
+                Cache.log.warn(
+                        "dealing with multiple alignment products returned by non-vertically separable service.");
               }
               // recover reference to last alignment created for this rest frame
               // ready for extension
               destAl = destAls.get(als);
-              destCs = destColsel.get(als);
+              destHCs = destColsel.get(als);
             }
             else
             {
@@ -799,14 +825,16 @@ public class RestJobThread extends AWSThread
                 newview = input.getUpdatedView(rseqs, orders, gapCharacter);
               }
               destAl = new Alignment((SequenceI[]) newview[0]);
-              destCs = (ColumnSelection) newview[1];
+              destHCs = (HiddenColumns) newview[1];
               newAlignment = true;
               // TODO create alignment from result data with propagated
               // references.
               destAls.add(destAl);
-              destColsel.add(destCs);
+              destColsel.add(destHCs);
               resultDest.add(AddDataTo.newAlignment);
-              throw new Error(MessageManager.getString("error.implementation_error")+"TODO: ");
+              throw new Error(
+                      MessageManager.getString("error.implementation_error")
+                              + "TODO: ");
             }
           }
           /**
@@ -876,8 +904,8 @@ public class RestJobThread extends AWSThread
                     }
                     else
                     {
-                      Cache.log
-                              .warn("Couldn't resolve original sequence for new sequence.");
+                      Cache.log.warn(
+                              "Couldn't resolve original sequence for new sequence.");
                     }
                   }
                   if (sg.hasSeqrep())
@@ -899,8 +927,8 @@ public class RestJobThread extends AWSThread
                 {
                   // adjust boundaries of recovered group w.r.t. new group being
                   // merged on to original alignment.
-                  int start = sg.getStartRes() + contigs[ncnt], end = sg
-                          .getEndRes() + contigs[ncnt];
+                  int start = sg.getStartRes() + contigs[ncnt],
+                          end = sg.getEndRes() + contigs[ncnt];
                   if (start < exsg.getStartRes())
                   {
                     exsg.setStartRes(start);
@@ -954,14 +982,14 @@ public class RestJobThread extends AWSThread
                   grass = groupNames.get(alan[nrj][an].groupRef.getName());
                   if (grass == null)
                   {
-                    Cache.log
-                            .error("Couldn't relocate group referemce for group "
+                    Cache.log.error(
+                            "Couldn't relocate group referemce for group "
                                     + alan[nrj][an].groupRef.getName());
                   }
                 }
                 if (visAlAn == null)
                 {
-                  visAlAn = new ArrayList<AlignmentAnnotation>();
+                  visAlAn = new ArrayList<>();
                 }
                 AlignmentAnnotation visan = null;
                 for (AlignmentAnnotation v : visAlAn)
@@ -981,7 +1009,8 @@ public class RestJobThread extends AWSThread
                   visan.sequenceRef = sqass;
                   visAlAn.add(visan);
                 }
-                if (contigs[ncnt] + alan[nrj][an].annotations.length > visan.annotations.length)
+                if (contigs[ncnt]
+                        + alan[nrj][an].annotations.length > visan.annotations.length)
                 {
                   // increase width of annotation row
                   Annotation[] newannv = new Annotation[contigs[ncnt]
@@ -1004,8 +1033,8 @@ public class RestJobThread extends AWSThread
               {
                 // TODO: process each newick file, lifting over sequence refs to
                 // current alignment, if necessary.
-                Cache.log
-                        .error("Tree recovery from restjob not yet implemented.");
+                Cache.log.error(
+                        "Tree recovery from restjob not yet implemented.");
               }
             }
           }
@@ -1041,8 +1070,12 @@ public class RestJobThread extends AWSThread
     for (AddDataTo action : resultDest)
     {
       AlignmentI destal;
-      ColumnSelection destcs;
-      String alTitle = MessageManager.formatMessage("label.webservice_job_title_on", new String[]{restClient.service.details.Action,restClient.service.details.Name,restClient.viewTitle});
+      HiddenColumns destcs;
+      String alTitle = MessageManager
+              .formatMessage("label.webservice_job_title_on", new String[]
+              { restClient.service.details.getAction(),
+                  restClient.service.details.getName(),
+                  restClient.viewTitle });
       switch (action)
       {
       case newAlignment:
@@ -1050,8 +1083,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());
+        PaintRefresher.Refresh(destaf,
+                destaf.getViewport().getSequenceSetId());
         // todo transfer any feature settings and colouring
         /*
          * destaf.getFeatureRenderer().transferSettings(this.featureSettings);
@@ -1179,8 +1212,8 @@ public class RestJobThread extends AWSThread
           {
             if (start + width < end)
             {
-              blocks[c][s] = sequenceIs[s].getSubSequence(start, start
-                      + width);
+              blocks[c][s] = sequenceIs[s].getSubSequence(start,
+                      start + width);
             }
             else
             {
@@ -1252,7 +1285,7 @@ public class RestJobThread extends AWSThread
    */
   public boolean isValid()
   {
-    ArrayList<String> _warnings = new ArrayList<String>();
+    ArrayList<String> _warnings = new ArrayList<>();
     boolean validt = true;
     if (jobs != null)
     {