// implement Comparator public int compare(SargInterval i1, SargInterval i2) { int c = i1.getLowerBound().compareTo(i2.getLowerBound()); if (c != 0) { return c; } return i1.getUpperBound().compareTo(i2.getUpperBound()); }
private void intersectSequences(SargIntervalSequence targetSeq, SargIntervalSequence sourceSeq) { ListIterator<SargInterval> targetIter = targetSeq.list.listIterator(); if (!targetIter.hasNext()) { // No target intervals at all, so quit. return; } ListIterator<SargInterval> sourceIter = sourceSeq.list.listIterator(); if (!sourceIter.hasNext()) { // No source intervals at all, so result is empty targetSeq.list.clear(); return; } // Start working on first source and target intervals SargInterval target = targetIter.next(); SargInterval source = sourceIter.next(); // loop invariant: both source and target are non-null on entry for (; ; ) { if (source.getUpperBound().compareTo(target.getLowerBound()) < 0) { // Source is completely below target; discard it and // move on to next one. if (!sourceIter.hasNext()) { // No more sources. break; } source = sourceIter.next(); continue; } if (target.getUpperBound().compareTo(source.getLowerBound()) < 0) { // Target is completely below source; discard it and // move on to next one. targetIter.remove(); if (!targetIter.hasNext()) { // All done. return; } target = targetIter.next(); continue; } // Overlap case: perform intersection of the two intervals. if (source.getLowerBound().compareTo(target.getLowerBound()) > 0) { // Source starts after target starts, so trim the target. target.setLower( source.getLowerBound().getCoordinate(), source.getLowerBound().getStrictness()); } int c = source.getUpperBound().compareTo(target.getUpperBound()); if (c < 0) { // The source ends before the target ends, so split the target // into two parts. The first part will be kept for sure; the // second part will be compared against further source ranges. SargInterval newTarget = new SargInterval(factory, dataType); newTarget.setLower( source.getUpperBound().getCoordinate(), source.getUpperBound().getStrictnessComplement()); if (target.getUpperBound().isFinite()) { newTarget.setUpper( target.getUpperBound().getCoordinate(), target.getUpperBound().getStrictness()); } // Trim current target to exclude the part of the range // which will move to newTarget. target.setUpper( source.getUpperBound().getCoordinate(), source.getUpperBound().getStrictness()); // Insert newTarget after target. This makes newTarget // into previous(). targetIter.add(newTarget); // Next time through, work on newTarget. // targetIter.previous() is pointing at the newTarget. target = targetIter.previous(); // Now targetIter.next() is also pointing at the newTarget; // need to do this redundant step to get targetIter in sync // with target. target = targetIter.next(); // Advance source. if (!sourceIter.hasNext()) { break; } source = sourceIter.next(); } else if (c == 0) { // Source and target ends coincide, so advance both source and // target. if (!targetIter.hasNext()) { return; } target = targetIter.next(); if (!sourceIter.hasNext()) { break; } source = sourceIter.next(); } else { // Source ends after target ends, so advance target. assert (c > 0); if (!targetIter.hasNext()) { return; } target = targetIter.next(); } } // Discard any remaining targets since they didn't have corresponding // sources. for (; ; ) { targetIter.remove(); if (!targetIter.hasNext()) { break; } targetIter.next(); } }
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; }