001/*
002 * Copyright (C) 2011 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.collect;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019
020import com.google.common.annotations.GwtIncompatible;
021import com.google.common.annotations.VisibleForTesting;
022import com.google.common.base.MoreObjects;
023import com.google.errorprone.annotations.concurrent.LazyInit;
024import java.io.Serializable;
025import java.util.Collection;
026import java.util.Comparator;
027import java.util.Iterator;
028import java.util.Map.Entry;
029import java.util.NavigableMap;
030import java.util.NoSuchElementException;
031import java.util.Set;
032import java.util.TreeMap;
033import javax.annotation.CheckForNull;
034
035/**
036 * An implementation of {@link RangeSet} backed by a {@link TreeMap}.
037 *
038 * @author Louis Wasserman
039 * @since 14.0
040 */
041@GwtIncompatible // uses NavigableMap
042@ElementTypesAreNonnullByDefault
043public class TreeRangeSet<C extends Comparable<?>> extends AbstractRangeSet<C>
044    implements Serializable {
045
046  @VisibleForTesting final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
047
048  /** Creates an empty {@code TreeRangeSet} instance. */
049  public static <C extends Comparable<?>> TreeRangeSet<C> create() {
050    return new TreeRangeSet<>(new TreeMap<Cut<C>, Range<C>>());
051  }
052
053  /** Returns a {@code TreeRangeSet} initialized with the ranges in the specified range set. */
054  public static <C extends Comparable<?>> TreeRangeSet<C> create(RangeSet<C> rangeSet) {
055    TreeRangeSet<C> result = create();
056    result.addAll(rangeSet);
057    return result;
058  }
059
060  /**
061   * Returns a {@code TreeRangeSet} representing the union of the specified ranges.
062   *
063   * <p>This is the smallest {@code RangeSet} which encloses each of the specified ranges. An
064   * element will be contained in this {@code RangeSet} if and only if it is contained in at least
065   * one {@code Range} in {@code ranges}.
066   *
067   * @since 21.0
068   */
069  public static <C extends Comparable<?>> TreeRangeSet<C> create(Iterable<Range<C>> ranges) {
070    TreeRangeSet<C> result = create();
071    result.addAll(ranges);
072    return result;
073  }
074
075  private TreeRangeSet(NavigableMap<Cut<C>, Range<C>> rangesByLowerCut) {
076    this.rangesByLowerBound = rangesByLowerCut;
077  }
078
079  @LazyInit @CheckForNull private transient Set<Range<C>> asRanges;
080  @LazyInit @CheckForNull private transient Set<Range<C>> asDescendingSetOfRanges;
081
082  @Override
083  public Set<Range<C>> asRanges() {
084    Set<Range<C>> result = asRanges;
085    return (result == null) ? asRanges = new AsRanges(rangesByLowerBound.values()) : result;
086  }
087
088  @Override
089  public Set<Range<C>> asDescendingSetOfRanges() {
090    Set<Range<C>> result = asDescendingSetOfRanges;
091    return (result == null)
092        ? asDescendingSetOfRanges = new AsRanges(rangesByLowerBound.descendingMap().values())
093        : result;
094  }
095
096  final class AsRanges extends ForwardingCollection<Range<C>> implements Set<Range<C>> {
097
098    final Collection<Range<C>> delegate;
099
100    AsRanges(Collection<Range<C>> delegate) {
101      this.delegate = delegate;
102    }
103
104    @Override
105    protected Collection<Range<C>> delegate() {
106      return delegate;
107    }
108
109    @Override
110    public int hashCode() {
111      return Sets.hashCodeImpl(this);
112    }
113
114    @Override
115    public boolean equals(@CheckForNull Object o) {
116      return Sets.equalsImpl(this, o);
117    }
118  }
119
120  @Override
121  @CheckForNull
122  public Range<C> rangeContaining(C value) {
123    checkNotNull(value);
124    Entry<Cut<C>, Range<C>> floorEntry = rangesByLowerBound.floorEntry(Cut.belowValue(value));
125    if (floorEntry != null && floorEntry.getValue().contains(value)) {
126      return floorEntry.getValue();
127    } else {
128      // TODO(kevinb): revisit this design choice
129      return null;
130    }
131  }
132
133  @Override
134  public boolean intersects(Range<C> range) {
135    checkNotNull(range);
136    Entry<Cut<C>, Range<C>> ceilingEntry = rangesByLowerBound.ceilingEntry(range.lowerBound);
137    if (ceilingEntry != null
138        && ceilingEntry.getValue().isConnected(range)
139        && !ceilingEntry.getValue().intersection(range).isEmpty()) {
140      return true;
141    }
142    Entry<Cut<C>, Range<C>> priorEntry = rangesByLowerBound.lowerEntry(range.lowerBound);
143    return priorEntry != null
144        && priorEntry.getValue().isConnected(range)
145        && !priorEntry.getValue().intersection(range).isEmpty();
146  }
147
148  @Override
149  public boolean encloses(Range<C> range) {
150    checkNotNull(range);
151    Entry<Cut<C>, Range<C>> floorEntry = rangesByLowerBound.floorEntry(range.lowerBound);
152    return floorEntry != null && floorEntry.getValue().encloses(range);
153  }
154
155  @CheckForNull
156  private Range<C> rangeEnclosing(Range<C> range) {
157    checkNotNull(range);
158    Entry<Cut<C>, Range<C>> floorEntry = rangesByLowerBound.floorEntry(range.lowerBound);
159    return (floorEntry != null && floorEntry.getValue().encloses(range))
160        ? floorEntry.getValue()
161        : null;
162  }
163
164  @Override
165  public Range<C> span() {
166    Entry<Cut<C>, Range<C>> firstEntry = rangesByLowerBound.firstEntry();
167    Entry<Cut<C>, Range<C>> lastEntry = rangesByLowerBound.lastEntry();
168    if (firstEntry == null || lastEntry == null) {
169      /*
170       * Either both are null or neither is: Either the set is empty, or it's not. But we check both
171       * to make the nullness checker happy.
172       */
173      throw new NoSuchElementException();
174    }
175    return Range.create(firstEntry.getValue().lowerBound, lastEntry.getValue().upperBound);
176  }
177
178  @Override
179  public void add(Range<C> rangeToAdd) {
180    checkNotNull(rangeToAdd);
181
182    if (rangeToAdd.isEmpty()) {
183      return;
184    }
185
186    // We will use { } to illustrate ranges currently in the range set, and < >
187    // to illustrate rangeToAdd.
188    Cut<C> lbToAdd = rangeToAdd.lowerBound;
189    Cut<C> ubToAdd = rangeToAdd.upperBound;
190
191    Entry<Cut<C>, Range<C>> entryBelowLB = rangesByLowerBound.lowerEntry(lbToAdd);
192    if (entryBelowLB != null) {
193      // { <
194      Range<C> rangeBelowLB = entryBelowLB.getValue();
195      if (rangeBelowLB.upperBound.compareTo(lbToAdd) >= 0) {
196        // { < }, and we will need to coalesce
197        if (rangeBelowLB.upperBound.compareTo(ubToAdd) >= 0) {
198          // { < > }
199          ubToAdd = rangeBelowLB.upperBound;
200          /*
201           * TODO(cpovirk): can we just "return;" here? Or, can we remove this if() entirely? If
202           * not, add tests to demonstrate the problem with each approach
203           */
204        }
205        lbToAdd = rangeBelowLB.lowerBound;
206      }
207    }
208
209    Entry<Cut<C>, Range<C>> entryBelowUB = rangesByLowerBound.floorEntry(ubToAdd);
210    if (entryBelowUB != null) {
211      // { >
212      Range<C> rangeBelowUB = entryBelowUB.getValue();
213      if (rangeBelowUB.upperBound.compareTo(ubToAdd) >= 0) {
214        // { > }, and we need to coalesce
215        ubToAdd = rangeBelowUB.upperBound;
216      }
217    }
218
219    // Remove ranges which are strictly enclosed.
220    rangesByLowerBound.subMap(lbToAdd, ubToAdd).clear();
221
222    replaceRangeWithSameLowerBound(Range.create(lbToAdd, ubToAdd));
223  }
224
225  @Override
226  public void remove(Range<C> rangeToRemove) {
227    checkNotNull(rangeToRemove);
228
229    if (rangeToRemove.isEmpty()) {
230      return;
231    }
232
233    // We will use { } to illustrate ranges currently in the range set, and < >
234    // to illustrate rangeToRemove.
235
236    Entry<Cut<C>, Range<C>> entryBelowLB = rangesByLowerBound.lowerEntry(rangeToRemove.lowerBound);
237    if (entryBelowLB != null) {
238      // { <
239      Range<C> rangeBelowLB = entryBelowLB.getValue();
240      if (rangeBelowLB.upperBound.compareTo(rangeToRemove.lowerBound) >= 0) {
241        // { < }, and we will need to subdivide
242        if (rangeToRemove.hasUpperBound()
243            && rangeBelowLB.upperBound.compareTo(rangeToRemove.upperBound) >= 0) {
244          // { < > }
245          replaceRangeWithSameLowerBound(
246              Range.create(rangeToRemove.upperBound, rangeBelowLB.upperBound));
247        }
248        replaceRangeWithSameLowerBound(
249            Range.create(rangeBelowLB.lowerBound, rangeToRemove.lowerBound));
250      }
251    }
252
253    Entry<Cut<C>, Range<C>> entryBelowUB = rangesByLowerBound.floorEntry(rangeToRemove.upperBound);
254    if (entryBelowUB != null) {
255      // { >
256      Range<C> rangeBelowUB = entryBelowUB.getValue();
257      if (rangeToRemove.hasUpperBound()
258          && rangeBelowUB.upperBound.compareTo(rangeToRemove.upperBound) >= 0) {
259        // { > }
260        replaceRangeWithSameLowerBound(
261            Range.create(rangeToRemove.upperBound, rangeBelowUB.upperBound));
262      }
263    }
264
265    rangesByLowerBound.subMap(rangeToRemove.lowerBound, rangeToRemove.upperBound).clear();
266  }
267
268  private void replaceRangeWithSameLowerBound(Range<C> range) {
269    if (range.isEmpty()) {
270      rangesByLowerBound.remove(range.lowerBound);
271    } else {
272      rangesByLowerBound.put(range.lowerBound, range);
273    }
274  }
275
276  @LazyInit @CheckForNull private transient RangeSet<C> complement;
277
278  @Override
279  public RangeSet<C> complement() {
280    RangeSet<C> result = complement;
281    return (result == null) ? complement = new Complement() : result;
282  }
283
284  @VisibleForTesting
285  static final class RangesByUpperBound<C extends Comparable<?>>
286      extends AbstractNavigableMap<Cut<C>, Range<C>> {
287    private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
288
289    /**
290     * upperBoundWindow represents the headMap/subMap/tailMap view of the entire "ranges by upper
291     * bound" map; it's a constraint on the *keys*, and does not affect the values.
292     */
293    private final Range<Cut<C>> upperBoundWindow;
294
295    RangesByUpperBound(NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
296      this.rangesByLowerBound = rangesByLowerBound;
297      this.upperBoundWindow = Range.all();
298    }
299
300    private RangesByUpperBound(
301        NavigableMap<Cut<C>, Range<C>> rangesByLowerBound, Range<Cut<C>> upperBoundWindow) {
302      this.rangesByLowerBound = rangesByLowerBound;
303      this.upperBoundWindow = upperBoundWindow;
304    }
305
306    private NavigableMap<Cut<C>, Range<C>> subMap(Range<Cut<C>> window) {
307      if (window.isConnected(upperBoundWindow)) {
308        return new RangesByUpperBound<>(rangesByLowerBound, window.intersection(upperBoundWindow));
309      } else {
310        return ImmutableSortedMap.of();
311      }
312    }
313
314    @Override
315    public NavigableMap<Cut<C>, Range<C>> subMap(
316        Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
317      return subMap(
318          Range.range(
319              fromKey, BoundType.forBoolean(fromInclusive),
320              toKey, BoundType.forBoolean(toInclusive)));
321    }
322
323    @Override
324    public NavigableMap<Cut<C>, Range<C>> headMap(Cut<C> toKey, boolean inclusive) {
325      return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive)));
326    }
327
328    @Override
329    public NavigableMap<Cut<C>, Range<C>> tailMap(Cut<C> fromKey, boolean inclusive) {
330      return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive)));
331    }
332
333    @Override
334    public Comparator<? super Cut<C>> comparator() {
335      return Ordering.<Cut<C>>natural();
336    }
337
338    @Override
339    public boolean containsKey(@CheckForNull Object key) {
340      return get(key) != null;
341    }
342
343    @Override
344    @CheckForNull
345    public Range<C> get(@CheckForNull Object key) {
346      if (key instanceof Cut) {
347        try {
348          @SuppressWarnings("unchecked") // we catch CCEs
349          Cut<C> cut = (Cut<C>) key;
350          if (!upperBoundWindow.contains(cut)) {
351            return null;
352          }
353          Entry<Cut<C>, Range<C>> candidate = rangesByLowerBound.lowerEntry(cut);
354          if (candidate != null && candidate.getValue().upperBound.equals(cut)) {
355            return candidate.getValue();
356          }
357        } catch (ClassCastException e) {
358          return null;
359        }
360      }
361      return null;
362    }
363
364    @Override
365    Iterator<Entry<Cut<C>, Range<C>>> entryIterator() {
366      /*
367       * We want to start the iteration at the first range where the upper bound is in
368       * upperBoundWindow.
369       */
370      Iterator<Range<C>> backingItr;
371      if (!upperBoundWindow.hasLowerBound()) {
372        backingItr = rangesByLowerBound.values().iterator();
373      } else {
374        Entry<Cut<C>, Range<C>> lowerEntry =
375            rangesByLowerBound.lowerEntry(upperBoundWindow.lowerEndpoint());
376        if (lowerEntry == null) {
377          backingItr = rangesByLowerBound.values().iterator();
378        } else if (upperBoundWindow.lowerBound.isLessThan(lowerEntry.getValue().upperBound)) {
379          backingItr = rangesByLowerBound.tailMap(lowerEntry.getKey(), true).values().iterator();
380        } else {
381          backingItr =
382              rangesByLowerBound
383                  .tailMap(upperBoundWindow.lowerEndpoint(), true)
384                  .values()
385                  .iterator();
386        }
387      }
388      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
389        @Override
390        @CheckForNull
391        protected Entry<Cut<C>, Range<C>> computeNext() {
392          if (!backingItr.hasNext()) {
393            return endOfData();
394          }
395          Range<C> range = backingItr.next();
396          if (upperBoundWindow.upperBound.isLessThan(range.upperBound)) {
397            return endOfData();
398          } else {
399            return Maps.immutableEntry(range.upperBound, range);
400          }
401        }
402      };
403    }
404
405    @Override
406    Iterator<Entry<Cut<C>, Range<C>>> descendingEntryIterator() {
407      Collection<Range<C>> candidates;
408      if (upperBoundWindow.hasUpperBound()) {
409        candidates =
410            rangesByLowerBound
411                .headMap(upperBoundWindow.upperEndpoint(), false)
412                .descendingMap()
413                .values();
414      } else {
415        candidates = rangesByLowerBound.descendingMap().values();
416      }
417      PeekingIterator<Range<C>> backingItr = Iterators.peekingIterator(candidates.iterator());
418      if (backingItr.hasNext()
419          && upperBoundWindow.upperBound.isLessThan(backingItr.peek().upperBound)) {
420        backingItr.next();
421      }
422      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
423        @Override
424        @CheckForNull
425        protected Entry<Cut<C>, Range<C>> computeNext() {
426          if (!backingItr.hasNext()) {
427            return endOfData();
428          }
429          Range<C> range = backingItr.next();
430          return upperBoundWindow.lowerBound.isLessThan(range.upperBound)
431              ? Maps.immutableEntry(range.upperBound, range)
432              : endOfData();
433        }
434      };
435    }
436
437    @Override
438    public int size() {
439      if (upperBoundWindow.equals(Range.all())) {
440        return rangesByLowerBound.size();
441      }
442      return Iterators.size(entryIterator());
443    }
444
445    @Override
446    public boolean isEmpty() {
447      return upperBoundWindow.equals(Range.all())
448          ? rangesByLowerBound.isEmpty()
449          : !entryIterator().hasNext();
450    }
451  }
452
453  private static final class ComplementRangesByLowerBound<C extends Comparable<?>>
454      extends AbstractNavigableMap<Cut<C>, Range<C>> {
455    private final NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound;
456    private final NavigableMap<Cut<C>, Range<C>> positiveRangesByUpperBound;
457
458    /**
459     * complementLowerBoundWindow represents the headMap/subMap/tailMap view of the entire
460     * "complement ranges by lower bound" map; it's a constraint on the *keys*, and does not affect
461     * the values.
462     */
463    private final Range<Cut<C>> complementLowerBoundWindow;
464
465    ComplementRangesByLowerBound(NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound) {
466      this(positiveRangesByLowerBound, Range.<Cut<C>>all());
467    }
468
469    private ComplementRangesByLowerBound(
470        NavigableMap<Cut<C>, Range<C>> positiveRangesByLowerBound, Range<Cut<C>> window) {
471      this.positiveRangesByLowerBound = positiveRangesByLowerBound;
472      this.positiveRangesByUpperBound = new RangesByUpperBound<>(positiveRangesByLowerBound);
473      this.complementLowerBoundWindow = window;
474    }
475
476    private NavigableMap<Cut<C>, Range<C>> subMap(Range<Cut<C>> subWindow) {
477      if (!complementLowerBoundWindow.isConnected(subWindow)) {
478        return ImmutableSortedMap.of();
479      } else {
480        subWindow = subWindow.intersection(complementLowerBoundWindow);
481        return new ComplementRangesByLowerBound<>(positiveRangesByLowerBound, subWindow);
482      }
483    }
484
485    @Override
486    public NavigableMap<Cut<C>, Range<C>> subMap(
487        Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
488      return subMap(
489          Range.range(
490              fromKey, BoundType.forBoolean(fromInclusive),
491              toKey, BoundType.forBoolean(toInclusive)));
492    }
493
494    @Override
495    public NavigableMap<Cut<C>, Range<C>> headMap(Cut<C> toKey, boolean inclusive) {
496      return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive)));
497    }
498
499    @Override
500    public NavigableMap<Cut<C>, Range<C>> tailMap(Cut<C> fromKey, boolean inclusive) {
501      return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive)));
502    }
503
504    @Override
505    public Comparator<? super Cut<C>> comparator() {
506      return Ordering.<Cut<C>>natural();
507    }
508
509    @Override
510    Iterator<Entry<Cut<C>, Range<C>>> entryIterator() {
511      /*
512       * firstComplementRangeLowerBound is the first complement range lower bound inside
513       * complementLowerBoundWindow. Complement range lower bounds are either positive range upper
514       * bounds, or Cut.belowAll().
515       *
516       * positiveItr starts at the first positive range with lower bound greater than
517       * firstComplementRangeLowerBound. (Positive range lower bounds correspond to complement range
518       * upper bounds.)
519       */
520      Collection<Range<C>> positiveRanges;
521      if (complementLowerBoundWindow.hasLowerBound()) {
522        positiveRanges =
523            positiveRangesByUpperBound
524                .tailMap(
525                    complementLowerBoundWindow.lowerEndpoint(),
526                    complementLowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
527                .values();
528      } else {
529        positiveRanges = positiveRangesByUpperBound.values();
530      }
531      PeekingIterator<Range<C>> positiveItr = Iterators.peekingIterator(positiveRanges.iterator());
532      Cut<C> firstComplementRangeLowerBound;
533      if (complementLowerBoundWindow.contains(Cut.<C>belowAll())
534          && (!positiveItr.hasNext() || positiveItr.peek().lowerBound != Cut.<C>belowAll())) {
535        firstComplementRangeLowerBound = Cut.belowAll();
536      } else if (positiveItr.hasNext()) {
537        firstComplementRangeLowerBound = positiveItr.next().upperBound;
538      } else {
539        return Iterators.emptyIterator();
540      }
541      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
542        Cut<C> nextComplementRangeLowerBound = firstComplementRangeLowerBound;
543
544        @Override
545        @CheckForNull
546        protected Entry<Cut<C>, Range<C>> computeNext() {
547          if (complementLowerBoundWindow.upperBound.isLessThan(nextComplementRangeLowerBound)
548              || nextComplementRangeLowerBound == Cut.<C>aboveAll()) {
549            return endOfData();
550          }
551          Range<C> negativeRange;
552          if (positiveItr.hasNext()) {
553            Range<C> positiveRange = positiveItr.next();
554            negativeRange = Range.create(nextComplementRangeLowerBound, positiveRange.lowerBound);
555            nextComplementRangeLowerBound = positiveRange.upperBound;
556          } else {
557            negativeRange = Range.create(nextComplementRangeLowerBound, Cut.<C>aboveAll());
558            nextComplementRangeLowerBound = Cut.aboveAll();
559          }
560          return Maps.immutableEntry(negativeRange.lowerBound, negativeRange);
561        }
562      };
563    }
564
565    @Override
566    Iterator<Entry<Cut<C>, Range<C>>> descendingEntryIterator() {
567      /*
568       * firstComplementRangeUpperBound is the upper bound of the last complement range with lower
569       * bound inside complementLowerBoundWindow.
570       *
571       * positiveItr starts at the first positive range with upper bound less than
572       * firstComplementRangeUpperBound. (Positive range upper bounds correspond to complement range
573       * lower bounds.)
574       */
575      Cut<C> startingPoint =
576          complementLowerBoundWindow.hasUpperBound()
577              ? complementLowerBoundWindow.upperEndpoint()
578              : Cut.<C>aboveAll();
579      boolean inclusive =
580          complementLowerBoundWindow.hasUpperBound()
581              && complementLowerBoundWindow.upperBoundType() == BoundType.CLOSED;
582      PeekingIterator<Range<C>> positiveItr =
583          Iterators.peekingIterator(
584              positiveRangesByUpperBound
585                  .headMap(startingPoint, inclusive)
586                  .descendingMap()
587                  .values()
588                  .iterator());
589      Cut<C> cut;
590      if (positiveItr.hasNext()) {
591        cut =
592            (positiveItr.peek().upperBound == Cut.<C>aboveAll())
593                ? positiveItr.next().lowerBound
594                : positiveRangesByLowerBound.higherKey(positiveItr.peek().upperBound);
595      } else if (!complementLowerBoundWindow.contains(Cut.<C>belowAll())
596          || positiveRangesByLowerBound.containsKey(Cut.belowAll())) {
597        return Iterators.emptyIterator();
598      } else {
599        cut = positiveRangesByLowerBound.higherKey(Cut.<C>belowAll());
600      }
601      Cut<C> firstComplementRangeUpperBound = MoreObjects.firstNonNull(cut, Cut.<C>aboveAll());
602      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
603        Cut<C> nextComplementRangeUpperBound = firstComplementRangeUpperBound;
604
605        @Override
606        @CheckForNull
607        protected Entry<Cut<C>, Range<C>> computeNext() {
608          if (nextComplementRangeUpperBound == Cut.<C>belowAll()) {
609            return endOfData();
610          } else if (positiveItr.hasNext()) {
611            Range<C> positiveRange = positiveItr.next();
612            Range<C> negativeRange =
613                Range.create(positiveRange.upperBound, nextComplementRangeUpperBound);
614            nextComplementRangeUpperBound = positiveRange.lowerBound;
615            if (complementLowerBoundWindow.lowerBound.isLessThan(negativeRange.lowerBound)) {
616              return Maps.immutableEntry(negativeRange.lowerBound, negativeRange);
617            }
618          } else if (complementLowerBoundWindow.lowerBound.isLessThan(Cut.<C>belowAll())) {
619            Range<C> negativeRange = Range.create(Cut.<C>belowAll(), nextComplementRangeUpperBound);
620            nextComplementRangeUpperBound = Cut.belowAll();
621            return Maps.immutableEntry(Cut.<C>belowAll(), negativeRange);
622          }
623          return endOfData();
624        }
625      };
626    }
627
628    @Override
629    public int size() {
630      return Iterators.size(entryIterator());
631    }
632
633    @Override
634    @CheckForNull
635    public Range<C> get(@CheckForNull Object key) {
636      if (key instanceof Cut) {
637        try {
638          @SuppressWarnings("unchecked")
639          Cut<C> cut = (Cut<C>) key;
640          // tailMap respects the current window
641          Entry<Cut<C>, Range<C>> firstEntry = tailMap(cut, true).firstEntry();
642          if (firstEntry != null && firstEntry.getKey().equals(cut)) {
643            return firstEntry.getValue();
644          }
645        } catch (ClassCastException e) {
646          return null;
647        }
648      }
649      return null;
650    }
651
652    @Override
653    public boolean containsKey(@CheckForNull Object key) {
654      return get(key) != null;
655    }
656  }
657
658  private final class Complement extends TreeRangeSet<C> {
659    Complement() {
660      super(new ComplementRangesByLowerBound<C>(TreeRangeSet.this.rangesByLowerBound));
661    }
662
663    @Override
664    public void add(Range<C> rangeToAdd) {
665      TreeRangeSet.this.remove(rangeToAdd);
666    }
667
668    @Override
669    public void remove(Range<C> rangeToRemove) {
670      TreeRangeSet.this.add(rangeToRemove);
671    }
672
673    @Override
674    public boolean contains(C value) {
675      return !TreeRangeSet.this.contains(value);
676    }
677
678    @Override
679    public RangeSet<C> complement() {
680      return TreeRangeSet.this;
681    }
682  }
683
684  private static final class SubRangeSetRangesByLowerBound<C extends Comparable<?>>
685      extends AbstractNavigableMap<Cut<C>, Range<C>> {
686    /**
687     * lowerBoundWindow is the headMap/subMap/tailMap view; it only restricts the keys, and does not
688     * affect the values.
689     */
690    private final Range<Cut<C>> lowerBoundWindow;
691
692    /**
693     * restriction is the subRangeSet view; ranges are truncated to their intersection with
694     * restriction.
695     */
696    private final Range<C> restriction;
697
698    private final NavigableMap<Cut<C>, Range<C>> rangesByLowerBound;
699    private final NavigableMap<Cut<C>, Range<C>> rangesByUpperBound;
700
701    private SubRangeSetRangesByLowerBound(
702        Range<Cut<C>> lowerBoundWindow,
703        Range<C> restriction,
704        NavigableMap<Cut<C>, Range<C>> rangesByLowerBound) {
705      this.lowerBoundWindow = checkNotNull(lowerBoundWindow);
706      this.restriction = checkNotNull(restriction);
707      this.rangesByLowerBound = checkNotNull(rangesByLowerBound);
708      this.rangesByUpperBound = new RangesByUpperBound<>(rangesByLowerBound);
709    }
710
711    private NavigableMap<Cut<C>, Range<C>> subMap(Range<Cut<C>> window) {
712      if (!window.isConnected(lowerBoundWindow)) {
713        return ImmutableSortedMap.of();
714      } else {
715        return new SubRangeSetRangesByLowerBound<>(
716            lowerBoundWindow.intersection(window), restriction, rangesByLowerBound);
717      }
718    }
719
720    @Override
721    public NavigableMap<Cut<C>, Range<C>> subMap(
722        Cut<C> fromKey, boolean fromInclusive, Cut<C> toKey, boolean toInclusive) {
723      return subMap(
724          Range.range(
725              fromKey,
726              BoundType.forBoolean(fromInclusive),
727              toKey,
728              BoundType.forBoolean(toInclusive)));
729    }
730
731    @Override
732    public NavigableMap<Cut<C>, Range<C>> headMap(Cut<C> toKey, boolean inclusive) {
733      return subMap(Range.upTo(toKey, BoundType.forBoolean(inclusive)));
734    }
735
736    @Override
737    public NavigableMap<Cut<C>, Range<C>> tailMap(Cut<C> fromKey, boolean inclusive) {
738      return subMap(Range.downTo(fromKey, BoundType.forBoolean(inclusive)));
739    }
740
741    @Override
742    public Comparator<? super Cut<C>> comparator() {
743      return Ordering.<Cut<C>>natural();
744    }
745
746    @Override
747    public boolean containsKey(@CheckForNull Object key) {
748      return get(key) != null;
749    }
750
751    @Override
752    @CheckForNull
753    public Range<C> get(@CheckForNull Object key) {
754      if (key instanceof Cut) {
755        try {
756          @SuppressWarnings("unchecked") // we catch CCE's
757          Cut<C> cut = (Cut<C>) key;
758          if (!lowerBoundWindow.contains(cut)
759              || cut.compareTo(restriction.lowerBound) < 0
760              || cut.compareTo(restriction.upperBound) >= 0) {
761            return null;
762          } else if (cut.equals(restriction.lowerBound)) {
763            // it might be present, truncated on the left
764            Range<C> candidate = Maps.valueOrNull(rangesByLowerBound.floorEntry(cut));
765            if (candidate != null && candidate.upperBound.compareTo(restriction.lowerBound) > 0) {
766              return candidate.intersection(restriction);
767            }
768          } else {
769            Range<C> result = rangesByLowerBound.get(cut);
770            if (result != null) {
771              return result.intersection(restriction);
772            }
773          }
774        } catch (ClassCastException e) {
775          return null;
776        }
777      }
778      return null;
779    }
780
781    @Override
782    Iterator<Entry<Cut<C>, Range<C>>> entryIterator() {
783      if (restriction.isEmpty()) {
784        return Iterators.emptyIterator();
785      }
786      Iterator<Range<C>> completeRangeItr;
787      if (lowerBoundWindow.upperBound.isLessThan(restriction.lowerBound)) {
788        return Iterators.emptyIterator();
789      } else if (lowerBoundWindow.lowerBound.isLessThan(restriction.lowerBound)) {
790        // starts at the first range with upper bound strictly greater than restriction.lowerBound
791        completeRangeItr =
792            rangesByUpperBound.tailMap(restriction.lowerBound, false).values().iterator();
793      } else {
794        // starts at the first range with lower bound above lowerBoundWindow.lowerBound
795        completeRangeItr =
796            rangesByLowerBound
797                .tailMap(
798                    lowerBoundWindow.lowerBound.endpoint(),
799                    lowerBoundWindow.lowerBoundType() == BoundType.CLOSED)
800                .values()
801                .iterator();
802      }
803      Cut<Cut<C>> upperBoundOnLowerBounds =
804          Ordering.<Cut<Cut<C>>>natural()
805              .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
806      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
807        @Override
808        @CheckForNull
809        protected Entry<Cut<C>, Range<C>> computeNext() {
810          if (!completeRangeItr.hasNext()) {
811            return endOfData();
812          }
813          Range<C> nextRange = completeRangeItr.next();
814          if (upperBoundOnLowerBounds.isLessThan(nextRange.lowerBound)) {
815            return endOfData();
816          } else {
817            nextRange = nextRange.intersection(restriction);
818            return Maps.immutableEntry(nextRange.lowerBound, nextRange);
819          }
820        }
821      };
822    }
823
824    @Override
825    Iterator<Entry<Cut<C>, Range<C>>> descendingEntryIterator() {
826      if (restriction.isEmpty()) {
827        return Iterators.emptyIterator();
828      }
829      Cut<Cut<C>> upperBoundOnLowerBounds =
830          Ordering.<Cut<Cut<C>>>natural()
831              .min(lowerBoundWindow.upperBound, Cut.belowValue(restriction.upperBound));
832      Iterator<Range<C>> completeRangeItr =
833          rangesByLowerBound
834              .headMap(
835                  upperBoundOnLowerBounds.endpoint(),
836                  upperBoundOnLowerBounds.typeAsUpperBound() == BoundType.CLOSED)
837              .descendingMap()
838              .values()
839              .iterator();
840      return new AbstractIterator<Entry<Cut<C>, Range<C>>>() {
841        @Override
842        @CheckForNull
843        protected Entry<Cut<C>, Range<C>> computeNext() {
844          if (!completeRangeItr.hasNext()) {
845            return endOfData();
846          }
847          Range<C> nextRange = completeRangeItr.next();
848          if (restriction.lowerBound.compareTo(nextRange.upperBound) >= 0) {
849            return endOfData();
850          }
851          nextRange = nextRange.intersection(restriction);
852          if (lowerBoundWindow.contains(nextRange.lowerBound)) {
853            return Maps.immutableEntry(nextRange.lowerBound, nextRange);
854          } else {
855            return endOfData();
856          }
857        }
858      };
859    }
860
861    @Override
862    public int size() {
863      return Iterators.size(entryIterator());
864    }
865  }
866
867  @Override
868  public RangeSet<C> subRangeSet(Range<C> view) {
869    return view.equals(Range.<C>all()) ? this : new SubRangeSet(view);
870  }
871
872  private final class SubRangeSet extends TreeRangeSet<C> {
873    private final Range<C> restriction;
874
875    SubRangeSet(Range<C> restriction) {
876      super(
877          new SubRangeSetRangesByLowerBound<C>(
878              Range.<Cut<C>>all(), restriction, TreeRangeSet.this.rangesByLowerBound));
879      this.restriction = restriction;
880    }
881
882    @Override
883    public boolean encloses(Range<C> range) {
884      if (!restriction.isEmpty() && restriction.encloses(range)) {
885        Range<C> enclosing = TreeRangeSet.this.rangeEnclosing(range);
886        return enclosing != null && !enclosing.intersection(restriction).isEmpty();
887      }
888      return false;
889    }
890
891    @Override
892    @CheckForNull
893    public Range<C> rangeContaining(C value) {
894      if (!restriction.contains(value)) {
895        return null;
896      }
897      Range<C> result = TreeRangeSet.this.rangeContaining(value);
898      return (result == null) ? null : result.intersection(restriction);
899    }
900
901    @Override
902    public void add(Range<C> rangeToAdd) {
903      checkArgument(
904          restriction.encloses(rangeToAdd),
905          "Cannot add range %s to subRangeSet(%s)",
906          rangeToAdd,
907          restriction);
908      TreeRangeSet.this.add(rangeToAdd);
909    }
910
911    @Override
912    public void remove(Range<C> rangeToRemove) {
913      if (rangeToRemove.isConnected(restriction)) {
914        TreeRangeSet.this.remove(rangeToRemove.intersection(restriction));
915      }
916    }
917
918    @Override
919    public boolean contains(C value) {
920      return restriction.contains(value) && TreeRangeSet.this.contains(value);
921    }
922
923    @Override
924    public void clear() {
925      TreeRangeSet.this.remove(restriction);
926    }
927
928    @Override
929    public RangeSet<C> subRangeSet(Range<C> view) {
930      if (view.encloses(restriction)) {
931        return this;
932      } else if (view.isConnected(restriction)) {
933        return new SubRangeSet(restriction.intersection(view));
934      } else {
935        return ImmutableRangeSet.of();
936      }
937    }
938  }
939}