+ return contactFeatureStarts != null && feature.begin <= maxContactStart
+ && listContains(contactFeatureStarts, feature);
+ }
+
+ /**
+ * Answers true if this store already contains a non-positional feature equal
+ * to the given feature (by {@code SequenceFeature.equals()} test), else false
+ *
+ * @param feature
+ * @return
+ */
+ private boolean containsNonPositionalFeature(SequenceFeature feature)
+ {
+ return nonPositionalFeatures == null ? false
+ : nonPositionalFeatures.contains(feature);
+ }
+
+ /**
+ * Deletes the given feature from the store, returning true if it was found
+ * (and deleted), else false. This method makes no assumption that the feature
+ * is in the 'expected' place in the store, in case it has been modified since
+ * it was added.
+ *
+ * @param sf
+ */
+ public synchronized boolean delete(SequenceFeature sf)
+ {
+ boolean removed = false;
+
+ /*
+ * try contact positions (and if found, delete
+ * from both lists of contact positions)
+ */
+ if (!removed && contactFeatureStarts != null)
+ {
+ removed = contactFeatureStarts.remove(sf);
+ if (removed)
+ {
+ contactFeatureEnds.remove(sf);
+ }
+ }
+
+ /*
+ * if not found, try non-positional features
+ */
+ if (!removed && nonPositionalFeatures != null)