11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2011 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in compliance with the License. You may obtain a copy of the License at
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software distributed under the License
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * or implied. See the License for the specific language governing permissions and limitations under
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the License.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkArgument;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.base.Preconditions.checkNotNull;
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static com.google.common.collect.BoundType.CLOSED;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * An implementation of {@link ContiguousSet} that contains one or more elements.
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Gregory Kick
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true)
350888a09821a98ac0680fad765217302858e70fa4Paul Duffin@SuppressWarnings("unchecked") // allow ungenerified Comparable types
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class RegularContiguousSet<C extends Comparable> extends ContiguousSet<C> {
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final Range<C> range;
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  RegularContiguousSet(Range<C> range, DiscreteDomain<C> domain) {
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    super(domain);
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.range = range;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
447dd252788645e940eada959bdde927426e2531c9Paul Duffin  private ContiguousSet<C> intersectionInCurrentDomain(Range<C> other) {
450888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return (range.isConnected(other))
460888a09821a98ac0680fad765217302858e70fa4Paul Duffin        ? ContiguousSet.create(range.intersection(other), domain)
477dd252788645e940eada959bdde927426e2531c9Paul Duffin        : new EmptyContiguousSet<C>(domain);
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
500888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override ContiguousSet<C> headSetImpl(C toElement, boolean inclusive) {
517dd252788645e940eada959bdde927426e2531c9Paul Duffin    return intersectionInCurrentDomain(Range.upTo(toElement, BoundType.forBoolean(inclusive)));
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
540888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override ContiguousSet<C> subSetImpl(C fromElement, boolean fromInclusive, C toElement,
550888a09821a98ac0680fad765217302858e70fa4Paul Duffin      boolean toInclusive) {
567dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (fromElement.compareTo(toElement) == 0 && !fromInclusive && !toInclusive) {
577dd252788645e940eada959bdde927426e2531c9Paul Duffin      // Range would reject our attempt to create (x, x).
587dd252788645e940eada959bdde927426e2531c9Paul Duffin      return new EmptyContiguousSet<C>(domain);
597dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
600888a09821a98ac0680fad765217302858e70fa4Paul Duffin    return intersectionInCurrentDomain(Range.range(
610888a09821a98ac0680fad765217302858e70fa4Paul Duffin        fromElement, BoundType.forBoolean(fromInclusive),
620888a09821a98ac0680fad765217302858e70fa4Paul Duffin        toElement, BoundType.forBoolean(toInclusive)));
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
650888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override ContiguousSet<C> tailSetImpl(C fromElement, boolean inclusive) {
667dd252788645e940eada959bdde927426e2531c9Paul Duffin    return intersectionInCurrentDomain(Range.downTo(fromElement, BoundType.forBoolean(inclusive)));
677dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
687dd252788645e940eada959bdde927426e2531c9Paul Duffin
697dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("not used by GWT emulation")
700888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override int indexOf(Object target) {
717dd252788645e940eada959bdde927426e2531c9Paul Duffin    return contains(target) ? (int) domain.distance(first(), (C) target) : -1;
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
740888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public UnmodifiableIterator<C> iterator() {
757dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new AbstractSequentialIterator<C>(first()) {
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      final C last = last();
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      protected C computeNext(C previous) {
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return equalsOrThrow(previous, last) ? null : domain.next(previous);
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
857dd252788645e940eada959bdde927426e2531c9Paul Duffin  @GwtIncompatible("NavigableSet")
860888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public UnmodifiableIterator<C> descendingIterator() {
877dd252788645e940eada959bdde927426e2531c9Paul Duffin    return new AbstractSequentialIterator<C>(last()) {
887dd252788645e940eada959bdde927426e2531c9Paul Duffin      final C first = first();
897dd252788645e940eada959bdde927426e2531c9Paul Duffin
907dd252788645e940eada959bdde927426e2531c9Paul Duffin      @Override
917dd252788645e940eada959bdde927426e2531c9Paul Duffin      protected C computeNext(C previous) {
927dd252788645e940eada959bdde927426e2531c9Paul Duffin        return equalsOrThrow(previous, first) ? null : domain.previous(previous);
937dd252788645e940eada959bdde927426e2531c9Paul Duffin      }
947dd252788645e940eada959bdde927426e2531c9Paul Duffin    };
957dd252788645e940eada959bdde927426e2531c9Paul Duffin  }
967dd252788645e940eada959bdde927426e2531c9Paul Duffin
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static boolean equalsOrThrow(Comparable<?> left, @Nullable Comparable<?> right) {
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return right != null && Range.compareOrThrow(left, right) == 0;
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1010888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override boolean isPartialView() {
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1050888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public C first() {
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return range.lowerBound.leastValueAbove(domain);
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1090888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public C last() {
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return range.upperBound.greatestValueBelow(domain);
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1130888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public int size() {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    long distance = domain.distance(first(), last());
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (distance >= Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) distance + 1;
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1180888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean contains(@Nullable Object object) {
1197dd252788645e940eada959bdde927426e2531c9Paul Duffin    if (object == null) {
1207dd252788645e940eada959bdde927426e2531c9Paul Duffin      return false;
1217dd252788645e940eada959bdde927426e2531c9Paul Duffin    }
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return range.contains((C) object);
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (ClassCastException e) {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1290888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean containsAll(Collection<?> targets) {
1307dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Collections2.containsAllImpl(this, targets);
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1330888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean isEmpty() {
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1370888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public ContiguousSet<C> intersection(ContiguousSet<C> other) {
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(other);
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkArgument(this.domain.equals(other.domain));
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (other.isEmpty()) {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return other;
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      C lowerEndpoint = Ordering.natural().max(this.first(), other.first());
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      C upperEndpoint = Ordering.natural().min(this.last(), other.last());
1450888a09821a98ac0680fad765217302858e70fa4Paul Duffin      return (lowerEndpoint.compareTo(upperEndpoint) < 0)
1460888a09821a98ac0680fad765217302858e70fa4Paul Duffin          ? ContiguousSet.create(Range.closed(lowerEndpoint, upperEndpoint), domain)
1470888a09821a98ac0680fad765217302858e70fa4Paul Duffin          : new EmptyContiguousSet<C>(domain);
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1510888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public Range<C> range() {
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return range(CLOSED, CLOSED);
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1550888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public Range<C> range(BoundType lowerBoundType, BoundType upperBoundType) {
1567dd252788645e940eada959bdde927426e2531c9Paul Duffin    return Range.create(range.lowerBound.withLowerBoundType(lowerBoundType, domain),
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        range.upperBound.withUpperBoundType(upperBoundType, domain));
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1600888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public boolean equals(@Nullable Object object) {
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (object == this) {
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
1637dd252788645e940eada959bdde927426e2531c9Paul Duffin    } else if (object instanceof RegularContiguousSet) {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      RegularContiguousSet<?> that = (RegularContiguousSet<?>) object;
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (this.domain.equals(that.domain)) {
1660888a09821a98ac0680fad765217302858e70fa4Paul Duffin        return this.first().equals(that.first())
1670888a09821a98ac0680fad765217302858e70fa4Paul Duffin            && this.last().equals(that.last());
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return super.equals(object);
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // copied to make sure not to use the GWT-emulated version
1740888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override public int hashCode() {
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Sets.hashCodeImpl(this);
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("serialization")
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class SerializedForm<C extends Comparable> implements Serializable {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Range<C> range;
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final DiscreteDomain<C> domain;
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private SerializedForm(Range<C> range, DiscreteDomain<C> domain) {
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.range = range;
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.domain = domain;
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private Object readResolve() {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new RegularContiguousSet<C>(range, domain);
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("serialization")
1940888a09821a98ac0680fad765217302858e70fa4Paul Duffin  @Override Object writeReplace() {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new SerializedForm<C>(range, domain);
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final long serialVersionUID = 0;
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
200