public FeatureStore()
{
nonNestedFeatures = new ArrayList<SequenceFeature>();
- // we only construct contactFeatures and the NCList if we need to
+ // we only construct nonPositionalFeatures, contactFeatures
+ // or the NCList if we need to
}
/**
- * Add one entry to the data store
+ * Adds one sequence feature to the store, and returns true, unless the
+ * feature is already contained in the store, in which case this method
+ * returns false. Containment is determined by SequenceFeature.equals()
+ * comparison.
*
* @param feature
*/
- public void addFeature(SequenceFeature feature)
+ public boolean addFeature(SequenceFeature feature)
{
+ boolean added = false;
+
if (feature.isContactFeature())
{
- addContactFeature(feature);
+ added = addContactFeature(feature);
}
else if (feature.isNonPositional())
{
- addNonPositionalFeature(feature);
+ added = addNonPositionalFeature(feature);
}
else
{
- boolean added = addNonNestedFeature(feature);
- if (!added)
+ if (!nonNestedFeatures.contains(feature))
{
- /*
- * detected a nested feature - put it in the NCList structure
- */
- addNestedFeature(feature);
+ added = addNonNestedFeature(feature);
+ if (!added)
+ {
+ /*
+ * detected a nested feature - put it in the NCList structure
+ */
+ added = addNestedFeature(feature);
+ }
}
}
+
+ return added;
}
/**
* Adds the feature to the list of non-positional features (with lazy
- * instantiation of the list if it is null)
+ * instantiation of the list if it is null), and returns true. If the
+ * non-positional features already include the new feature (by equality test),
+ * then it is not added, and this method returns false.
*
* @param feature
*/
- protected void addNonPositionalFeature(SequenceFeature feature)
+ protected boolean addNonPositionalFeature(SequenceFeature feature)
{
if (nonPositionalFeatures == null)
{
nonPositionalFeatures = new ArrayList<SequenceFeature>();
}
+ if (nonPositionalFeatures.contains(feature))
+ {
+ return false;
+ }
nonPositionalFeatures.add(feature);
+ return true;
}
/**
* Adds one feature to the NCList that can manage nested features (creating
- * the NCList if necessary)
+ * the NCList if necessary), and returns true. If the feature is already
+ * stored in the NCList (by equality test), then it is not added, and this
+ * method returns false.
*/
- protected synchronized void addNestedFeature(SequenceFeature feature)
+ protected synchronized boolean addNestedFeature(SequenceFeature feature)
{
if (nestedFeatures == null)
{
nestedFeatures = new NCList<SequenceFeature>(feature);
+ return true;
}
- else
- {
- nestedFeatures.add(feature);
- }
+ return nestedFeatures.add(feature, false);
}
/**
/**
* 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
+ * ordered, and returns true. If the contact feature lists already contain the
+ * given feature (by test for equality), does not add it and returns false.
*
* @param feature
+ * @return
*/
- protected synchronized void addContactFeature(SequenceFeature feature)
+ protected synchronized boolean addContactFeature(SequenceFeature feature)
{
- // TODO binary search for insertion points!
if (contactFeatureStarts == null)
{
contactFeatureStarts = new ArrayList<SequenceFeature>();
{
contactFeatureEnds = new ArrayList<SequenceFeature>();
}
+
+ // TODO binary search for insertion points!
+ if (contactFeatureStarts.contains(feature))
+ {
+ return false;
+ }
+
contactFeatureStarts.add(feature);
Collections.sort(contactFeatureStarts, startOrdering);
contactFeatureEnds.add(feature);
Collections.sort(contactFeatureEnds, endOrdering);
+
+ return true;
}
/**
}
return new ArrayList<SequenceFeature>(nonPositionalFeatures);
}
+
+ /**
+ * 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 boolean delete(SequenceFeature sf)
+ {
+ /*
+ * try the non-nested positional features first
+ */
+ boolean removed = nonNestedFeatures.remove(sf);
+
+ /*
+ * if not found, 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)
+ {
+ removed = nonPositionalFeatures.remove(sf);
+ }
+
+ /*
+ * if not found, try nested features
+ */
+ if (!removed && nestedFeatures != null)
+ {
+ removed = nestedFeatures.delete(sf);
+ }
+
+ return removed;
+ }
}