package org.zstack.utils; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** */ public class RangeSet { public static class Range { private long start; private long end; public Range(long start, long end) { this.start = Math.min(start, end); this.end = Math.max(start, end); } public long getStart() { return start; } public void setStart(long start) { this.start = start; } public long getEnd() { return end; } public void setEnd(long end) { this.end = end; } public boolean isOverlap(Range r) { return (start <= r.end && r.end <= end) || (start <= r.start && r.start <= end); } public boolean isConnected(Range r) { return end + 1 == r.getStart() || r.getEnd() + 1 == start; } public void merge(Range r) { DebugUtils.Assert(isOverlap(r) || isConnected(r), String.format("range %s is not overlap with %s", toString(), r.toString())); start = Math.min(start, r.start); end = Math.max(end, r.end); } public boolean is(long s, long e) { return start == s && end == e; } @Override public String toString() { return String.format("[%s, %s]", start, end); } } private List<Range> ranges = new ArrayList<Range>(); public RangeSet open(long s, long e) { ranges.add(new Range(s+1, e-1)); return this; } public RangeSet closed(long s, long e) { ranges.add(new Range(s, e)); return this; } public RangeSet openClosed(long s, long e) { ranges.add(new Range(s+1, e)); return this; } public RangeSet closedOpen(long s, long e) { ranges.add(new Range(s, e-1)); return this; } public List<Range> merge() { List<Range> ret = new ArrayList<Range>(); if (ranges.isEmpty()) { return ret; } Collections.sort(ranges, new Comparator<Range>() { @Override public int compare(Range o1, Range o2) { return (int)(o1.start - o2.start); } }); Range r = ranges.get(0); for (int i=1; i<ranges.size(); i++) { Range r1 = ranges.get(i); if (r.isOverlap(r1) || r.isConnected(r1)) { r.merge(r1); } else { ret.add(r); r = r1; } } ret.add(r); return ret; } public List<Range> mergeAndSort() { List<Range> ret = merge(); Collections.sort(ranges, new Comparator<Range>() { @Override public int compare(Range o1, Range o2) { return (int)(o1.start - o2.start); } }); return ret; } }