private SargIntervalSequence evaluateIntersection(List<SargIntervalSequence> list) { SargIntervalSequence seq = null; if (list.isEmpty()) { // Counterintuitive but true: intersection of no sets is the // universal set (kinda like 2^0=1). One way to prove this to // yourself is to apply DeMorgan's law. The union of no sets is // certainly the empty set. So the complement of that union is the // universal set. That's equivalent to the intersection of the // complements of no sets, which is the intersection of no sets. // QED. seq = new SargIntervalSequence(); seq.addInterval(new SargInterval(factory, getDataType())); return seq; } // The way we evaluate the intersection is to start with the first // entry as a baseline, and then keep deleting stuff from it by // intersecting the other entrie in turn. Whatever makes it through // this filtering remains as the final result. for (SargIntervalSequence newSeq : list) { if (seq == null) { // first child seq = newSeq; continue; } intersectSequences(seq, newSeq); } return seq; }
private SargIntervalSequence evaluateUnion(List<SargIntervalSequence> list) { SargIntervalSequence seq = new SargIntervalSequence(); // Toss all entries from each sequence in the list into one big sorted // set. SortedSet<SargInterval> intervals = new TreeSet<SargInterval>(new IntervalComparator()); for (SargIntervalSequence childSeq : list) { intervals.addAll(childSeq.getList()); } // Now, overlapping ranges are consecutive in the set. Merge them by // increasing the upper bound of the first; discard the others. In the // example, [4, 6] and [5, 7) are combined to form [4, 7). (7, 8] is // not merged with the new range because neither range contains the // value 7. // // Input: // 1 2 3 4 5 6 7 8 9 // 1 [1, 3] [-----] // 2 [4, 6] [-----] // 3 [5, 7) [-----) // 4 (7, 8] (--] // // Output: // 1 [1, 3] [-----] // 2 [4, 7) [--------) // 3 (7, 8] (--] SargInterval accumulator = null; for (SargInterval interval : intervals) { // Empty intervals should have been previously filtered out. assert (!interval.isEmpty()); if (accumulator == null) { // The very first interval: start accumulating. accumulator = new SargInterval(factory, getDataType()); accumulator.copyFrom(interval); seq.addInterval(accumulator); continue; } if (accumulator.contains(interval)) { // Just drop new interval because it's already covered // by accumulator. continue; } // Test for overlap. int c = interval.getLowerBound().compareTo(accumulator.getUpperBound()); // If no overlap, test for touching instead. if (c > 0) { if (interval.getLowerBound().isTouching(accumulator.getUpperBound())) { // Force test below to pass. c = -1; } } if (c <= 0) { // Either touching or overlap: grow the accumulator. accumulator.upperBound.copyFrom(interval.getUpperBound()); } else { // Disjoint: start accumulating a new interval accumulator = new SargInterval(factory, getDataType()); accumulator.copyFrom(interval); seq.addInterval(accumulator); } } return seq; }