JAL-3615 used gzip endpoints for Pfam and Rfam
[jalview.git] / src / jalview / io / FileParse.java
index 2221312..68b5d28 100755 (executable)
@@ -23,6 +23,7 @@ package jalview.io;
 import jalview.api.AlignExportSettingI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureSettingsModelI;
 import jalview.util.MessageManager;
 
 import java.io.BufferedReader;
@@ -38,12 +39,22 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.zip.GZIPInputStream;
 
+
+import jalview.ws.dbsources.Pfam;
+import jalview.ws.dbsources.Rfam;
+
 /**
  * implements a random access wrapper around a particular datasource, for
  * passing to identifyFile and AlignFile objects.
  */
 public class FileParse
 {
+  protected static final String SPACE = " ";
+
+  protected static final String TAB = "\t";
+
+  private static final String GZ_EXT = ".gz";
+
   /**
    * text specifying source of data. usually filename or url.
    */
@@ -51,6 +62,7 @@ public class FileParse
 
   public File inFile = null;
 
+
   /**
    * a viewport associated with the current file operation. May be null. May
    * move to different object.
@@ -80,7 +92,7 @@ public class FileParse
 
   public void setNewlineString(String nl)
   {
-      newline = nl;
+    newline = nl;
   }
 
   public String getNewlineString()
@@ -94,11 +106,11 @@ public class FileParse
    */
   protected String suffix = null;
 
-  protected String type = null;
+  protected DataSourceType dataSourceType = null;
 
   protected BufferedReader dataIn = null;
 
-  protected String errormessage = "UNITIALISED SOURCE";
+  protected String errormessage = "UNINITIALISED SOURCE";
 
   protected boolean error = true;
 
@@ -124,7 +136,8 @@ public class FileParse
   {
     if (from == null)
     {
-      throw new Error(MessageManager.getString("error.implementation_error_null_fileparse"));
+      throw new Error(MessageManager
+              .getString("error.implementation_error_null_fileparse"));
     }
     if (from == this)
     {
@@ -136,7 +149,7 @@ public class FileParse
     suffix = from.suffix;
     errormessage = from.errormessage; // inherit potential error messages
     error = false; // reset any error condition.
-    type = from.type;
+    dataSourceType = from.dataSourceType;
     dataIn = from.dataIn;
     if (dataIn != null)
     {
@@ -176,7 +189,7 @@ public class FileParse
     }
     if (!error)
     {
-      if (fileStr.toLowerCase().endsWith(".gz"))
+      if (fileStr.toLowerCase().endsWith(GZ_EXT))
       {
         try
         {
@@ -201,16 +214,16 @@ public class FileParse
   private BufferedReader tryAsGzipSource(InputStream inputStream)
           throws Exception
   {
-    BufferedReader inData = new BufferedReader(new InputStreamReader(
-            new GZIPInputStream(inputStream)));
+    BufferedReader inData = new BufferedReader(
+            new InputStreamReader(new GZIPInputStream(inputStream)));
     inData.mark(2048);
     inData.read();
     inData.reset();
     return inData;
   }
 
-  private boolean checkURLSource(String fileStr) throws IOException,
-          MalformedURLException
+  private boolean checkURLSource(String fileStr)
+          throws IOException, MalformedURLException
   {
     errormessage = "URL NOT FOUND";
     URL url = new URL(fileStr);
@@ -218,7 +231,7 @@ public class FileParse
     // GZIPInputStream code borrowed from Aquaria (soon to be open sourced) via
     // Kenny Sabir
     Exception e = null;
-    if (fileStr.toLowerCase().endsWith(".gz"))
+    if (isGzipped(fileStr))
     {
       try
       {
@@ -239,7 +252,8 @@ public class FileParse
     {
       if (e != null)
       {
-        throw new IOException(MessageManager.getString("exception.failed_to_resolve_gzip_stream"), e);
+        throw new IOException(MessageManager
+                .getString("exception.failed_to_resolve_gzip_stream"), e);
       }
       throw q;
     }
@@ -249,6 +263,27 @@ public class FileParse
   }
 
   /**
+   * Answers true if the filename (or URL) has a format which Jalview recognises
+   * as denoting gzipped content.
+   * <p>
+   * Currently this means having a ".gz" extension, or ending in "/gzipped" or
+   * "?gz=1" (used to retrieve gzipped from Pfam and Rfam respectively).
+   * 
+   * @param filename
+   * @return
+   */
+  protected static boolean isGzipped(String filename)
+  {
+    if (filename == null)
+    {
+      return false;
+    }
+    String lower = filename.toLowerCase();
+    return lower.endsWith(GZ_EXT) || lower.endsWith(Pfam.GZIPPED)
+            || lower.endsWith(Rfam.GZIPPED);
+  }
+
+  /**
    * sets the suffix string (if any) and returns remainder (if suffix was
    * detected)
    * 
@@ -273,9 +308,9 @@ public class FileParse
    * configurable values for the origin and the type of the source
    */
   public FileParse(BufferedReader source, String originString,
-          String typeString)
+          DataSourceType sourceType)
   {
-    type = typeString;
+    dataSourceType = sourceType;
     error = false;
     inFile = null;
     dataName = originString;
@@ -298,18 +333,18 @@ public class FileParse
    * 
    * @param fileStr
    *          - datasource locator/content
-   * @param type
+   * @param sourceType
    *          - protocol of source
    * @throws MalformedURLException
    * @throws IOException
    */
-  public FileParse(String fileStr, String type)
+  public FileParse(String fileStr, DataSourceType sourceType)
           throws MalformedURLException, IOException
   {
-    this.type = type;
+    this.dataSourceType = sourceType;
     error = false;
 
-    if (type.equals(AppletFormatAdapter.FILE))
+    if (sourceType == DataSourceType.FILE)
     {
       if (checkFileSource(fileStr))
       {
@@ -318,16 +353,21 @@ public class FileParse
         {
           if (checkFileSource(suffixLess))
           {
-            throw new IOException(MessageManager.formatMessage("exception.problem_opening_file_also_tried", new String[]{inFile.getName(),suffixLess,errormessage}));
+            throw new IOException(MessageManager.formatMessage(
+                    "exception.problem_opening_file_also_tried",
+                    new String[]
+                    { inFile.getName(), suffixLess, errormessage }));
           }
         }
         else
         {
-          throw new IOException(MessageManager.formatMessage("exception.problem_opening_file", new String[]{inFile.getName(),errormessage}));
+          throw new IOException(MessageManager.formatMessage(
+                  "exception.problem_opening_file", new String[]
+                  { inFile.getName(), errormessage }));
         }
       }
     }
-    else if (type.equals(AppletFormatAdapter.URL))
+    else if (sourceType == DataSourceType.URL)
     {
       try
       {
@@ -335,7 +375,7 @@ public class FileParse
         {
           checkURLSource(fileStr);
           if (suffixSeparator == '#')
-           {
+          {
             extractSuffix(fileStr); // URL lref is stored for later reference.
           }
         } catch (IOException e)
@@ -364,13 +404,13 @@ public class FileParse
         error = true;
       }
     }
-    else if (type.equals(AppletFormatAdapter.PASTE))
+    else if (sourceType == DataSourceType.PASTE)
     {
       errormessage = "PASTE INACCESSIBLE!";
       dataIn = new BufferedReader(new StringReader(fileStr));
       dataName = "Paste";
     }
-    else if (type.equals(AppletFormatAdapter.CLASSLOADER))
+    else if (sourceType == DataSourceType.CLASSLOADER)
     {
       errormessage = "RESOURCE CANNOT BE LOCATED";
       java.io.InputStream is = getClass()
@@ -396,13 +436,15 @@ public class FileParse
     else
     {
       errormessage = "PROBABLE IMPLEMENTATION ERROR : Datasource Type given as '"
-              + (type != null ? type : "null") + "'";
+              + (sourceType != null ? sourceType : "null") + "'";
       error = true;
     }
     if (dataIn == null || error)
     {
       // pass up the reason why we have no source to read from
-      throw new IOException(MessageManager.formatMessage("exception.failed_to_read_data_from_source", new String[]{errormessage}));
+      throw new IOException(MessageManager.formatMessage(
+              "exception.failed_to_read_data_from_source", new String[]
+              { errormessage }));
     }
     error = false;
     dataIn.mark(READAHEAD_LIMIT);
@@ -422,7 +464,8 @@ public class FileParse
     }
     else
     {
-      throw new IOException(MessageManager.getString("exception.no_init_source_stream"));
+      throw new IOException(
+              MessageManager.getString("exception.no_init_source_stream"));
     }
   }
 
@@ -432,7 +475,9 @@ public class FileParse
     {
       return dataIn.readLine();
     }
-    throw new IOException(MessageManager.formatMessage("exception.invalid_source_stream", new String[]{errormessage}));
+    throw new IOException(MessageManager
+            .formatMessage("exception.invalid_source_stream", new String[]
+            { errormessage }));
   }
 
   /**
@@ -466,18 +511,27 @@ public class FileParse
   }
 
   /**
-   * rewinds the datasource the beginning.
+   * Rewinds the datasource to the marked point if possible
+   * 
+   * @param bytesRead
    * 
    */
-  public void reset() throws IOException
+  public void reset(int bytesRead) throws IOException
   {
+    if (bytesRead >= READAHEAD_LIMIT)
+    {
+      System.err.println(String.format(
+              "File reset error: read %d bytes but reset limit is %d",
+              bytesRead, READAHEAD_LIMIT));
+    }
     if (dataIn != null && !error)
     {
       dataIn.reset();
     }
     else
     {
-      throw new IOException(MessageManager.getString("error.implementation_error_reset_called_for_invalid_source"));
+      throw new IOException(MessageManager.getString(
+              "error.implementation_error_reset_called_for_invalid_source"));
     }
   }
 
@@ -582,9 +636,26 @@ public class FileParse
    */
   public void configureForView(AlignmentViewPanel avpanel)
   {
-    if (avpanel!=null) {
+    if (avpanel != null)
+    {
       setViewport(avpanel.getAlignViewport());
     }
     // could also set export/import settings
   }
+
+  /**
+   * Returns the preferred feature colour configuration if there is one, else
+   * null
+   * 
+   * @return
+   */
+  public FeatureSettingsModelI getFeatureColourScheme()
+  {
+    return null;
+  }
+
+  public DataSourceType getDataSourceType()
+  {
+    return dataSourceType;
+  }
 }