merge
authortcofoegbu <tcnofoegbu@dundee.ac.uk>
Wed, 11 Nov 2015 13:04:11 +0000 (13:04 +0000)
committertcofoegbu <tcnofoegbu@dundee.ac.uk>
Wed, 11 Nov 2015 13:04:11 +0000 (13:04 +0000)
15 files changed:
RELEASE
build.xml
help/html/menus/alignmentMenu.html
help/html/menus/alwedit.html
help/html/releases.html
help/html/whatsNew.html
src/jalview/appletgui/AlignFrame.java
src/jalview/commands/TrimRegionCommand.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/Jalview2XML_V1.java
src/jalview/gui/TreeCanvas.java
src/jalview/io/PfamFile.java
test/jalview/commands/TrimRegionCommandTest.java [new file with mode: 0644]
test/jalview/io/PfamFormatInputTest.java [new file with mode: 0644]
test/jalview/util/ComparisonTest.java

diff --git a/RELEASE b/RELEASE
index 933f887..6cd9254 100644 (file)
--- a/RELEASE
+++ b/RELEASE
@@ -1,2 +1,2 @@
 jalview.release=Release_2_9_0b1_Branch
-jalview.version=2.9.0b1
+jalview.version=2.9.0b2
index e1ca55f..42ef13f 100755 (executable)
--- a/build.xml
+++ b/build.xml
@@ -27,7 +27,8 @@
     <echo message="build - compiles all necessary files for Application" />
     <echo message="makedist - compiles and places all necessary jar files into directory dist" />
     <echo message="makefulldist - signs all jar files and builds jnlp file for full distribution" />
-    <echo message="              this needs a keystore and key. See docs/building.html for more information." />
+    <echo message="              this needs a keystore and key. Add -Dtimestamp to timestamp signed jars"/>
+    <echo message="              See docs/building.html for more information." />
     <echo message="compileApplet - compiles all necessary files for Applet" />
     <echo message="makeApplet - compiles, then packages and obfuscates the Applet" />
     <echo message="testng - run jalview's tests via testNG. Default group is '${testng-groups}'" />
     <property name="jalview.key" value="jalview" />
     <!-- Key Password -->
     <property name="jalview.key.pass" value="alignmentisfun" />
+    <!-- time stamp server URL -->
+    <property name="jalview.tsaurl" value="" />
+    <!-- locally valid proxy for signing with external time server -->
+    <property name="proxyPort" value="80"/>
+    <property name="proxyHost" value="sqid"/>
 
+    <!-- default TestNG groups to run -->
     <property name="testng-groups" value="Functional" />
 
     <!-- Don't change anything below here unless you know what you are doing! -->
     </java>
   </target>
 
-  <target name="makefulldist" depends="makedist">
+  <target name="preparejnlp" depends="makedist">
     <copy todir="${packageDir}">
       <fileset dir="${resourceDir}/images">
         <include name="${WebStartImage}" />
         <association mime-type="application-x/ext-file" extensions="amsa"/>
         <association mime-type="application-x/ext-file" extensions="stk"/>
         <association mime-type="application-x/ext-file" extensions="jar"/>-->
-    <!-- and sign the jars -->
-    <!-- the default keystore details might need to be edited here -->
+  </target>
+
+  <target name="-jarsignwithtsa" depends="makedist,preparejnlp" if="timestamp">
+    <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" sigalg="SHA1withRSA"
+      tsaproxyhost="${proxyHost}" tsaproxyport="${proxyPort}" tsaurl="${jalview.tsaurl}">
+      <fileset dir="${packageDir}">
+        <include name="*.jar" />
+      </fileset>
+    </signjar>
+  </target>
+  <target name="-jarsignnotsa" depends="makedist,preparejnlp" unless="timestamp">
     <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" sigalg="SHA1withRSA">
       <fileset dir="${packageDir}">
         <include name="*.jar" />
     </signjar>
   </target>
 
+  <target name="makefulldist" depends="makedist,preparejnlp,-jarsignwithtsa,-jarsignnotsa">
+    <!-- and sign the jars -->
+    <!-- the default keystore details might need to be edited here -->
+  </target>
+
   <target name="runenv" depends="init">
     <path id="run.classpath">
       <pathelement location="${outputDir}" />
             <exclude name="jalview.jar" />
             <exclude name="*jnilib.jar" />
           </fileset>
+          <property name="jalview.version" value="${JALVIEW_VERSION}" />
         </resources>
         <resources os="Mac OS X">
-          <property name="jalview.version" value="${JALVIEW_VERSION}" />
           <fileset dir="${packageDir}">
             <include name="*quaqua*.jnilib.jar" />
           </fileset>
     </tarfileset>
   </tar>
 </target>
-<target name="pubapplet" description="installs the jalviewLite applet and dependent jars into an applet examples directory built under ${outputDir}" depends="makeApplet">
+<target name="prepubapplet_1" depends="makeApplet">
   <copy todir="${packageDir}/examples">
     <fileset dir="examples">
       <include name="**/*" />
       <attribute name="Caller-Allowable-Codebase" value="${applet.caller-codebase}" />
     </manifest>
   </jar>
-  <signjar sigalg="SHA1WithRSA" storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false">
-    <fileset dir="${packageDir}/examples">
-      <include name="*.jar" />
-    </fileset>
-  </signjar>
+
   <presetdef name="ap_applet.jar">
     <!-- build a signed applet with 'all-permissions' - 
                          Needs 'param name="permissions' value="all-permissions"' in applet tag
   <applet.jar jarfile="${packageDir}/examples/${javaJson}" />
   <applet.jar jarfile="${packageDir}/examples/${jsonSimple}" />
 
-  <!-- todo - write examples/downloads for alternate versions of the applet -->
+  <!-- todo - write examples/downloads for alternate versions of the applet 
+    probably don't need to do this now since we don't have alternate versions anymore !-->
+</target>
+<target name="-signapplet" depends="prepubapplet_1">
+  <fileset id="signappletjarset" dir="${packageDir}/examples">
+    <exclude name="u_*.jar" />
+    <include name="${jalviewLiteJar}" />
+    <include name="${jmolJar}" />
+    <include name="${javaJson}" />
+    <include name="${jsonSimple}" />
+    <include name="to_${jalviewLiteJar}" />
+    <include name="to_${jmolJar}" />
+    <include name="to_${javaJson}" />
+    <include name="to_${jsonSimple}" />
+    <include name="tl_${jalviewLiteJar}" />
+    <include name="tl_${jmolJar}" />
+    <include name="tl_${javaJson}" />
+    <include name="tl_${jsonSimple}" />
+    <include name="ap_${jalviewLiteJar}" />
+    <include name="ap_${jmolJar}" />
+    <include name="ap_${javaJson}" />
+    <include name="ap_${jsonSimple}" />
+  </fileset>
+</target>
+<target name="-signappletnotsa" unless="timestamp" depends="-signapplet">
   <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false">
+    <fileset refid="signappletjarset" />
+  </signjar>
+</target>
 
-    <fileset dir="${packageDir}/examples">
-      <exclude name="u_*.jar" />
-      <include name="${jalviewLiteJar}" />
-      <include name="${jmolJar}" />
-      <include name="${javaJson}" />
-      <include name="${jsonSimple}" />
-      <include name="to_${jalviewLiteJar}" />
-      <include name="to_${jmolJar}" />
-      <include name="to_${javaJson}" />
-      <include name="to_${jsonSimple}" />
-      <include name="tl_${jalviewLiteJar}" />
-      <include name="tl_${jmolJar}" />
-      <include name="tl_${javaJson}" />
-      <include name="tl_${jsonSimple}" />
-      <include name="ap_${jalviewLiteJar}" />
-      <include name="ap_${jmolJar}" />
-      <include name="ap_${javaJson}" />
-      <include name="ap_${jsonSimple}" />
-    </fileset>
+<target name="-signapplettsa" if="timestamp" depends="-signapplet">
+  <signjar storepass="${jalview.keystore.pass}" keypass="${jalview.key.pass}" keystore="${jalview.keystore}" alias="${jalview.key}" lazy="false" verbose="false" tsaproxyhost="${proxyHost}" tsaproxyport="${proxyPort}" tsaurl="${jalview.tsaurl}">
+    <fileset refid="signappletjarset" />
   </signjar>
+</target>
+
+<target name="signApplet" description="internal target to sign applet" depends="-signappletnotsa,-signapplettsa" />
+
+<target name="pubapplet" description="installs the jalviewLite applet and dependent jars into an applet examples directory built under ${outputDir}" depends="makeApplet, signApplet">
+
   <!-- bizarre bug causes JmolApplet to always get signed, even if excluded from above. so copy explicitly -->
   <copy file="appletlib/${jmolJar}" tofile="${packageDir}/examples/u_${jmolJar}" overwrite="true" />
   <!-- finally, replace any launchApp servlet tags with a version specification -->
index b006c89..ce339cc 100755 (executable)
             &quot;Deselect All&quot; to deselect all columns.</em></li>
         <li><strong>Remove Right (Control R)<br>
         </strong><em>If the alignment has marked columns, the alignment will
-            be trimmed to the left of the leftmost marked column. To
+            be trimmed to the right of the rightmost marked column. To
             mark a column, mouse click the scale bar above the
             alignment. Click again to unmark a column, or select
             &quot;Deselect All&quot; to deselect all columns.</em></li>
index a8390c2..846a1bd 100755 (executable)
@@ -75,7 +75,7 @@
         deselect all columns.</em></li>
     <li><strong>Remove Right (Control R)<br>
     </strong><em>If the alignment has marked columns, the alignment will be
-        trimmed to the left of the leftmost marked column. To mark a
+        trimmed to the right of the rightmost marked column. To mark a
         column, mouse click the scale bar above the alignment. Click
         again to unmark a column, or select &quot;Deselect All&quot; to
         deselect all columns.</em></li>
index 73f6952..23e958c 100755 (executable)
     <tr>
       <td width="60" nowrap>
         <div align="center">
+          <strong><a name="Jalview.2.9.0b2">2.9.0b2</a><br />
+            <em>16/10/2015</em></strong>
+        </div>
+      </td>
+      <td>
+      <em>General</em>
+      <ul>
+            <li>Time stamps for signed Jalview application and applet jars</li>
+      </ul>
+      </td>
+      <td>
+        <div align="left">
+        <em>Application</em><ul>
+          <li>Duplicate group consensus and conservation rows shown when tree is partitioned</li>
+            <li>Erratic behaviour when tree partitions made with multiple cDNA/Protein split views</li>
+            </ul>
+        </div>
+      </td>
+    </tr>
+    <tr>
+      <td width="60" nowrap>
+        <div align="center">
           <strong><a name="Jalview.2.9.0b1">2.9.0b1</a><br />
             <em>8/10/2015</em></strong>
         </div>
index 67d89b7..19be76f 100755 (executable)
     <strong>What's new ?</strong>
   </p>
   <p>
-    Jalview 2.9.0b1 is a bug fix release for Jalview 2.9, which has been in development since December 2014. In addition
-    to a multitude of bug fixes and minor improvements (both small, and
+    Jalview 2.9.0b2 is a bug fix release for Jalview 2.9.
+    The release of Jalview 2.9 in September 2015 included
+    a multitude of bug fixes and minor improvements (both small, and
     rather big!), it also brings major new capabilities for codon-level
     analysis of protein alignments and the retrieval and manipulation of
-    structural data.</p><p>For the patches since version 2.9 was release, see the
-    <a href="releases.html#Jalview.2.9.0b1">Jalview 2.9.0b1 Release Notes</a>.
+    structural data.</p><p>For the patches since version 2.9 was released, see the
+    <a href="releases.html#Jalview.2.9.0b2">Jalview 2.9.0b2 Release Notes</a>.
   </p>
   <p>
     <strong>Highlights in Jalview 2.9</strong>
index 80ab5d5..50ec7e0 100644 (file)
@@ -2294,18 +2294,14 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
       TrimRegionCommand trimRegion;
       if (trimLeft)
       {
-        trimRegion = new TrimRegionCommand("Remove Left",
-                TrimRegionCommand.TRIM_LEFT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
+        trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
+                column, viewport.getAlignment());
         viewport.setStartRes(0);
       }
       else
       {
-        trimRegion = new TrimRegionCommand("Remove Right",
-                TrimRegionCommand.TRIM_RIGHT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
+        trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
+                column, viewport.getAlignment());
       }
 
       statusBar.setText(MessageManager.formatMessage(
@@ -2609,6 +2605,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
 
   }
 
+  @Override
   public void changeColour(ColourSchemeI cs)
   {
 
@@ -3759,6 +3756,7 @@ public class AlignFrame extends EmbmenuFrame implements ActionListener,
     this.add(statusBar, BorderLayout.SOUTH);
   }
 
+  @Override
   public void setStatus(String string)
   {
     statusBar.setText(string);
index b4d92a0..dc6c424 100644 (file)
 package jalview.commands;
 
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.ColumnSelection;
-import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.util.ShiftList;
-
-import java.util.List;
 
 public class TrimRegionCommand extends EditCommand
 {
-  public static String TRIM_LEFT = "TrimLeft";
-
-  public static String TRIM_RIGHT = "TrimRight";
-
-  public ColumnSelection colSel = null;
-
-  int[] start;
-
-  ShiftList shiftList;
-
-  SequenceGroup selectionGroup;
-
-  List<int[]> deletedHiddenColumns;
-
   int columnsDeleted;
 
-  public TrimRegionCommand(String description, String command,
-          SequenceI[] seqs, int column, AlignmentI al,
-          ColumnSelection colSel, SequenceGroup selectedRegion)
+  /**
+   * Constructs and performs a trim alignment command
+   * 
+   * @param description
+   *          (to show in Undo/Redo menu)
+   * @param trimLeft
+   *          if true trim to left of column, else to right
+   * @param seqs
+   *          the sequences to trim
+   * @param column
+   *          the alignment column (base 0) from which to trim
+   * @param al
+   */
+  public TrimRegionCommand(String description, boolean trimLeft,
+          SequenceI[] seqs, int column, AlignmentI al)
   {
     this.description = description;
-    this.selectionGroup = selectedRegion;
-    this.colSel = colSel;
-    if (command.equalsIgnoreCase(TRIM_LEFT))
+    if (trimLeft)
     {
       if (column == 0)
       {
@@ -64,109 +55,24 @@ public class TrimRegionCommand extends EditCommand
 
       setEdit(new Edit(Action.CUT, seqs, 0, column, al));
     }
-    else if (command.equalsIgnoreCase(TRIM_RIGHT))
+    else
     {
       int width = al.getWidth() - column - 1;
-      if (width < 2)
+      if (width < 1)
       {
         return;
       }
 
-      columnsDeleted = width - 1;
+      columnsDeleted = width;
 
       setEdit(new Edit(Action.CUT, seqs, column + 1, width, al));
     }
 
-    // We need to keep a record of the sequence start
-    // in order to restore the state after a redo
-    int i, isize = getEdit(0).seqs.length;
-    start = new int[isize];
-    for (i = 0; i < isize; i++)
-    {
-      start[i] = getEdit(0).seqs[i].getStart();
-    }
 
     performEdit(0, null);
   }
 
-  void cut(Edit command)
-  {
-    int column, j, jSize = command.seqs.length;
-    for (j = 0; j < jSize; j++)
-    {
-      if (command.position == 0)
-      {
-        // This is a TRIM_LEFT command
-        column = command.seqs[j].findPosition(command.number);
-        command.seqs[j].setStart(column);
-      }
-      else
-      {
-        // This is a TRIM_RIGHT command
-        column = command.seqs[j].findPosition(command.position) - 1;
-        command.seqs[j].setEnd(column);
-      }
-    }
-
-    super.cut(command, null);
-
-    if (command.position == 0)
-    {
-      deletedHiddenColumns = colSel.compensateForEdit(0, command.number);
-      if (selectionGroup != null)
-      {
-        selectionGroup.adjustForRemoveLeft(command.number);
-      }
-    }
-    else
-    {
-      deletedHiddenColumns = colSel.compensateForEdit(command.position,
-              command.number);
-      if (selectionGroup != null)
-      {
-        selectionGroup.adjustForRemoveRight(command.position);
-      }
-    }
-  }
-
-  void paste(Edit command)
-  {
-    super.paste(command, null);
-    int column, j, jSize = command.seqs.length;
-    for (j = 0; j < jSize; j++)
-    {
-      if (command.position == 0)
-      {
-        command.seqs[j].setStart(start[j]);
-      }
-      else
-      {
-        column = command.seqs[j].findPosition(command.number
-                + command.position) - 1;
-        command.seqs[j].setEnd(column);
-      }
-    }
-
-    if (command.position == 0)
-    {
-      colSel.compensateForEdit(0, -command.number);
-      if (selectionGroup != null)
-      {
-        selectionGroup.adjustForRemoveLeft(-command.number);
-      }
-    }
-
-    if (deletedHiddenColumns != null)
-    {
-      int[] region;
-      for (int i = 0; i < deletedHiddenColumns.size(); i++)
-      {
-        region = deletedHiddenColumns.get(i);
-        colSel.hideColumns(region[0], region[1]);
-      }
-    }
-  }
-
+  @Override
   public int getSize()
   {
     return columnsDeleted;
index a41e519..5e15195 100644 (file)
@@ -2572,18 +2572,14 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       TrimRegionCommand trimRegion;
       if (trimLeft)
       {
-        trimRegion = new TrimRegionCommand("Remove Left",
-                TrimRegionCommand.TRIM_LEFT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
+        trimRegion = new TrimRegionCommand("Remove Left", true, seqs,
+                column, viewport.getAlignment());
         viewport.setStartRes(0);
       }
       else
       {
-        trimRegion = new TrimRegionCommand("Remove Right",
-                TrimRegionCommand.TRIM_RIGHT, seqs, column,
-                viewport.getAlignment(), viewport.getColumnSelection(),
-                viewport.getSelectionGroup());
+        trimRegion = new TrimRegionCommand("Remove Right", false, seqs,
+                column, viewport.getAlignment());
       }
 
       statusBar.setText(MessageManager.formatMessage(
index b551f5d..61e20fa 100755 (executable)
@@ -44,6 +44,8 @@ import jalview.util.jarInputStreamProvider;
 import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
 
 import java.io.InputStreamReader;
+import java.io.Reader;
+import java.net.UnknownHostException;
 import java.util.Hashtable;
 import java.util.Vector;
 import java.util.jar.JarEntry;
@@ -51,8 +53,6 @@ import java.util.jar.JarInputStream;
 
 import javax.swing.JOptionPane;
 
-import org.exolab.castor.xml.IDResolver;
-
 /**
  * DOCUMENT ME!
  * 
@@ -127,33 +127,29 @@ public class Jalview2XML_V1
           jarentry = jin.getNextJarEntry();
         }
 
-        class NoDescIDResolver implements IDResolver
-        {
-          public Object resolve(String idref)
-          {
-            System.out.println(idref + " used");
-            return null;
-          }
-        }
-
         if (jarentry != null)
         {
-          InputStreamReader in = new InputStreamReader(jin, "UTF-8");
-          JalviewModel object = new JalviewModel();
+          entryCount++;
+          if (jarentry.getName().endsWith(".xml"))
+          {
+            Reader in = new InputStreamReader(jin, "UTF-8");
+            JalviewModel object = new JalviewModel();
 
-          object = object.unmarshal(in);
+            object = object.unmarshal(in);
 
-          af = LoadFromObject(object, file);
-          entryCount++;
+            af = LoadFromObject(object, file);
+          }
         }
+        jin.close();
       } while (jarentry != null);
-    } catch (final java.net.UnknownHostException ex)
+    } catch (final UnknownHostException ex)
     {
       ex.printStackTrace();
       if (raiseGUI)
       {
         javax.swing.SwingUtilities.invokeLater(new Runnable()
         {
+          @Override
           public void run()
           {
 
@@ -176,6 +172,7 @@ public class Jalview2XML_V1
       {
         javax.swing.SwingUtilities.invokeLater(new Runnable()
         {
+          @Override
           public void run()
           {
 
index 9cb3d18..90c74be 100755 (executable)
@@ -546,6 +546,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
   }
 
   // put printing in a thread to avoid painting problems
+  @Override
   public void run()
   {
     PrinterJob printJob = PrinterJob.getPrinterJob();
@@ -580,6 +581,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @throws PrinterException
    *           DOCUMENT ME!
    */
+  @Override
   public int print(Graphics pg, PageFormat pf, int pi)
           throws PrinterException
   {
@@ -634,6 +636,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param g
    *          DOCUMENT ME!
    */
+  @Override
   public void paintComponent(Graphics g)
   {
     super.paintComponent(g);
@@ -677,6 +680,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param fontSize
    *          DOCUMENT ME!
    */
+  @Override
   public void setFont(Font font)
   {
     this.font = font;
@@ -749,6 +753,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseReleased(MouseEvent e)
   {
   }
@@ -759,6 +764,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseEntered(MouseEvent e)
   {
   }
@@ -769,6 +775,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseExited(MouseEvent e)
   {
   }
@@ -779,6 +786,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void mouseClicked(MouseEvent evt)
   {
     if (highlightNode != null)
@@ -818,6 +826,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
     }
   }
 
+  @Override
   public void mouseMoved(MouseEvent evt)
   {
     av.setCurrentTree(tree);
@@ -843,6 +852,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
     }
   }
 
+  @Override
   public void mouseDragged(MouseEvent ect)
   {
   }
@@ -853,6 +863,7 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
    * @param e
    *          DOCUMENT ME!
    */
+  @Override
   public void mousePressed(MouseEvent e)
   {
     av.setCurrentTree(tree);
@@ -891,12 +902,13 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
           aps[a].av.setSelectionGroup(null);
           aps[a].av.getAlignment().deleteAllGroups();
           aps[a].av.clearSequenceColours();
-        }
-        if (av.getCodingComplement() != null)
-        {
-          av.getCodingComplement().setSelectionGroup(null);
-          av.getCodingComplement().getAlignment().deleteAllGroups();
-          av.getCodingComplement().clearSequenceColours();
+          if (aps[a].av.getCodingComplement() != null)
+          {
+            aps[a].av.getCodingComplement().setSelectionGroup(null);
+            aps[a].av.getCodingComplement().getAlignment()
+                    .deleteAllGroups();
+            aps[a].av.getCodingComplement().clearSequenceColours();
+          }
         }
         colourGroups();
       }
@@ -977,42 +989,45 @@ public class TreeCanvas extends JPanel implements MouseListener, Runnable,
         }
 
         aps[a].av.getAlignment().addGroup(new SequenceGroup(sg));
-      }
-
-      // TODO can we push all of the below into AlignViewportI?
-      av.getAlignment().addGroup(sg);
-      final AlignViewportI codingComplement = av.getCodingComplement();
-      if (codingComplement != null)
-      {
-        SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg, av,
-                codingComplement);
-        if (mappedGroup.getSequences().size() > 0)
+        // TODO can we push all of the below into AlignViewportI?
+        final AlignViewportI codingComplement = aps[a].av
+                .getCodingComplement();
+        if (codingComplement != null)
         {
-          codingComplement.getAlignment().addGroup(mappedGroup);
-          for (SequenceI seq : mappedGroup.getSequences())
+          if (codingComplement != null)
           {
-            codingComplement.setSequenceColour(seq, col.brighter());
+            SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
+                    av, codingComplement);
+            if (mappedGroup.getSequences().size() > 0)
+            {
+              codingComplement.getAlignment().addGroup(mappedGroup);
+              for (SequenceI seq : mappedGroup.getSequences())
+              {
+                codingComplement.setSequenceColour(seq, col.brighter());
+              }
+            }
           }
         }
       }
     }
 
-    // notify the panel to redo any group specific stuff.
+    // notify the panel(s) to redo any group specific stuff.
     for (int a = 0; a < aps.length; a++)
     {
       aps[a].updateAnnotation();
       // TODO: JAL-868 - need to ensure view colour change message is broadcast
       // to any Jmols listening in
-    }
+      final AlignViewportI codingComplement = aps[a].av
+              .getCodingComplement();
+      if (codingComplement != null)
+      {
+        ((AlignViewport) codingComplement).getAlignPanel()
+                .updateAnnotation();
+
+      }
 
-    if (av.getCodingComplement() != null)
-    {
-      ((AlignViewport) av.getCodingComplement()).getAlignPanel()
-              .updateAnnotation();
-      /*
-       * idPanel. repaint ()
-       */
     }
+
   }
 
   /**
index 07ba3f5..71cc7f0 100755 (executable)
@@ -26,9 +26,8 @@ import jalview.util.Format;
 import jalview.util.MessageManager;
 
 import java.io.IOException;
-import java.util.Hashtable;
-import java.util.StringTokenizer;
-import java.util.Vector;
+import java.util.ArrayList;
+import java.util.HashMap;
 
 public class PfamFile extends AlignFile
 {
@@ -47,57 +46,70 @@ public class PfamFile extends AlignFile
     super(source);
   }
 
+  @Override
   public void initData()
   {
     super.initData();
   }
 
+  @Override
   public void parse() throws IOException
   {
     int i = 0;
     String line;
 
-    Hashtable seqhash = new Hashtable();
-    Vector headers = new Vector();
-
+    HashMap<String, StringBuffer> seqhash = new HashMap<String, StringBuffer>();
+    ArrayList<String> headers = new ArrayList<String>();
+    boolean useTabs = false;
+    int spces;
     while ((line = nextLine()) != null)
     {
-      if (line.indexOf(" ") != 0)
+      if (line.indexOf("#") == 0)
+      {
+        // skip comment lines
+        continue;
+      }
+      // locate first space or (if already checked), tab
+      if (useTabs)
+      {
+        spces = line.indexOf("\t");
+      }
+      else
       {
-        if (line.indexOf("#") != 0)
+        spces = line.indexOf(" ");
+        // check to see if we ought to split on tabs instead.
+        if (!useTabs && spces == -1)
         {
-          // TODO: verify pfam format requires spaces and not tab characters -
-          // if not upgrade to use stevesoft regex and look for whitespace.
-          StringTokenizer str = new StringTokenizer(line, " ");
-          String id = "";
-
-          if (str.hasMoreTokens())
-          {
-            id = str.nextToken();
-
-            StringBuffer tempseq;
-
-            if (seqhash.containsKey(id))
-            {
-              tempseq = (StringBuffer) seqhash.get(id);
-            }
-            else
-            {
-              tempseq = new StringBuffer();
-              seqhash.put(id, tempseq);
-            }
-
-            if (!(headers.contains(id)))
-            {
-              headers.addElement(id);
-            }
-            if (str.hasMoreTokens())
-            {
-              tempseq.append(str.nextToken());
-            }
-          }
+          useTabs = true;
+          spces = line.indexOf("\t");
         }
       }
+      if (spces <= 0)
+      {
+        // no sequence data to split on
+        continue;
+      }
+      String id = line.substring(0, spces);
+      StringBuffer tempseq;
+
+      if (seqhash.containsKey(id))
+      {
+        tempseq = seqhash.get(id);
+      }
+      else
+      {
+        tempseq = new StringBuffer();
+        seqhash.put(id, tempseq);
+      }
+
+      if (!(headers.contains(id)))
+      {
+        headers.add(id);
+      }
+      if (spces + 1 < line.length())
+      {
+        tempseq.append(line.substring(spces + 1));
+      }
     }
 
     this.noSeqs = headers.size();
@@ -110,23 +122,23 @@ public class PfamFile extends AlignFile
 
     for (i = 0; i < headers.size(); i++)
     {
-      if (seqhash.get(headers.elementAt(i)) != null)
+      if (seqhash.get(headers.get(i)) != null)
       {
-        if (maxLength < seqhash.get(headers.elementAt(i)).toString()
+        if (maxLength < seqhash.get(headers.get(i)).toString()
                 .length())
         {
-          maxLength = seqhash.get(headers.elementAt(i)).toString().length();
+          maxLength = seqhash.get(headers.get(i)).toString().length();
         }
 
-        Sequence newSeq = parseId(headers.elementAt(i).toString());
-        newSeq.setSequence(seqhash.get(headers.elementAt(i).toString())
+        Sequence newSeq = parseId(headers.get(i).toString());
+        newSeq.setSequence(seqhash.get(headers.get(i).toString())
                 .toString());
         seqs.addElement(newSeq);
       }
       else
       {
         System.err.println("PFAM File reader: Can't find sequence for "
-                + headers.elementAt(i));
+                + headers.get(i));
       }
     }
   }
@@ -178,6 +190,7 @@ public class PfamFile extends AlignFile
     return out.toString();
   }
 
+  @Override
   public String print()
   {
     return print(getSeqsAsArray());
diff --git a/test/jalview/commands/TrimRegionCommandTest.java b/test/jalview/commands/TrimRegionCommandTest.java
new file mode 100644 (file)
index 0000000..d593d41
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ *  
+ * 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.commands;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.Sequence;
+import jalview.datamodel.SequenceI;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for TrimRegionCommand
+ * 
+ * @author gmcarstairs
+ *
+ */
+public class TrimRegionCommandTest
+{
+  private AlignmentI al;
+
+  @BeforeMethod(alwaysRun = true)
+  public void setUp()
+  {
+    SequenceI[] seqs = new SequenceI[2];
+    seqs[0] = new Sequence("seq0", "abcde-");
+    seqs[1] = new Sequence("seq1", "-ghjkl");
+    al = new Alignment(seqs);
+    al.setDataset(null);
+  }
+
+  /**
+   * Test performing, undoing and redoing a 'trim left'
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimLeft_withUndoAndRedo()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Left", true,
+            al.getSequencesArray(), 2, al);
+    assertEquals(2, cmd.getSize());
+    assertEquals("cde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("hjkl", al.getSequenceAt(1).getSequenceAsString());
+
+    /*
+     * undo and verify
+     */
+    cmd.undoCommand(new AlignmentI[] { al });
+    assertEquals("abcde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-ghjkl", al.getSequenceAt(1).getSequenceAsString());
+
+    /*
+     * redo and verify
+     */
+    cmd.doCommand(new AlignmentI[] { al });
+    assertEquals("cde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("hjkl", al.getSequenceAt(1).getSequenceAsString());
+  }
+
+  /**
+   * Trim left of no columns - should do nothing. This is the case where the
+   * first column is selected and 'Remove Left' is selected.
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimLeft_noColumns()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Left", true,
+            al.getSequencesArray(), 0, al);
+    assertEquals(0, cmd.getSize());
+    assertEquals("abcde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-ghjkl", al.getSequenceAt(1).getSequenceAsString());
+  }
+
+  /**
+   * Trim left of a single column
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimLeft_oneColumn()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Left", true,
+            al.getSequencesArray(), 1, al);
+    assertEquals(1, cmd.getSize());
+    assertEquals("bcde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("ghjkl", al.getSequenceAt(1).getSequenceAsString());
+  }
+
+  /**
+   * Trim right of no columns - should do nothing. This is the case where the
+   * last column is selected and 'Remove Right' is selected.
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimRight_noColumns()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Right", false,
+            al.getSequencesArray(), 5, al);
+    assertEquals(0, cmd.getSize());
+    assertEquals("abcde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-ghjkl", al.getSequenceAt(1).getSequenceAsString());
+  }
+
+  /**
+   * Trim right of a single column
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimRight_oneColumn()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Right", false,
+            al.getSequencesArray(), 4, al);
+    assertEquals(1, cmd.getSize());
+    assertEquals("abcde", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-ghjk", al.getSequenceAt(1).getSequenceAsString());
+  }
+
+  /**
+   * Test performing, undoing and redoing a 'trim right'
+   */
+  @Test(groups = { "Functional" })
+  public void testTrimRight_withUndoAndRedo()
+  {
+    TrimRegionCommand cmd = new TrimRegionCommand("Remove Right", false,
+            al.getSequencesArray(), 2, al);
+    assertEquals(3, cmd.getSize());
+    assertEquals("abc", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-gh", al.getSequenceAt(1).getSequenceAsString());
+
+    /*
+     * undo and verify
+     */
+    cmd.undoCommand(new AlignmentI[] { al });
+    assertEquals("abcde-", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-ghjkl", al.getSequenceAt(1).getSequenceAsString());
+
+    /*
+     * redo and verify
+     */
+    cmd.doCommand(new AlignmentI[] { al });
+    assertEquals("abc", al.getSequenceAt(0).getSequenceAsString());
+    assertEquals("-gh", al.getSequenceAt(1).getSequenceAsString());
+  }
+}
diff --git a/test/jalview/io/PfamFormatInputTest.java b/test/jalview/io/PfamFormatInputTest.java
new file mode 100644 (file)
index 0000000..5dd4ecb
--- /dev/null
@@ -0,0 +1,32 @@
+package jalview.io;
+
+import jalview.datamodel.AlignmentI;
+
+import java.io.IOException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class PfamFormatInputTest
+{
+  @Test
+  public void testPfamFormatNoLimits() throws IOException
+  {
+    AlignmentI al = new jalview.io.AppletFormatAdapter().readFile("ASEQ"
+            + '\t' + "...--FFAFAFF--", AppletFormatAdapter.PASTE, "PFAM");
+    Assert.assertEquals(1, al.getHeight(), "Wrong number of sequences");
+    Assert.assertTrue(al.hasValidSequence(),
+            "Didn't extract limits from PFAM ID");
+  }
+
+  @Test
+  public void testPfamFormatValidLimits() throws IOException
+  {
+    AlignmentI al = new jalview.io.AppletFormatAdapter().readFile(
+            "ASEQ/15-25" + '\t' + "...--FFAFAFF--",
+            AppletFormatAdapter.PASTE, "PFAM");
+    Assert.assertEquals(1, al.getHeight(), "Wrong number of sequences");
+    Assert.assertTrue(al.hasValidSequence(),
+            "Didn't extract limits from PFAM ID");
+  }
+}
index 6618789..0c2c998 100644 (file)
@@ -101,10 +101,10 @@ public class ComparisonTest
   }
 
   /**
-   * Test percentage identity calculation for two sequences.
+   * Test the percentage identity calculation for two sequences
    */
   @Test(groups = { "Functional" })
-  public void testPID_matchGaps()
+  public void testPID_includingGaps()
   {
     String seq1 = "ABCDEF";
     String seq2 = "abcdef";
@@ -114,6 +114,48 @@ public class ComparisonTest
     seq2 = "abcdefghijklmnopqrstuvwxyz";
     assertEquals("identical", 100f, Comparison.PID(seq1, seq2), 0.001f);
 
-    seq2 = "a---bcdef";
+    // 5 identical, 2 gap-gap, 2 gap-residue, 1 mismatch
+    seq1 = "a--b-cdefh";
+    seq2 = "a---bcdefg";
+    int length = seq1.length();
+
+    // match gap-residue, match gap-gap: 9/10 identical
+    assertEquals(90f, Comparison.PID(seq1, seq2, 0, length, true, false),
+            0.001f);
+    // overloaded version of the method signature above:
+    assertEquals(90f, Comparison.PID(seq1, seq2), 0.001f);
+
+    // don't match gap-residue, match gap-gap: 7/10 identical
+    assertEquals(70f, Comparison.PID(seq1, seq2, 0, length, false, false),
+            0.001f);
+  }
+
+  /**
+   * Test the percentage identity calculation for two sequences
+   */
+  @Test(groups = { "Functional" })
+  public void testPID_ungappedOnly()
+  {
+    // 5 identical, 2 gap-gap, 2 gap-residue, 1 mismatch
+    String seq1 = "a--b-cdefh";
+    String seq2 = "a---bcdefg";
+    int length = seq1.length();
+
+    /*
+     * As currently coded, 'ungappedOnly' ignores gap-residue but counts
+     * gap-gap. Is this a bug - should gap-gap also be ignored, giving a PID of
+     * 5/6?
+     * 
+     * Note also there is no variant of the calculation that penalises
+     * gap-residue i.e. counts it as a mismatch. This would give a score of 5/8
+     * (if we ignore gap-gap) or 5/10 (if we count gap-gap as a match).
+     */
+    // match gap-residue, match gap-gap: 7/8 identical
+    assertEquals(87.5f, Comparison.PID(seq1, seq2, 0, length, true, true),
+            0.001f);
+
+    // don't match gap-residue with 'ungapped only' - same as above
+    assertEquals(87.5f, Comparison.PID(seq1, seq2, 0, length, false, true),
+            0.001f);
   }
 }