Merge branch 'features/JAL-2446NCList' into bug/JAL-2541cutWithFeatures
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 27 Jun 2017 16:35:24 +0000 (17:35 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 27 Jun 2017 16:35:24 +0000 (17:35 +0100)
(Undo fails outstanding to resolve)

Conflicts:
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceI.java
test/jalview/datamodel/SequenceTest.java

1  2 
src/jalview/datamodel/Sequence.java
src/jalview/datamodel/SequenceI.java
src/jalview/datamodel/features/FeatureStore.java
src/jalview/datamodel/features/NCList.java
src/jalview/datamodel/features/SequenceFeatures.java
test/jalview/commands/EditCommandTest.java
test/jalview/datamodel/SequenceTest.java
test/jalview/datamodel/features/FeatureStoreTest.java
test/jalview/datamodel/features/SequenceFeaturesTest.java

Simple merge
Simple merge
@@@ -491,13 -452,4 +452,13 @@@ public class SequenceFeatures implement
      }
      return modified;
    }
 -}
 +
 +  /**
 +   * {@inheritDoc}
 +   */
 +  @Override
 +  public void deleteAll()
 +  {
 +    featureStore.clear();
 +  }
- }
++}
@@@ -34,6 -34,6 +34,8 @@@ import jalview.datamodel.SequenceI
  import jalview.datamodel.features.SequenceFeatures;
  import jalview.gui.JvOptionPane;
  
++import java.util.Collections;
++import java.util.Comparator;
  import java.util.List;
  import java.util.Map;
  
@@@ -768,6 -750,6 +770,19 @@@ public class EditCommandTes
          sfs = seq0.getSequenceFeatures();
  
          /*
++         * sort just for ease of inspection in the debugger
++         */
++        Collections.sort(sfs, new Comparator<SequenceFeature>()
++        {
++
++          @Override
++          public int compare(SequenceFeature o1, SequenceFeature o2)
++          {
++            return o1.getDescription().compareTo(o2.getDescription());
++          }
++        });
++
++        /*
           * confirm the number of features has reduced by the
           * number of features within the cut region i.e. by
           * func(length of cut)
          }
          else
          {
++          // failure in checkFeatureRelocation is more informative!
            assertEquals(msg + "wrong number of features left", func(5)
                    - func(to - from + 1), sfs.size());
          }
           * undo ready for next cut
           */
          testee.undoCommand(new AlignmentI[] { alignment });
-         int size = seq0.getSequenceFeatures().size();
-         assertEquals(func(5), size);
 -        assertEquals(func(5), seq0.getSequenceFeatures().size());
++        sfs = seq0.getSequenceFeatures();
++        assertEquals(func(5), sfs.size());
++        verifyUndo(from, to, sfs);
        }
      }
    }
  
    /**
++   * Check that after Undo, every feature has start/end that match its original
++   * "start" and "end" properties
++   * 
++   * @param from
++   * @param to
++   * @param sfs
++   */
++  protected void verifyUndo(int from, int to, List<SequenceFeature> sfs)
++  {
++    for (SequenceFeature sf : sfs)
++    {
++      final int oldFrom = ((Integer) sf.getValue("from")).intValue();
++      final int oldTo = ((Integer) sf.getValue("to")).intValue();
++      String msg = String.format(
++              "Undo cut of [%d-%d], feature at [%d-%d] ", from, to,
++              oldFrom, oldTo);
++      assertEquals(msg + "start", oldFrom, sf.getBegin());
++      assertEquals(msg + "end", oldTo, sf.getEnd());
++    }
++  }
++
++  /**
     * Helper method to check a feature has been correctly relocated after a cut
     * 
     * @param sf
@@@ -1419,23 -1343,21 +1419,22 @@@ public class SequenceTes
              null);
      sq.addSequenceFeature(sf0);
      // add feature on BCD
-     SequenceFeature sf1 = new SequenceFeature("Cath", "desc", 9, 11, 2f,
+     SequenceFeature sfBCD = new SequenceFeature("Cath", "desc", 9, 11, 2f,
              null);
-     sq.addSequenceFeature(sf1);
+     sq.addSequenceFeature(sfBCD);
      // add feature on DE
-     SequenceFeature sf2 = new SequenceFeature("Cath", "desc", 11, 12, 2f,
+     SequenceFeature sfDE = new SequenceFeature("Cath", "desc", 11, 12, 2f,
              null);
-     sq.addSequenceFeature(sf2);
+     sq.addSequenceFeature(sfDE);
      // add contact feature at [B, H]
-     SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc", 9,
 -    SequenceFeature sfContactBH = new SequenceFeature("Disulphide bond",
 -            "desc", 9, 15, 2f, null);
++    SequenceFeature sfContactBH = new SequenceFeature("Disulphide bond", "desc", 9,
 +            15, 2f,
 +            null);
-     sq.addSequenceFeature(sf3);
+     sq.addSequenceFeature(sfContactBH);
      // add contact feature at [F, G]
-     SequenceFeature sf4 = new SequenceFeature("Disulfide Bond", "desc", 13,
-             14, 2f,
-             null);
-     sq.addSequenceFeature(sf4);
+     SequenceFeature sfContactFG = new SequenceFeature("Disulfide Bond",
+             "desc", 13, 14, 2f, null);
+     sq.addSequenceFeature(sfContactFG);
  
      // no features in columns 1-2 (-A)
      List<SequenceFeature> found = sq.findFeatures(1, 2);
@@@ -827,31 -826,86 +827,112 @@@ public class FeatureStoreTes
      assertEquals(pos.get(0).getEnd(), 4);
      assertEquals(pos.get(1).getBegin(), 13);
      assertEquals(pos.get(1).getEnd(), 22);
 +
 +    /*
 +     * shift right by 4 from position 2 onwards
 +     * feature at [1-4] unchanged, feature at [13-22] shifts
 +     */
 +    assertTrue(fs.shiftFeatures(2, 4));
 +    pos = fs.getPositionalFeatures();
 +    assertEquals(pos.size(), 2);
 +    SequenceFeatures.sortFeatures(pos, true);
 +    assertEquals(pos.get(0).getBegin(), 1);
 +    assertEquals(pos.get(0).getEnd(), 4);
 +    assertEquals(pos.get(1).getBegin(), 17);
 +    assertEquals(pos.get(1).getEnd(), 26);
 +
 +    /*
 +     * shift right by 4 from position 18 onwards
 +     * should be no change
 +     */
 +    SequenceFeature f1 = pos.get(0);
 +    SequenceFeature f2 = pos.get(1);
 +    assertFalse(fs.shiftFeatures(18, 4)); // no update
 +    pos = fs.getPositionalFeatures();
 +    assertEquals(pos.size(), 2);
 +    SequenceFeatures.sortFeatures(pos, true);
 +    assertSame(pos.get(0), f1);
 +    assertSame(pos.get(1), f2);
    }
+   @Test(groups = "Functional")
+   public void testDelete_readd()
+   {
+     /*
+      * add a feature and a nested feature
+      */
+     FeatureStore store = new FeatureStore();
+     SequenceFeature sf1 = addFeature(store, 10, 20);
+     // sf2 is nested in sf1 so will be stored in nestedFeatures
+     SequenceFeature sf2 = addFeature(store, 12, 14);
+     List<SequenceFeature> features = store.getPositionalFeatures();
+     assertEquals(features.size(), 2);
+     assertTrue(features.contains(sf1));
+     assertTrue(features.contains(sf2));
+     assertTrue(store.nonNestedFeatures.contains(sf1));
+     assertTrue(store.nestedFeatures.contains(sf2));
+   
+     /*
+      * delete the first feature
+      */
+     assertTrue(store.delete(sf1));
+     features = store.getPositionalFeatures();
+     assertFalse(features.contains(sf1));
+     assertTrue(features.contains(sf2));
+     /*
+      * re-add the 'nested' feature; is it now duplicated?
+      */
+     store.addFeature(sf2);
+     features = store.getPositionalFeatures();
+     assertEquals(features.size(), 1);
+     assertTrue(features.contains(sf2));
+   }
+   @Test(groups = "Functional")
+   public void testContains()
+   {
+     FeatureStore fs = new FeatureStore();
+     SequenceFeature sf1 = new SequenceFeature("Cath", "", 10, 20,
+             Float.NaN, "group1");
+     SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 20,
+             Float.NaN, "group2");
+     SequenceFeature sf3 = new SequenceFeature("Cath", "", 0, 0, Float.NaN,
+             "group1");
+     SequenceFeature sf4 = new SequenceFeature("Cath", "", 0, 0, 0f,
+             "group1");
+     SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "", 5, 15,
+             Float.NaN, "group1");
+     SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "", 5, 15,
+             Float.NaN, "group2");
+     fs.addFeature(sf1);
+     fs.addFeature(sf3);
+     fs.addFeature(sf5);
+     assertTrue(fs.contains(sf1)); // positional feature
+     assertTrue(fs.contains(new SequenceFeature(sf1))); // identical feature
+     assertFalse(fs.contains(sf2)); // different group
+     assertTrue(fs.contains(sf3)); // non-positional
+     assertTrue(fs.contains(new SequenceFeature(sf3)));
+     assertFalse(fs.contains(sf4)); // different score
+     assertTrue(fs.contains(sf5)); // contact feature
+     assertTrue(fs.contains(new SequenceFeature(sf5)));
+     assertFalse(fs.contains(sf6)); // different group
+     /*
+      * add a nested feature
+      */
+     SequenceFeature sf7 = new SequenceFeature("Cath", "", 12, 16,
+             Float.NaN, "group1");
+     fs.addFeature(sf7);
+     assertTrue(fs.contains(sf7));
+     assertTrue(fs.contains(new SequenceFeature(sf7)));
+     /*
+      * delete the outer (enclosing, non-nested) feature
+      */
+     fs.delete(sf1);
+     assertFalse(fs.contains(sf1));
+     assertTrue(fs.contains(sf7));
+   }
  }