diff --git a/uk/ac/sanger/artemis/chado/ArtemisUtils.java b/uk/ac/sanger/artemis/chado/ArtemisUtils.java
index a4f65f0351b6f0bfde916101caa432e717854da3..f0eea5f306acbd15af4d5c04e2f7f0e988c8e2bf 100644
--- a/uk/ac/sanger/artemis/chado/ArtemisUtils.java
+++ b/uk/ac/sanger/artemis/chado/ArtemisUtils.java
@@ -76,23 +76,34 @@ public class ArtemisUtils
    */
   public static void inserFeatureCvTerm(GmodDAO dao, FeatureCvTerm featureCvTerm)
   {
-    List featureCvTerms = dao.getFeatureCvTermsByFeature(featureCvTerm.getFeature());
+    List<FeatureCvTerm> featureCvTerms = dao.getFeatureCvTermsByFeature(featureCvTerm.getFeature());
     logger4j.debug("In inserFeatureCvTerm() inserting");
-    int rank = 0;
-    for(int i=0; i<featureCvTerms.size(); i++)
+   
+    boolean isNotProduct = true;
+    try
     {
-      FeatureCvTerm this_feature_cvterm = (FeatureCvTerm)featureCvTerms.get(i);
-      
-      if(this_feature_cvterm.getCvTerm().getName().equals( 
-         featureCvTerm.getCvTerm().getName() )  &&
-         this_feature_cvterm.getCvTerm().getCv().getName().equals( 
-             featureCvTerm.getCvTerm().getCv().getName() ))
+      // product feature_cvterm.rank is used to define alternative products
+      // where there are multiple products, so the rank may already be set
+      if(featureCvTerm.getCvTerm().getCv().getName().equals(
+          DatabaseDocument.PRODUCTS_TAG_CVNAME))
+        isNotProduct = false;
+    } catch(Exception e){}
+    
+    if(isNotProduct || featureCvTerm.getRank() == 0)
+    {
+      int rank = 0;
+      for(FeatureCvTerm this_feature_cvterm: featureCvTerms)
       {
-        rank++;
+        if(this_feature_cvterm.getCvTerm().getName().equals( 
+           featureCvTerm.getCvTerm().getName() )  &&
+           this_feature_cvterm.getCvTerm().getCv().getName().equals( 
+               featureCvTerm.getCvTerm().getCv().getName() ))
+        {
+          rank++;
+        }
       }
+      featureCvTerm.setRank(rank);
     }
-    
-    featureCvTerm.setRank(rank);
     dao.persist(featureCvTerm);
   }
   
diff --git a/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java b/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
index bc307568d2224454edb69c01b7cf974888d90bef..444080cdba525688245711c67a5080b79db333e8 100644
--- a/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
+++ b/uk/ac/sanger/artemis/chado/ChadoTransactionManager.java
@@ -2460,6 +2460,17 @@ public class ChadoTransactionManager
         continue;
       }
       
+      // for product use the rank=1 to specify an alternative product 
+      // where there are multiple products for a feature
+      if(cvName != null && cvName.equals(PRODUCT_CV) && 
+         this_qualifier_part_lowercase.startsWith("rank="))
+      {
+        if(this_qualifier_part_lowercase.equals("rank=1"))
+          feature_cvterm.setRank(1);
+        else
+          feature_cvterm.setRank(0);
+        continue;
+      }
       // feature_cvterm_prop's  
       
       if(!this_qualifier_part_lowercase.startsWith("goid=") &&
diff --git a/uk/ac/sanger/artemis/components/genebuilder/cv/CVPanel.java b/uk/ac/sanger/artemis/components/genebuilder/cv/CVPanel.java
index 173760c0b21dba5234ab0c4de611b21e9f3b7770..b8f4f5ec03c657781f3bc5166b91ec89885e532f 100644
--- a/uk/ac/sanger/artemis/components/genebuilder/cv/CVPanel.java
+++ b/uk/ac/sanger/artemis/components/genebuilder/cv/CVPanel.java
@@ -36,7 +36,6 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Vector;
 
-
 import javax.swing.Box;
 import javax.swing.JLabel;
 import javax.swing.JTextField;
@@ -180,16 +179,10 @@ public class CVPanel extends JPanel
     cvBox.add(xBox);
 
     Dimension go_dimension = null;
-    int nGo = 0;
-
- 
     Box goBox = null;
     Box goHeadings = null;
-    for(int qualifier_index = 0; qualifier_index < cvQualifiers.size();
-        ++qualifier_index) 
+    for(Qualifier this_qualifier: cvQualifiers) 
     {
-      Qualifier this_qualifier = (Qualifier)cvQualifiers.elementAt(qualifier_index);
-
       if(this_qualifier.getName().equals("GO"))
       {
         empty = false;
@@ -204,32 +197,24 @@ public class CVPanel extends JPanel
         
         if(goHeadings == null)
           goHeadings = Box.createHorizontalBox();
-        
-        nGo++;
+
         final StringVector qualifier_strings = this_qualifier.getValues();
-        
-        for(int value_index = 0; value_index < qualifier_strings.size();
-            ++value_index)
+        for(int i = 0; i < qualifier_strings.size(); ++i)
         {
-          final int v_index = value_index;
-          
-          final String qualifierString = 
-            (String)qualifier_strings.elementAt(value_index);
-                      
-          GoBox go_box = new GoBox(this_qualifier, qualifierString, value_index, 
+          GoBox go_box = new GoBox(this_qualifier, qualifier_strings.elementAt(i), i, 
                                    go_dimension, dimension);
           go_dimension = go_box.getGoDimension();
           editableComponents.add(go_box);
           
           xBox = go_box.getBox();
           xBox.add(Box.createHorizontalGlue());
-          xBox.add(getRemoveButton(this_qualifier, v_index));
+          xBox.add(getRemoveButton(this_qualifier, i));
           
           goBox.add(xBox);
         }
         
         // add column headings
-        JLabel lab = new JLabel("GO terms");
+        final JLabel lab = new JLabel("GO terms");
         lab.setPreferredSize(go_dimension);
         lab.setFont(lab.getFont().deriveFont(Font.BOLD));
         goHeadings.add(lab);
@@ -248,9 +233,7 @@ public class CVPanel extends JPanel
         final JLabel qualLabel = new JLabel("Qualifier");
         qualLabel.setPreferredSize(dimension);
         goHeadings.add(qualLabel);
-        
-        final JLabel dateLabel = new JLabel("Date");
-        goHeadings.add(dateLabel);
+        goHeadings.add(new JLabel("Date"));
         
         goHeadings.add(Box.createHorizontalGlue());
         goHeadings.add(hide_show_GO);
@@ -261,34 +244,24 @@ public class CVPanel extends JPanel
     }
     
     int n = 0;
-    for(int qualifier_index = 0; qualifier_index < cvQualifiers.size();
-        ++qualifier_index) 
+    for(Qualifier this_qualifier: cvQualifiers) 
     {
-      final Qualifier this_qualifier = (Qualifier)cvQualifiers.elementAt(qualifier_index);
       if(this_qualifier.getName().equals("product"))
       {
         final StringVector qualifier_strings = this_qualifier.getValues();
-
-        for(int value_index = 0; value_index < qualifier_strings.size(); ++value_index)
+        for(int i = 0; i < qualifier_strings.size(); ++i)
         {
-          final int v_index = value_index;
-
-          xBox = Box.createHorizontalBox();
-          final String qualifierString = (String) qualifier_strings
-              .elementAt(value_index);
-          
           empty = false;
-            
-          xBox = Box.createHorizontalBox();            
           final ProductBox productBox = new ProductBox(
-                    this_qualifier,
-                    qualifierString, value_index, 
-                    dimension, go_dimension);
+                    this_qualifier, qualifier_strings.elementAt(i), 
+                    i, dimension, go_dimension);
           editableComponents.add(productBox);
-            
+
+          if(qualifier_strings.size() == 1)
+            productBox.getRecommended().setEnabled(false);
           xBox = productBox.getBox();
           xBox.add(Box.createHorizontalGlue());
-          xBox.add(getRemoveButton(this_qualifier, v_index));         
+          xBox.add(getRemoveButton(this_qualifier, i));         
           n++;
           cvBox.add(productBox.getHeadingsBox()); 
           cvBox.add(xBox); 
@@ -301,35 +274,25 @@ public class CVPanel extends JPanel
     
     // history field
     n = 0;
-    for(int qualifier_index = 0; qualifier_index < cvQualifiers.size();
-        ++qualifier_index) 
+    for(Qualifier this_qualifier: cvQualifiers) 
     {
-      final Qualifier this_qualifier = 
-        (Qualifier)cvQualifiers.elementAt(qualifier_index);
       if(this_qualifier.getName().equals("history"))
       {
         final StringVector qualifier_strings = this_qualifier.getValues();
 
-        for(int value_index = 0; value_index < qualifier_strings.size(); ++value_index)
+        for(int i = 0; i < qualifier_strings.size(); ++i)
         {
-          final int v_index = value_index;
-
-          xBox = Box.createHorizontalBox();
-          final String qualifierString = (String) qualifier_strings
-              .elementAt(value_index);
-          
           empty = false;
-            
-          xBox = Box.createHorizontalBox();            
+           
           final HistoryBox historyBox = new HistoryBox(
                     this_qualifier,
-                    qualifierString, value_index, 
+                    qualifier_strings.elementAt(i), i, 
                     dimension, go_dimension);
           editableComponents.add(historyBox);
             
           xBox = historyBox.getBox();
           xBox.add(Box.createHorizontalGlue());
-          xBox.add(getRemoveButton(this_qualifier, v_index));
+          xBox.add(getRemoveButton(this_qualifier, i));
           
           if(n == 0)
           {
@@ -359,15 +322,12 @@ public class CVPanel extends JPanel
 
 
     n = 0;
-    for(int qualifier_index = 0; qualifier_index < cvQualifiers.size();
-        ++qualifier_index) 
+    for(Qualifier this_qualifier: cvQualifiers) 
     {
-      final Qualifier this_qualifier = (Qualifier)cvQualifiers.elementAt(qualifier_index);
       if(this_qualifier.getName().equals("controlled_curation"))
       {
         empty = false;
-        final StringVector qualifier_strings = this_qualifier.getValues();
-        
+
         final Box yBox = Box.createVerticalBox();
         if(hide_show_CC == null)
           hide_show_CC = new JButton("-");
@@ -423,23 +383,20 @@ public class CVPanel extends JPanel
           xHeadings.add(Box.createHorizontalGlue());
         }
 
-        for(int value_index = 0; value_index < qualifier_strings.size();
-            ++value_index)
+        final StringVector qualifier_strings = this_qualifier.getValues();
+        for(int i = 0; i < qualifier_strings.size(); ++i)
         {
           n++;
-          xBox = Box.createHorizontalBox();
-          final String qualifierString = 
-             (String)qualifier_strings.elementAt(value_index);
 
           final ControlledCurationBox ccBox = new ControlledCurationBox(
                   this_qualifier,
-                  qualifierString, value_index, 
+                  qualifier_strings.elementAt(i), i, 
                   dimension, go_dimension);
           editableComponents.add(ccBox);
 
           xBox = ccBox.getBox();
           xBox.add(Box.createHorizontalGlue());
-          xBox.add(getRemoveButton(this_qualifier, value_index));         
+          xBox.add(getRemoveButton(this_qualifier, i));         
           yBox.add(xBox);
           yBox.add(Box.createVerticalStrut(2));
         }
@@ -461,43 +418,39 @@ public class CVPanel extends JPanel
     if(go_dimension == null)
       go_dimension = new JLabel("product ").getPreferredSize();
     n = 0;
-    for(int qualifier_index = 0; qualifier_index < cvQualifiers.size(); ++qualifier_index)
+    for(Qualifier this_qualifier: cvQualifiers)
     {
-      final Qualifier this_qualifier = (Qualifier) cvQualifiers
-          .elementAt(qualifier_index);
       if(this_qualifier.getName().equals("class"))
       {
         empty = false;
         final StringVector qualifier_strings = this_qualifier.getValues();
         n++;
         
-        for(int value_index = 0; value_index < qualifier_strings.size(); ++value_index)
+        for(int i = 0; i < qualifier_strings.size(); ++i)
         {
-          final int v_index = value_index;
-          
           xBox = Box.createHorizontalBox();
-          final String qualifierString = (String) qualifier_strings.elementAt(value_index);
+          final String qualifierStr = qualifier_strings.elementAt(i);
 
           JLabel label = new JLabel("class");
           if(go_dimension != null)
             label.setPreferredSize(go_dimension);
           xBox.add(label);
 
-          int index = qualifierString.indexOf("::");
-          String classStr = qualifierString.substring(0, index);
+          int index = qualifierStr.indexOf("::");
+          String classStr = qualifierStr.substring(0, index);
           JLabel termTextField = new JLabel(classStr);
           termTextField.setOpaque(false);
 
           termTextField
               .setToolTipText(DatabaseDocument.getCvTermByCvTermId(
-                  Integer.parseInt(qualifierString.substring(index + 2)), feature.getEmblFeature())
+                  Integer.parseInt(qualifierStr.substring(index + 2)), feature.getEmblFeature())
                   .getDefinition());
           termTextField.setPreferredSize(dimension);
           termTextField.setMaximumSize(dimension);
 
           xBox.add(termTextField);
           xBox.add(Box.createHorizontalGlue());
-          xBox.add(getRemoveButton(this_qualifier, v_index));
+          xBox.add(getRemoveButton(this_qualifier, i));
           cvBox.add(xBox);
         }
       }
diff --git a/uk/ac/sanger/artemis/components/genebuilder/cv/ProductBox.java b/uk/ac/sanger/artemis/components/genebuilder/cv/ProductBox.java
index c9983887e33ca7fa8390a2bb2f45daa9c9597056..bc027a5fce437e7354ceb4a224924858956bd182 100644
--- a/uk/ac/sanger/artemis/components/genebuilder/cv/ProductBox.java
+++ b/uk/ac/sanger/artemis/components/genebuilder/cv/ProductBox.java
@@ -28,6 +28,7 @@ import java.awt.Dimension;
 import java.awt.Font;
 
 import javax.swing.Box;
+import javax.swing.JCheckBox;
 import javax.swing.JLabel;
 import javax.swing.JTextField;
 
@@ -38,7 +39,11 @@ import uk.ac.sanger.artemis.io.QualifierVector;
 import uk.ac.sanger.artemis.util.StringVector;
 
 /**
- * Product display box
+ * Product display box. 
+ * 
+ * Where there are multiple products associated with a feature assume 
+ * the product is the recommended product unless rank=1 which means it 
+ * is an alternative product.
  */
 class ProductBox extends AbstractCvBox
 {
@@ -48,33 +53,34 @@ class ProductBox extends AbstractCvBox
   private JTextField withTextField;
   private JTextField dbxrefTextField;
   private JExtendedComboBox evidenceList;
-  private String origQualifierString;
+  private JCheckBox recommended = new JCheckBox();
+  private String origQualifierStr;
   private Qualifier origQualifier;
   private Box xHeadings = Box.createHorizontalBox();
   
   public ProductBox(final Qualifier qualifier,
-                    final String qualifierString,
+                    final String qualifierStr,
                     final int value_index,
                     final Dimension dimension,
                     final Dimension go_dimension)
   {
     this.origQualifier = qualifier;
-    this.origQualifierString = qualifierString;
+    this.origQualifierStr = qualifierStr;
     this.value_index  = value_index;
     this.xBox = Box.createHorizontalBox();
     
-    String term = getField("term=", qualifierString);
+    String term = getField("term=", qualifierStr);
 
     // this may not be stored as a CV (product_cv=no?)
     if(term.equals(""))
-      term = qualifierString;
+      term = qualifierStr;
    
     termTextField = new WrapTextArea(term, go_dimension, dimension.width*2);
     
     xBox.add(termTextField);
     
     // the WITH column is associated with one or more FeatureCvTermDbXRef
-    String with = getField("with=", qualifierString);
+    String with = getField("with=", qualifierStr);
     withTextField = new JTextField(with);
     withTextField.setToolTipText("with/from column");
     withTextField.setPreferredSize(dimension);
@@ -85,7 +91,7 @@ class ProductBox extends AbstractCvBox
 
     // N.B. for /GO the db_xref is a Pub (for primary pubs) 
     //      or FeatureCvTermPub (for others) in /GO
-    String dbxref = getField("db_xref=", qualifierString);
+    String dbxref = getField("db_xref=", qualifierStr);
     dbxrefTextField = new JTextField(dbxref);
     dbxrefTextField.setToolTipText("dbxref column");
     dbxrefTextField.setPreferredSize(dimension);
@@ -95,7 +101,7 @@ class ProductBox extends AbstractCvBox
     xBox.add(dbxrefTextField); 
     
     // feature_cvterm_prop's
-    String evidence = getField("evidence=", qualifierString);
+    String evidence = getField("evidence=", qualifierStr);
     
     evidenceList = new JExtendedComboBox(GoBox.evidenceCodes[1]);
     evidenceList.setOpaque(false);
@@ -109,23 +115,38 @@ class ProductBox extends AbstractCvBox
     evidenceList.setActionCommand("evidence=");
     xBox.add(evidenceList);
     
-   
-    JLabel lab = new JLabel("Product");
-    lab.setFont(lab.getFont().deriveFont(Font.BOLD));
-    xHeadings.add(lab);
-    
-    xHeadings.add(Box.createRigidArea(new Dimension(
-         termTextField.getPreferredSize().width-lab.getPreferredSize().width,0)));
-    JLabel withLabel = new JLabel("WITH/FROM");
-    withLabel.setPreferredSize(dimension);
-    withLabel.setMaximumSize(dimension);
-    xHeadings.add(withLabel);
-    
-    JLabel dbxrefLabel = new JLabel("Dbxref");
-    dbxrefLabel.setPreferredSize(dimension);
-    dbxrefLabel.setMaximumSize(dimension);
-    xHeadings.add(dbxrefLabel);
-    xHeadings.add(Box.createHorizontalGlue());
+    // check box for recommended product
+    final String rank = getField("rank=", qualifierStr);
+    recommended.setSelected( (rank.length() == 0 || rank.equals("0")) ? true : false );
+    evidenceList.setActionCommand("rank=");
+    xBox.add(recommended);
+    
+    if (value_index == 0)
+    {
+      JLabel lab = new JLabel("Product");
+      lab.setFont(lab.getFont().deriveFont(Font.BOLD));
+      xHeadings.add(lab);
+
+      xHeadings.add(Box.createRigidArea(new Dimension(termTextField
+          .getPreferredSize().width - lab.getPreferredSize().width, 0)));
+      JLabel withLabel = new JLabel("WITH/FROM");
+      withLabel.setPreferredSize(dimension);
+      withLabel.setMaximumSize(dimension);
+      xHeadings.add(withLabel);
+
+      JLabel dbxrefLabel = new JLabel("Dbxref");
+      dbxrefLabel.setPreferredSize(dimension);
+      dbxrefLabel.setMaximumSize(dimension);
+      xHeadings.add(dbxrefLabel);
+
+      xHeadings.add(Box.createHorizontalStrut(de.width));
+      JLabel recommendedLabel = new JLabel("Recommended");
+      recommendedLabel.setPreferredSize(dimension);
+      recommendedLabel.setMaximumSize(dimension);
+      xHeadings.add(recommendedLabel);
+
+      xHeadings.add(Box.createHorizontalGlue());
+    }
   }
 
   /**
@@ -133,29 +154,40 @@ class ProductBox extends AbstractCvBox
    */
   protected boolean isQualifierChanged()
   {
-    String old = getField("with=", origQualifierString);
+    String old = getField("with=", origQualifierStr);
     if(!old.equals(withTextField.getText().trim()))
       return true;
     
-    old = getField("db_xref=", origQualifierString);
+    old = getField("db_xref=", origQualifierStr);
     if(!old.equals(dbxrefTextField.getText().trim()))
       return true;
     
-    old = getField("evidence=", origQualifierString);
+    old = getField("evidence=", origQualifierStr);
     if(evidenceList.getSelectedIndex() > -1 &&
        !old.equalsIgnoreCase(GoBox.evidenceCodes[2][ evidenceList.getSelectedIndex() ]))
       return true;
     
+    // test rank change for recommended/alternative product
+    if(recommended.isEnabled())
+    {
+      old = getField("rank=", origQualifierStr);
+      if( !recommended.isSelected() && (old.equals("0") || old.equals("")) )
+        return true;
+      else if(recommended.isSelected() && !old.equals("0"))
+        return true;
+    }
     return false;
   }
 
   protected void updateQualifier(QualifierVector qv)
   {
-    StringVector values = origQualifier.getValues();
+    Qualifier oldQualifier = qv.getQualifierByName(origQualifier.getName());
+    StringVector values = oldQualifier.getValues();
+
     values.remove(value_index);
     String updatedQualifierString = updateQualifierString();
     
-    Splash.logger4j.debug(origQualifierString);
+    Splash.logger4j.debug(origQualifierStr);
     Splash.logger4j.debug(updatedQualifierString);
     values.add(value_index, updatedQualifierString);
     
@@ -168,23 +200,23 @@ class ProductBox extends AbstractCvBox
   
   private String updateQualifierString()
   {
-    String newQualifierString = origQualifierString;
+    String newQualifierString = origQualifierStr;
     
-    String old = getField("with=", origQualifierString);
+    String old = getField("with=", origQualifierStr);
     if(!old.equals(withTextField.getText().trim()))
     {
       newQualifierString = changeField("with=", withTextField.getText().trim(), 
                                        newQualifierString);
     }
     
-    old = getField("db_xref=", origQualifierString);
+    old = getField("db_xref=", origQualifierStr);
     if(!old.equals(dbxrefTextField.getText().trim()))
     {    
       newQualifierString = changeField("db_xref=", dbxrefTextField.getText().trim(), 
                                        newQualifierString);
     }
     
-    old = getField("evidence=", origQualifierString);
+    old = getField("evidence=", origQualifierStr);
     if(evidenceList.getSelectedIndex() > -1 &&
        !old.equals(GoBox.evidenceCodes[2][ evidenceList.getSelectedIndex() ]))
     {
@@ -192,6 +224,19 @@ class ProductBox extends AbstractCvBox
                    GoBox.evidenceCodes[2][ evidenceList.getSelectedIndex() ], 
                                        newQualifierString);
     }
+    
+    // test rank change
+    old = getField("rank=", origQualifierStr);
+    if( !recommended.isSelected() )
+    {
+      if(old.equals("0") || old.equals(""))
+        newQualifierString = changeField("rank=", "1", newQualifierString);
+    }
+    else
+    {
+      if(recommended.isEnabled() && !old.equals("0") && !old.equals(""))
+        newQualifierString = changeField("rank=", "0", newQualifierString);
+    }
 
     return newQualifierString;
   }
@@ -205,6 +250,12 @@ class ProductBox extends AbstractCvBox
   {
     return xHeadings;
   }
-  
 
+  /**
+   * @return the recommended
+   */
+  protected JCheckBox getRecommended()
+  {
+    return recommended;
+  }
 }
diff --git a/uk/ac/sanger/artemis/util/DatabaseDocument.java b/uk/ac/sanger/artemis/util/DatabaseDocument.java
index f1a889b1d2e6017cd99cf2451c13de772821be71..6cba75df3449f18a6ac8c27112ac66ae89d5f06d 100644
--- a/uk/ac/sanger/artemis/util/DatabaseDocument.java
+++ b/uk/ac/sanger/artemis/util/DatabaseDocument.java
@@ -1595,6 +1595,9 @@ public class DatabaseDocument extends Document
     {
       attr_buff.append("product=");
       
+      // use the rank=1 to specify an alternative product where there is more than one
+      if(feature_cvterm.getRank() > 0)
+        attr_buff.append("rank="+feature_cvterm.getRank()+"%3B");
       constructCvTermString(attr_buff, dao, feature_cvterm, featureCvTermDbXRefs, 
           featureCvTermPubs, dbXRef, false, gene_builder);
     }