X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2Ffeatures%2FNCNode.java;fp=src%2Fjalview%2Fdatamodel%2Ffeatures%2FNCNode.java;h=007f3b12cbd7b8821bd9b84676c38d38f38dfcc4;hb=9f70ff4b6d193b340031997634c9e3602486bc8e;hp=0000000000000000000000000000000000000000;hpb=76844c43faeeeba369deaf42f1998ca0fb33d956;p=jalview.git diff --git a/src/jalview/datamodel/features/NCNode.java b/src/jalview/datamodel/features/NCNode.java new file mode 100644 index 0000000..007f3b1 --- /dev/null +++ b/src/jalview/datamodel/features/NCNode.java @@ -0,0 +1,255 @@ +package jalview.datamodel.features; + +import jalview.datamodel.ContiguousI; + +import java.util.ArrayList; +import java.util.List; + +/** + * Each node of the NCList tree consists of a range, and (optionally) the NCList + * of ranges it encloses + * + * @param + */ +class NCNode implements ContiguousI +{ + /* + * deep size (number of ranges included) + */ + private int size; + + private V region; + + /* + * null, or an object holding contained subregions of this nodes region + */ + private NCList subregions; + + /** + * Constructor given a list of ranges + * + * @param ranges + */ + NCNode(List ranges) + { + build(ranges); + } + + /** + * Constructor given a single range + * + * @param range + */ + NCNode(V range) + { + List ranges = new ArrayList<>(); + ranges.add(range); + build(ranges); + } + + NCNode(V entry, NCList newNCList) + { + region = entry; + subregions = newNCList; + size = 1 + newNCList.size(); + } + + /** + * @param ranges + */ + protected void build(List ranges) + { + size = ranges.size(); + + if (!ranges.isEmpty()) + { + region = ranges.get(0); + } + if (ranges.size() > 1) + { + subregions = new NCList(ranges.subList(1, ranges.size())); + } + } + + @Override + public int getBegin() + { + return region.getBegin(); + } + + @Override + public int getEnd() + { + return region.getEnd(); + } + + /** + * Formats the node as a bracketed list e.g. + * + *
+   * [1-100 [10-30 [10-20]], 15-30 [20-20]]
+   * 
+ */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(10 * size); + sb.append(region.getBegin()).append("-").append(region.getEnd()); + if (subregions != null) + { + sb.append(" ").append(subregions.toString()); + } + return sb.toString(); + } + + void prettyPrint(StringBuilder sb, int offset, int indent) { + for (int i = 0 ; i < offset ; i++) { + sb.append(" "); + } + sb.append(region.getBegin()).append("-").append(region.getEnd()); + if (subregions != null) + { + sb.append(System.lineSeparator()); + subregions.prettyPrint(sb, offset + 2, indent); + } + } + /** + * Add any ranges that overlap the from-to range to the result list + * + * @param from + * @param to + * @param result + */ + void findOverlaps(long from, long to, List result) + { + if (region.getBegin() <= to && region.getEnd() >= from) + { + result.add(region); + } + if (subregions != null) + { + subregions.findOverlaps(from, to, result); + } + } + + /** + * Add one range to this subrange + * + * @param entry + */ + synchronized void add(V entry) + { + if (entry.getBegin() < region.getBegin() || entry.getEnd() > region.getEnd()) { + throw new IllegalArgumentException(String.format( + "adding improper subrange %d-%d to range %d-%d", + entry.getBegin(), entry.getEnd(), region.getBegin(), + region.getEnd())); + } + if (subregions == null) + { + subregions = new NCList(entry); + } + else + { + subregions.add(entry); + } + size++; + } + + /** + * Answers true if the data held satisfy the rules of construction of an + * NCList, else false. + * + * @return + */ + boolean isValid() + { + /* + * we don't handle reverse ranges + */ + if (region != null && region.getBegin() > region.getEnd()) + { + return false; + } + if (subregions == null) + { + return true; + } + return subregions.isValid(getBegin(), getEnd()); + } + + /** + * Adds all contained entries to the given list + * + * @param entries + */ + void getEntries(List entries) + { + entries.add(region); + if (subregions != null) + { + subregions.getEntries(entries); + } + } + + /** + * Answers true if this object contains the given entry (by object equals + * test), else false + * + * @param entry + * @return + */ + boolean contains(V entry) + { + if (entry == null) + { + return false; + } + if (entry.equals(region)) + { + return true; + } + return subregions == null ? false : subregions.contains(entry); + } + + /** + * Answers the 'root' region modelled by this object + * + * @return + */ + V getRegion() + { + return region; + } + + /** + * Answers the (possibly null) contained regions within this object + * + * @return + */ + NCList getSubRegions() + { + return subregions; + } + + /** + * Nulls the subregion reference if it is empty (after a delete entry + * operation) + */ + void deleteSubRegionsIfEmpty() + { + if (subregions != null && subregions.size() == 0) + { + subregions = null; + } + } + + /** + * Answers the (deep) size of this node i.e. the number of ranges it models + * + * @return + */ + int size() + { + return size; + } +}