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(); } }