diff --git a/uk/ac/sanger/artemis/components/FeaturePopup.java b/uk/ac/sanger/artemis/components/FeaturePopup.java
index 7715b8e77afed5a9fd984cf255ed3ba61f42fa49..31ac6bc8d1bb79f7919d3776f34984b973876ef0 100644
--- a/uk/ac/sanger/artemis/components/FeaturePopup.java
+++ b/uk/ac/sanger/artemis/components/FeaturePopup.java
@@ -20,7 +20,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
- * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeaturePopup.java,v 1.9 2005-12-09 16:17:13 tjc Exp $
+ * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeaturePopup.java,v 1.10 2006-03-10 10:15:32 tjc Exp $
  */
 
 package uk.ac.sanger.artemis.components;
@@ -30,6 +30,7 @@ import uk.ac.sanger.artemis.util.StringVector;
 
 import java.io.*;
 import java.awt.Component;
+import java.awt.BorderLayout;
 import java.awt.event.*;
 import javax.swing.*;
 
@@ -37,7 +38,7 @@ import javax.swing.*;
  *  FeaturePopup class
  *
  *  @author Kim Rutherford
- *  @version $Id: FeaturePopup.java,v 1.9 2005-12-09 16:17:13 tjc Exp $
+ *  @version $Id: FeaturePopup.java,v 1.10 2006-03-10 10:15:32 tjc Exp $
  *
  **/
 
@@ -506,6 +507,24 @@ public class FeaturePopup extends JPopupMenu
       }
     });
 
+/*
+    feature_display_menus[19] = new JMenuItem("Define Frame Line Features");
+    feature_display_menus[19].addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent e)
+      {
+        JPanel frame_keys = new JPanel(new BorderLayout());
+        int select = JOptionPane.showConfirmDialog(null, frame_keys,
+                                "Define Frame Line Features",
+                                 JOptionPane.OK_CANCEL_OPTION,
+                                 JOptionPane.QUESTION_MESSAGE);
+
+        if(select == JOptionPane.CANCEL_OPTION)
+          return;
+      }
+    });
+*/
+
     return feature_display_menus;
   }
 
diff --git a/uk/ac/sanger/artemis/util/DatabaseDocument.java b/uk/ac/sanger/artemis/util/DatabaseDocument.java
index 25c4f8ce5a12a8e6fb9f58299a66b2bc29639b3f..8f5d30e585e51d62bad6b749e4901b5ba827d6e6 100644
--- a/uk/ac/sanger/artemis/util/DatabaseDocument.java
+++ b/uk/ac/sanger/artemis/util/DatabaseDocument.java
@@ -431,28 +431,26 @@ public class DatabaseDocument extends Document
       if(feat.getValue() != null)
         value = GFFStreamFeature.encode(feat.getValue());
 
-      this_buff.append(propTypeName + "=" + value); // attributes
-
-      // is the next line part of the same feature, if so merge
-      boolean rewind = false;
-      Feature featNext = null;
-    
-      if(i < feature_size - 1)
-        featNext = (Feature)featList.get(i + 1);
-
-      // merge next line if part of the same feature
-      while(featNext != null && featNext.getUniquename().equals(name))
+      // attributes
+      Hashtable qualifiers     = feat.getQualifiers();
+      if(qualifiers != null)
       {
-        prop_type_id = featNext.getProp_type_id();
-        propTypeName = getCvtermName(prop_type_id);
-        value = GFFStreamFeature.encode(featNext.getValue());
-        this_buff.append(";" + propTypeName + "=" + value);
-        i++;
-        if(i < feature_size - 1)
-          featNext = (Feature) featList.get(i + 1);
-        else
-          break;
-      }
+        Enumeration e_qualifiers = qualifiers.keys();
+        while(e_qualifiers.hasMoreElements())
+        {
+          Long qualifier_type_id = (Long)e_qualifiers.nextElement();
+          String qualifier_name = getCvtermName(qualifier_type_id.longValue());
+          if(qualifier_name == null)
+            continue;
+          Vector qualifier_value = (Vector)qualifiers.get(qualifier_type_id);
+        
+          for(int j=0; j<qualifier_value.size(); j++)
+          {
+            this_buff.append(qualifier_name+ "=" +
+                             GFFStreamFeature.encode((String)qualifier_value.get(j))+";");
+          }
+        }
+      } 
 
       this_buff.append("\n");
 
diff --git a/uk/ac/sanger/ibatis/Feature.java b/uk/ac/sanger/ibatis/Feature.java
index 2f7827ed237f1b5647bedb99969b28d6a18b6006..86ef35a633c76e18050566b03f1645e5f40cedb5 100644
--- a/uk/ac/sanger/ibatis/Feature.java
+++ b/uk/ac/sanger/ibatis/Feature.java
@@ -26,6 +26,8 @@
 package uk.ac.sanger.ibatis;
 
 import java.util.Date;
+import java.util.Hashtable;
+import java.util.Vector;
 
 public class Feature
 {
@@ -62,7 +64,8 @@ public class Feature
   private String value;
   /** feature organism abbreviation */
   private String abbreviation;
-
+  /** hashtable of qualifiers */
+  private Hashtable qualifiers;
  
   public int getId()
   {
@@ -224,4 +227,27 @@ public class Feature
     this.srcfeature_id = srcfeature_id;
   }
 
+  public void addQualifier(long prop_type_id, String value)
+  {
+    if(qualifiers == null)
+      qualifiers = new Hashtable();
+     
+    final Long type_id = new Long(prop_type_id);
+    if(qualifiers.contains(type_id))
+    {
+      Vector v = (Vector)qualifiers.get(type_id);
+      v.add(value);
+    }
+    else
+    {
+      Vector v = new Vector();
+      v.add(value);
+      qualifiers.put(type_id, v);
+    }
+  }
+
+  public Hashtable getQualifiers()
+  {
+    return qualifiers;
+  }
 }
diff --git a/uk/ac/sanger/ibatis/IBatisDAO.java b/uk/ac/sanger/ibatis/IBatisDAO.java
index a88db3c5108f18f227596fcfe1b443ed51ffabb3..53aadf6eef1b8a73df5c88ff17dd7327f7a77ebb 100644
--- a/uk/ac/sanger/ibatis/IBatisDAO.java
+++ b/uk/ac/sanger/ibatis/IBatisDAO.java
@@ -26,6 +26,7 @@ package uk.ac.sanger.ibatis;
 
 import com.ibatis.sqlmap.client.SqlMapClient;
 import java.util.List;
+import java.util.Vector;
 import java.sql.*;
 import javax.swing.JPasswordField;
 
@@ -84,7 +85,11 @@ public class IBatisDAO implements ChadoDAO
     feature.setId(feature_id);
     if(schema != null)
       feature.setSchema(schema);
-    return sqlMap.queryForList("getGffLine", feature);
+
+    List feature_list = sqlMap.queryForList("getGffLine", feature);
+
+    // merge same features in the list
+    return JdbcDAO.mergeList(feature_list);
   }
 
   /**
diff --git a/uk/ac/sanger/ibatis/JdbcDAO.java b/uk/ac/sanger/ibatis/JdbcDAO.java
index d01b92635308354ccf93b79f8956bd1eb62fd70e..d9b812ae0736e314fe9141de2345d935c4808dbb 100644
--- a/uk/ac/sanger/ibatis/JdbcDAO.java
+++ b/uk/ac/sanger/ibatis/JdbcDAO.java
@@ -109,30 +109,30 @@ public class JdbcDAO
     Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                         ResultSet.CONCUR_UPDATABLE);
 
-    String sql = "SELECT timelastmodified, feature.feature_id, object_id, strand, fmin, fmax, uniquename, "
-        + schema + ".feature.type_id, "
+    String sql = "SELECT timelastmodified, f.feature_id, object_id, "
+        + "strand, fmin, fmax, uniquename, f.type_id, "
         + schema + ".featureprop.type_id AS prop_type_id, featureprop.value"
         + " FROM  "
-        + schema + ".featureloc, "
-        + schema + ".feature"
+        + schema + ".featureloc fl, "
+        + schema + ".feature f"
         + " LEFT JOIN "
-        + schema + ".feature_relationship ON "
-        + schema + ".feature_relationship.subject_id="
-        + schema + ".feature.feature_id"
+        + schema + ".feature_relationship fr ON "
+        + "fr.subject_id="
+        + "f.feature_id"
         + " LEFT JOIN "
         + schema + ".featureprop ON "
         + schema + ".featureprop.feature_id="
-        + schema + ".feature.feature_id"
+        + "f.feature_id"
         + " WHERE srcfeature_id = "
         + parentFeatureID + " AND "
-        + schema + ".featureloc.feature_id="
-        + schema + ".feature.feature_id"
+        + "fl.feature_id="
+        + "f.feature_id"
         + " AND ("
-        + schema + ".featureloc.rank="
-        + schema + ".feature_relationship.rank OR "
-        + schema + ".feature_relationship.rank IS NULL)"
+        + "fl.rank="
+        + "fr.rank OR "
+        + "fr.rank IS NULL)"
         + " ORDER BY "
-        + schema + ".feature.type_id, uniquename";
+        + "f.type_id, uniquename";
 
     appendToLogFile(sql, sqlLog);
     ResultSet rs = st.executeQuery(sql);
@@ -154,7 +154,53 @@ public class JdbcDAO
 
       list.add(feature);
     }
-    return list;
+
+    // merge same features in the list
+    return mergeList(list);
+  }
+
+  /**
+   *
+   * Takes a list and creates a new one merging all feature objects
+   * within it with the same feature and stores the qualifiers/attributes
+   *  as a hash
+   * @param list of feature objects
+   * @return list of flattened/merged feature objects
+   * 
+   */
+  protected static List mergeList(List list)
+  {
+    // merge same features in the list
+    int feature_size  = list.size();
+    List flatten_list = new Vector();
+    Feature featNext  = null;
+
+    for(int i = 0; i < feature_size; i++)
+    {
+      Feature feat = (Feature)list.get(i);
+      String name  = feat.getUniquename();
+
+      feat.addQualifier(feat.getProp_type_id(),
+                        feat.getValue());
+
+      if(i < feature_size - 1)
+        featNext = (Feature)list.get(i + 1);
+
+      // merge next line if part of the same feature
+      while(featNext != null && featNext.getUniquename().equals(name))
+      {
+        feat.addQualifier(featNext.getProp_type_id(),
+                          featNext.getValue());
+        i++;
+        if(i < feature_size - 1)
+          featNext = (Feature)list.get(i + 1);
+        else
+          break;
+      }
+      flatten_list.add(feat);
+    }
+
+    return flatten_list;
   }
 
   /**