X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fdatamodel%2Ffeatures%2FFeatureStore.java;h=02ce1c50a5f28eb59603bab4d7b7f7d335c4cfaa;hb=b320470d1ddb95476d3678477b72f6f791a51404;hp=7218b380cc4d07a36ff2d79650974fb341e292e9;hpb=b44349fe3a5f2d70b74a1b110018a753a1036aca;p=jalview.git diff --git a/src/jalview/datamodel/features/FeatureStore.java b/src/jalview/datamodel/features/FeatureStore.java index 7218b38..02ce1c5 100644 --- a/src/jalview/datamodel/features/FeatureStore.java +++ b/src/jalview/datamodel/features/FeatureStore.java @@ -1,5 +1,26 @@ +/* + * 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 . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ package jalview.datamodel.features; +import jalview.datamodel.ContiguousI; import jalview.datamodel.SequenceFeature; import java.util.ArrayList; @@ -32,6 +53,13 @@ public class FeatureStore */ abstract boolean compare(SequenceFeature entry); + /** + * serves a search condition for finding the first feature whose start + * position follows a given target location + * + * @param target + * @return + */ static SearchCriterion byStart(final long target) { return new SearchCriterion() { @@ -44,6 +72,13 @@ public class FeatureStore }; } + /** + * serves a search condition for finding the first feature whose end + * position is at or follows a given target location + * + * @param target + * @return + */ static SearchCriterion byEnd(final long target) { return new SearchCriterion() @@ -57,6 +92,13 @@ public class FeatureStore }; } + /** + * serves a search condition for finding the first feature which follows the + * given range as determined by a supplied comparator + * + * @param target + * @return + */ static SearchCriterion byFeature(final ContiguousI to, final Comparator rc) { @@ -158,6 +200,11 @@ public class FeatureStore */ public boolean addFeature(SequenceFeature feature) { + if (contains(feature)) + { + return false; + } + /* * keep a record of feature groups */ @@ -178,16 +225,13 @@ public class FeatureStore } else { - if (!contains(nonNestedFeatures, feature)) + added = addNonNestedFeature(feature); + if (!added) { - added = addNonNestedFeature(feature); - if (!added) - { - /* - * detected a nested feature - put it in the NCList structure - */ - added = addNestedFeature(feature); - } + /* + * detected a nested feature - put it in the NCList structure + */ + added = addNestedFeature(feature); } } @@ -224,6 +268,36 @@ public class FeatureStore } /** + * Answers true if this store contains the given feature (testing by + * SequenceFeature.equals), else false + * + * @param feature + * @return + */ + public boolean contains(SequenceFeature feature) + { + if (feature.isNonPositional()) + { + return nonPositionalFeatures == null ? false : nonPositionalFeatures + .contains(feature); + } + + if (feature.isContactFeature()) + { + return contactFeatureStarts == null ? false : listContains( + contactFeatureStarts, feature); + } + + if (listContains(nonNestedFeatures, feature)) + { + return true; + } + + return nestedFeatures == null ? false : nestedFeatures + .contains(feature); + } + + /** * Answers the 'length' of the feature, counting 0 for non-positional features * and 1 for contact features * @@ -245,10 +319,10 @@ public class FeatureStore /** * Adds the feature to the list of non-positional features (with lazy - * 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. The feature group is - * added to the set of distinct feature groups for non-positional features. + * instantiation of the list if it is null), and returns true. The feature + * group is added to the set of distinct feature groups for non-positional + * features. This method allows duplicate features, so test before calling to + * prevent this. * * @param feature */ @@ -258,10 +332,6 @@ public class FeatureStore { nonPositionalFeatures = new ArrayList(); } - if (nonPositionalFeatures.contains(feature)) - { - return false; - } nonPositionalFeatures.add(feature); @@ -280,7 +350,7 @@ public class FeatureStore { if (nestedFeatures == null) { - nestedFeatures = new NCList(feature); + nestedFeatures = new NCList<>(feature); return true; } return nestedFeatures.add(feature, false); @@ -361,8 +431,8 @@ public class FeatureStore /** * 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. If the contact feature lists already contain the - * given feature (by test for equality), does not add it and returns false. + * ordered, and returns true. This method allows duplicate features to be + * added, so test before calling to avoid this. * * @param feature * @return @@ -378,11 +448,6 @@ public class FeatureStore contactFeatureEnds = new ArrayList(); } - if (contains(contactFeatureStarts, feature)) - { - return false; - } - /* * binary search the sorted list to find the insertion point */ @@ -411,7 +476,7 @@ public class FeatureStore * @param feature * @return */ - protected static boolean contains(List features, + protected static boolean listContains(List features, SequenceFeature feature) { if (features == null || feature == null) @@ -454,7 +519,7 @@ public class FeatureStore */ public List findOverlappingFeatures(long start, long end) { - List result = new ArrayList(); + List result = new ArrayList<>(); findNonNestedFeatures(start, end, result); @@ -551,28 +616,15 @@ public class FeatureStore protected void findNonNestedFeatures(long from, long to, List result) { + /* + * find the first feature whose end position is + * after the target range start + */ int startIndex = binarySearch(nonNestedFeatures, SearchCriterion.byEnd(from)); - findNonNestedFeatures(startIndex, from, to, result); - } - - /** - * Scans the list of non-nested features, starting from startIndex, to find - * those that overlap the from-to range, and adds them to the result list. - * Returns the index of the first feature whose start position is after the - * target range (or the length of the whole list if none such feature exists). - * - * @param startIndex - * @param from - * @param to - * @param result - * @return - */ - protected int findNonNestedFeatures(final int startIndex, long from, - long to, List result) - { - int i = startIndex; + final int startIndex1 = startIndex; + int i = startIndex1; while (i < nonNestedFeatures.size()) { SequenceFeature sf = nonNestedFeatures.get(i); @@ -580,15 +632,12 @@ public class FeatureStore { break; } - int start = sf.getBegin(); - int end = sf.getEnd(); - if (start <= to && end >= from) + if (sf.getBegin() <= to && sf.getEnd() >= from) { result.add(sf); } i++; } - return i; } /** @@ -632,7 +681,7 @@ public class FeatureStore /* * add non-nested features (may be all features for many cases) */ - List result = new ArrayList(); + List result = new ArrayList<>(); result.addAll(nonNestedFeatures); /* @@ -666,7 +715,7 @@ public class FeatureStore { return Collections.emptyList(); } - return new ArrayList(contactFeatureStarts); + return new ArrayList<>(contactFeatureStarts); } /** @@ -681,7 +730,7 @@ public class FeatureStore { return Collections.emptyList(); } - return new ArrayList(nonPositionalFeatures); + return new ArrayList<>(nonPositionalFeatures); } /** @@ -819,27 +868,6 @@ public class FeatureStore } /** - * Scans all positional features to check whether the given feature group is - * found, and returns true if found, else false - * - * @param featureGroup - * @return - */ - protected boolean findFeatureGroup(String featureGroup) - { - for (SequenceFeature sf : getPositionalFeatures()) - { - String group = sf.getFeatureGroup(); - if (group == featureGroup - || (group != null && group.equals(featureGroup))) - { - return true; - } - } - return false; - } - - /** * Answers true if this store has no features, else false * * @return @@ -992,7 +1020,7 @@ public class FeatureStore public List getFeaturesForGroup(boolean positional, String group) { - List result = new ArrayList(); + List result = new ArrayList<>(); /* * if we know features don't include the target group, no need @@ -1046,7 +1074,7 @@ public class FeatureStore { newBegin = Math.max(1, newBegin); SequenceFeature sf2 = new SequenceFeature(sf, newBegin, newEnd, - sf.getFeatureGroup()); + sf.getFeatureGroup(), sf.getScore()); addFeature(sf2); } delete(sf);