JAL-3397 final update
[jalview.git] / src / jalview / datamodel / features / FeatureStoreImpl.java
index 62832d7..63ee678 100644 (file)
@@ -25,9 +25,7 @@ import jalview.datamodel.SequenceFeature;
 import java.util.ArrayList;
 import java.util.List;
 
-import intervalstore.api.IntervalStoreI;
 import intervalstore.impl.BinarySearcher;
-import intervalstore.impl.IntervalStore;
 
 /**
  * A data store for a set of sequence features that supports efficient lookup of
@@ -42,7 +40,60 @@ public class FeatureStoreImpl extends FeatureStore
 
   public FeatureStoreImpl()
   {
-    features = new IntervalStore<>();
+    super();
+  }
+
+  public FeatureStoreImpl(int option)
+  {
+    super(option);
+  }
+
+  /**
+   * Add a contact feature to the lists that hold them ordered by start (first
+   * contact) and by end (second contact) position, ensuring the lists remain
+   * ordered, and returns true. This method allows duplicate features to be
+   * added, so test before calling to avoid this.
+   * 
+   * @param feature
+   * @return
+   */
+  @Override
+  protected synchronized boolean addContactFeature(SequenceFeature feature)
+  {
+    if (contactFeatureStarts == null)
+    {
+      contactFeatureStarts = new ArrayList<>();
+      contactFeatureEnds = new ArrayList<>();
+    }
+
+    /*
+     * insert into list sorted by start (first contact position):
+     * binary search the sorted list to find the insertion point
+     */
+    int insertPosition = findFirstBegin(contactFeatureStarts,
+            feature.getBegin());
+    contactFeatureStarts.add(insertPosition, feature);
+
+    /*
+     * insert into list sorted by end (second contact position):
+     * binary search the sorted list to find the insertion point
+     */
+    insertPosition = findFirstEnd(contactFeatureEnds,
+            feature.getEnd());
+    contactFeatureEnds.add(insertPosition, feature);
+
+    return true;
+  }
+
+  /**
+   * Adds one feature to the IntervalStore that can manage nested features
+   * (creating the IntervalStore if necessary)
+   */
+  @Override
+  protected synchronized boolean addPositionalFeature(
+          SequenceFeature feature)
+  {
+    return features.add(feature);
   }
 
   /**
@@ -64,6 +115,12 @@ public class FeatureStoreImpl extends FeatureStore
     }
   }
 
+  @Override
+  protected boolean containsFeature(SequenceFeature feature)
+  {
+    return features.contains(feature);
+  }
+
   /**
    * Adds to the result list any contact features whose end (second contact
    * point), but not start (first contact point), lies in the query from-to
@@ -81,8 +138,7 @@ public class FeatureStoreImpl extends FeatureStore
      * find the first contact feature (if any) 
      * whose end point is not before the target range
      */
-    int index = BinarySearcher.findFirst(contactFeatureEnds,
-            f -> f.getEnd() >= from);
+    int index = findFirstEnd(contactFeatureEnds, from);
 
     int n = contactFeatureEnds.size();
     while (index < n)
@@ -136,8 +192,7 @@ public class FeatureStoreImpl extends FeatureStore
   private void findContactStartOverlaps(long from, long to,
           List<SequenceFeature> result)
   {
-    int index = BinarySearcher.findFirst(contactFeatureStarts,
-            f -> f.getBegin() >= from);
+    int index = findFirstBegin(contactFeatureStarts, from);
 
     while (index < contactFeatureStarts.size())
     {
@@ -193,10 +248,27 @@ public class FeatureStoreImpl extends FeatureStore
   private void findOverlaps(long start, long end,
           List<SequenceFeature> result)
   {
-    result.addAll(((IntervalStoreI<SequenceFeature>) features)
+    result.addAll(features
             .findOverlaps(start, end));
-    // TODO Auto-generated method stub
+  }
 
+  @Override
+  protected int findFirstBegin(List<SequenceFeature> list, long pos)
+  {
+    return BinarySearcher.findFirst(list, (int) pos,
+            BinarySearcher.fbegin);
+  }
+
+  @Override
+  protected int findFirstEnd(List<SequenceFeature> list, long pos)
+  {
+    return BinarySearcher.findFirst(list, (int) pos, BinarySearcher.fend);
+  }
+
+  @Override
+  protected boolean findAndRemoveNonContactFeature(SequenceFeature sf)
+  {
+    return features.remove(sf);
   }
 
 }