JAL-653 trim initial tab in sequence feature ATTRIBUTES
[jalview.git] / src / jalview / io / FeaturesFile.java
index 5faf334..a9ad665 100755 (executable)
@@ -1,29 +1,47 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
- * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ 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.
+ * 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/>.
+ * 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 java.io.*;
-import java.util.*;
-
 import jalview.analysis.SequenceIdMatcher;
-import jalview.datamodel.*;
-import jalview.schemes.*;
+import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceDummy;
+import jalview.datamodel.SequenceFeature;
+import jalview.datamodel.SequenceI;
+import jalview.schemes.AnnotationColourGradient;
+import jalview.schemes.GraduatedColor;
+import jalview.schemes.UserColourScheme;
 import jalview.util.Format;
+import jalview.util.MapList;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.Vector;
 
 /**
  * Parse and create Jalview Features files Detects GFF format features files and
@@ -151,6 +169,10 @@ public class FeaturesFile extends AlignFile
     try
     {
       SequenceI seq = null;
+      /**
+       * keep track of any sequences we try to create from the data if it is a GFF3 file
+       */
+      ArrayList<SequenceI> newseqs = new ArrayList<SequenceI>();
       String type, desc, token = null;
 
       int index, start, end;
@@ -424,7 +446,7 @@ public class FeaturesFile extends AlignFile
             // Still possible this is an old Jalview file,
             // which does not have type colours at the beginning
             seqId = token = st.nextToken();
-            seq = findName(align, seqId, relaxedIdmatching);
+            seq = findName(align, seqId, relaxedIdmatching, newseqs);
             if (seq != null)
             {
               desc = st.nextToken();
@@ -493,9 +515,11 @@ public class FeaturesFile extends AlignFile
               if (st.hasMoreTokens())
               {
                 StringBuffer attributes = new StringBuffer();
+                boolean sep = false;
                 while (st.hasMoreTokens())
                 {
-                  attributes.append("\t" + st.nextElement());
+                  attributes.append((sep ? "\t" : "") + st.nextElement());
+                  sep = true;
                 }
                 // TODO validate and split GFF2 attributes field ? parse out
                 // ([A-Za-z][A-Za-z0-9_]*) <value> ; and add as
@@ -533,7 +557,7 @@ public class FeaturesFile extends AlignFile
 
           if (!token.equals("ID_NOT_SPECIFIED"))
           {
-            seq = findName(align, seqId = token, relaxedIdmatching);
+            seq = findName(align, seqId = token, relaxedIdmatching, null);
             st.nextToken();
           }
           else
@@ -629,7 +653,7 @@ public class FeaturesFile extends AlignFile
   }
 
   private SequenceI findName(AlignmentI align, String seqId,
-          boolean relaxedIdMatching)
+          boolean relaxedIdMatching, List<SequenceI> newseqs)
   {
     SequenceI match = null;
     if (relaxedIdMatching)
@@ -638,16 +662,29 @@ public class FeaturesFile extends AlignFile
       {
         matcher = new SequenceIdMatcher(
                 (lastmatchedAl = align).getSequencesArray());
+        if (newseqs != null)
+        {
+          matcher.addAll(newseqs);
+        }
       }
       match = matcher.findIdMatch(seqId);
     }
     else
     {
       match = align.findName(seqId, true);
+      
+    }
+    if (match==null && newseqs!=null)
+    {
+      match = new SequenceDummy(seqId);
+      if (relaxedIdMatching)
+      {
+        matcher.addAll(Arrays.asList(new SequenceI[]
+        { match }));
+      }
     }
     return match;
   }
-
   public void parseDescriptionHTML(SequenceFeature sf, boolean removeHTML)
   {
     if (sf.getDescription() == null)
@@ -675,7 +712,7 @@ public class FeaturesFile extends AlignFile
    *          hash of feature types and colours
    * @return features file contents
    */
-  public String printJalviewFormat(SequenceI[] seqs, Hashtable visible)
+  public String printJalviewFormat(SequenceI[] seqs, Map<String,Object> visible)
   {
     return printJalviewFormat(seqs, visible, true, true);
   }
@@ -694,7 +731,7 @@ public class FeaturesFile extends AlignFile
    *          of group or type)
    * @return features file contents
    */
-  public String printJalviewFormat(SequenceI[] seqs, Hashtable visible,
+  public String printJalviewFormat(SequenceI[] seqs, Map visible,
           boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();
@@ -711,11 +748,11 @@ public class FeaturesFile extends AlignFile
       // write feature colours only if we're given them and we are generating
       // viewed features
       // TODO: decide if feature links should also be written here ?
-      Enumeration en = visible.keys();
+      Iterator en = visible.keySet().iterator();
       String type, color;
-      while (en.hasMoreElements())
+      while (en.hasNext())
       {
-        type = en.nextElement().toString();
+        type = en.next().toString();
 
         if (visible.get(type) instanceof GraduatedColor)
         {
@@ -923,12 +960,12 @@ public class FeaturesFile extends AlignFile
    * @param visible
    * @return
    */
-  public String printGFFFormat(SequenceI[] seqs, Hashtable visible)
+  public String printGFFFormat(SequenceI[] seqs, Map<String,Object> visible)
   {
     return printGFFFormat(seqs, visible, true, true);
   }
 
-  public String printGFFFormat(SequenceI[] seqs, Hashtable visible,
+  public String printGFFFormat(SequenceI[] seqs, Map<String,Object> visible,
           boolean visOnly, boolean nonpos)
   {
     StringBuffer out = new StringBuffer();