JAL-1894 update year/version in copyright
[jalview.git] / src / jalview / io / ModellerDescription.java
index 457a6ae..a24afff 100755 (executable)
@@ -1,50 +1,70 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b1)
+ * 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.io;
 
 import jalview.datamodel.SequenceI;
-import java.util.Vector;
-import com.stevesoft.pat.Regex;
+
 public class ModellerDescription
 {
-    /**
-     * Translates between a String containing a set of colon-separated values
-     * on a single line, and sequence start/end and other properties.
-     * See PIRFile IO for its use.
-     */
-    final String[] seqTypes =
-      {
-      "sequence", "structure", "structureX", "structureN"};
-  final String[] Fields =
-      {
-      "objectType", "objectId",
-      "startField", "startCode",
-      "endField", "endCode",
-      "description1", "description2",
-      "resolutionField", "tailField"};
+  /**
+   * Translates between a String containing a set of colon-separated values on a
+   * single line, and sequence start/end and other properties. See PIRFile IO
+   * for its use.
+   */
+  final String[] seqTypes = { "sequence", "structure", "structureX",
+      "structureN" };
+
+  final String[] Fields = { "objectType", "objectId", "startField",
+      "startCode", "endField", "endCode", "description1", "description2",
+      "resolutionField", "tailField" };
+
   final int TYPE = 0;
+
   final int LOCALID = 1;
+
   final int START = 2;
+
   final int START_CHAIN = 3;
+
   final int END = 4;
+
   final int END_CHAIN = 5;
+
   final int DESCRIPTION1 = 6;
+
   final int DESCRIPTION2 = 7;
+
   final int RESOLUTION = 8;
+
   final int TAIL = 9;
 
   /**
-   * 0 is free text or empty
-   * 1 is something that parses to an integer, or \@
+   * 0 is free text or empty 1 is something that parses to an integer, or \@
    */
-  final int Types[] =
-      {
-      0, 0, 1, 0, 1, 0, 0, 0, 0, 0
-  };
-  final char Padding[] =
-      {
-      ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.', '.'
-  };
+  final int Types[] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 };
+
+  final char Padding[] = { ' ', ' ', ' ', '.', ' ', '.', '.', '.', '.', '.' };
 
   java.util.Hashtable fields = new java.util.Hashtable();
+
   ModellerDescription()
   {
     fields.put(Fields[TAIL], "");
@@ -53,7 +73,9 @@ public class ModellerDescription
   class resCode
   {
     Integer val;
+
     String field;
+
     resCode(String f, Integer v)
     {
       val = v;
@@ -70,7 +92,8 @@ public class ModellerDescription
   private resCode validResidueCode(String field)
   {
     Integer val = null;
-    com.stevesoft.pat.Regex r = new Regex("\\s*((([-0-9]+).?)|FIRST|LAST|@)");
+    com.stevesoft.pat.Regex r = new com.stevesoft.pat.Regex(
+            "\\s*((([-0-9]+).?)|FIRST|LAST|@)");
 
     if (!r.search(field))
     {
@@ -81,14 +104,13 @@ public class ModellerDescription
     {
       value = r.stringMatched(1);
     }
-    jalview.bin.Cache.log.debug("from '" + field + "' matched '" + value +
-                                "'");
+    // jalview.bin.Cache.log.debug("from '" + field + "' matched '" + value +
+    // "'");
     try
     {
       val = Integer.valueOf(value);
       return new resCode(field, val); // successful numeric extraction
-    }
-    catch (Exception e)
+    } catch (Exception e)
     {
     }
     return new resCode(field, null);
@@ -97,7 +119,9 @@ public class ModellerDescription
   private java.util.Hashtable parseDescription(String desc)
   {
     java.util.Hashtable fields = new java.util.Hashtable();
-    java.util.StringTokenizer st = new java.util.StringTokenizer(desc, ":");
+    java.util.StringTokenizer st = new java.util.StringTokenizer(desc, ":",
+            true);
+
     String field;
     int type = -1;
     if (st.countTokens() > 0)
@@ -107,39 +131,51 @@ public class ModellerDescription
       field = st.nextToken(":");
       do
       {
-        if (seqTypes[i].compareToIgnoreCase(field) == 0)
+        if (seqTypes[i].equalsIgnoreCase(field))
         {
           break;
         }
-      }
-      while (++i < seqTypes.length);
+      } while (++i < seqTypes.length);
 
       if (i < seqTypes.length)
       {
+        st.nextToken(); // skip ':'
         // valid seqType for modeller
         type = i;
         i = 1; // continue parsing fields
         while (i < TAIL && st.hasMoreTokens())
         {
-          if ( (field = st.nextToken(":")) != null)
+          if ((field = st.nextToken(":")) != null)
           {
-            // validate residue field value
-            if (Types[i] == 1)
+            if (!field.equals(":"))
             {
-              resCode val = validResidueCode(field);
-              if (val != null)
+              // validate residue field value
+              if (Types[i] == 1)
               {
-                fields.put(new String(Fields[i] + "num"), val);
+                resCode val = validResidueCode(field);
+                if (val != null)
+                {
+                  fields.put(new String(Fields[i] + "num"), val);
+                }
+                else
+                {
+                  // jalview.bin.Cache.log.debug(
+                  // "Ignoring non-Modeller description: invalid integer-like
+                  // field '" + field + "'");
+                  type = -1; /* invalid field! - throw the FieldSet away */
+                }
+                ;
               }
-              else
+              fields.put(Fields[i++], field);
+              if (st.hasMoreTokens())
               {
-                jalview.bin.Cache.log.debug(
-                    "Ignoring non-Modeller description: invalid integer-like field '" + field + "'");
-                type = -1; /* invalid field! - throw the FieldSet away */
+                st.nextToken(); // skip token sep.
               }
-              ;
             }
-            fields.put(Fields[i++], field);
+            else
+            {
+              i++;
+            }
           }
         }
         if (i == TAIL)
@@ -147,7 +183,8 @@ public class ModellerDescription
           // slurp remaining fields
           while (st.hasMoreTokens())
           {
-            field += ":" + st.nextToken(":");
+            String tl = st.nextToken(":");
+            field += tl.equals(":") ? tl : (":" + tl);
           }
           fields.put(Fields[TAIL], field);
         }
@@ -191,7 +228,9 @@ public class ModellerDescription
 
   /**
    * make a possibly updated modeller field line for the sequence object
-   * @param seq SequenceI
+   * 
+   * @param seq
+   *          SequenceI
    */
   ModellerDescription(SequenceI seq)
   {
@@ -203,13 +242,17 @@ public class ModellerDescription
 
     if (isModellerFieldset())
     {
-      // Set start and end before we update the type (in the case of a synthesized field set)
-      if (getStartNum() != seq.getStart() && getStartCode().val != null)
+      // Set start and end before we update the type (in the case of a
+      // synthesized field set)
+      if (getStartCode() == null
+              || (getStartNum() != seq.getStart() && getStartCode().val != null))
       {
+        // unset or user updated sequence start position
         setStartCode(seq.getStart());
       }
 
-      if (getEndNum() != seq.getEnd() && getStartCode().val != null)
+      if (getEndCode() == null
+              || (getEndNum() != seq.getEnd() && getStartCode() != null && getStartCode().val != null))
       {
         setEndCode(seq.getEnd());
       }
@@ -219,25 +262,29 @@ public class ModellerDescription
       // synthesize fields
       setStartCode(seq.getStart());
       setEndCode(seq.getEnd());
-      fields.put(Fields[LOCALID], seq.getName()); // this may be overwritten below...
-      // type - decide based on evidence of PDB database references - this also sets the local reference field
+      fields.put(Fields[LOCALID], seq.getName()); // this may be overwritten
+      // below...
+      // type - decide based on evidence of PDB database references - this also
+      // sets the local reference field
       int t = 0; // sequence
-      if (seq.getDatasetSequence() != null &&
-          seq.getDatasetSequence().getDBRef() != null)
+      if (seq.getDatasetSequence() != null
+              && seq.getDatasetSequence().getDBRef() != null)
       {
-        Vector dbr = seq.getDatasetSequence().getDBRef();
+        jalview.datamodel.DBRefEntry[] dbr = seq.getDatasetSequence()
+                .getDBRef();
         int i, j;
-        for (i = 0, j = dbr.size(); i < j; i++)
+        for (i = 0, j = dbr.length; i < j; i++)
         {
-          jalview.datamodel.DBRefEntry dref = (jalview.datamodel.DBRefEntry)
-              dbr.get(i);
-          if (dref != null)
+          if (dbr[i] != null)
           {
-            // JBPNote PDB dbRefEntry needs properties to propagate onto ModellerField
-            // JBPNote Need to get info from the user about whether the sequence is the one being modelled, or if it is a template.
-            if (dref.getSource().equals("PDB"))
+            // JBPNote PDB dbRefEntry needs properties to propagate onto
+            // ModellerField
+            // JBPNote Need to get info from the user about whether the sequence
+            // is the one being modelled, or if it is a template.
+            if (dbr[i].getSource()
+                    .equals(jalview.datamodel.DBRefSource.PDB))
             {
-              fields.put(Fields[LOCALID], dref.getAccessionId());
+              fields.put(Fields[LOCALID], dbr[i].getAccessionId());
               t = 2;
               break;
             }
@@ -251,6 +298,7 @@ public class ModellerDescription
 
   /**
    * Indicate if fields parsed to a modeller-like colon-separated value line
+   * 
    * @return boolean
    */
   boolean isModellerFieldset()
@@ -283,7 +331,7 @@ public class ModellerDescription
         value = (String) fields.get(Fields[i]);
         if (value != null && value.length() > 0)
         {
-          desc += ( (String) fields.get(Fields[i])) + ":";
+          desc += ((String) fields.get(Fields[i])) + ":";
         }
         else
         {
@@ -307,7 +355,7 @@ public class ModellerDescription
   {
     int start = 0;
     resCode val = getStartCode();
-    if (val.val != null)
+    if (val != null && val.val != null)
     {
       return val.val.intValue();
     }
@@ -336,7 +384,7 @@ public class ModellerDescription
   {
     int end = 0;
     resCode val = getEndCode();
-    if (val.val != null)
+    if (val != null && val.val != null)
     {
       return val.val.intValue();
     }
@@ -345,14 +393,17 @@ public class ModellerDescription
 
   /**
    * returns true if sequence object was modifed with a valid modellerField set
-   * @param newSeq SequenceI
+   * 
+   * @param newSeq
+   *          SequenceI
    * @return boolean
    */
   boolean updateSequenceI(SequenceI newSeq)
   {
     if (isModellerFieldset())
     {
-      if (getStartCode().val != null)
+      resCode rc = getStartCode();
+      if (rc != null && rc.val != null)
       {
         newSeq.setStart(getStartNum());
       }
@@ -360,7 +411,8 @@ public class ModellerDescription
       {
         newSeq.setStart(1);
       }
-      if (getEndCode().val != null)
+      rc = getEndCode();
+      if (rc != null && rc.val != null)
       {
         newSeq.setEnd(getEndNum());
       }
@@ -373,4 +425,3 @@ public class ModellerDescription
     return false;
   }
 }
-