11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2009 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.checkNotNull;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.primitives.Booleans;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.NoSuchElementException;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Implementation detail for the internal structure of {@link Range} instances. Represents
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a unique way of "cutting" a "number line" (actually of instances of type {@code C}, not
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * necessarily "numbers") into two sections; this can be done below a certain value, above
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * a certain value, below all values or above all values. With this object defined in this
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * way, an interval can always be represented by a pair of {@code Cut} instances.
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Kevin Bourrillion
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertabstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializable {
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  final C endpoint;
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Cut(@Nullable C endpoint) {
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.endpoint = endpoint;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract boolean isLessThan(C value);
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract BoundType typeAsLowerBound();
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract BoundType typeAsUpperBound();
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain);
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain);
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract void describeAsLowerBound(StringBuilder sb);
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract void describeAsUpperBound(StringBuilder sb);
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract C leastValueAbove(DiscreteDomain<C> domain);
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  abstract C greatestValueBelow(DiscreteDomain<C> domain);
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The canonical form is a BelowValue cut whenever possible, otherwise ABOVE_ALL, or
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * (only in the case of types that are unbounded below) BELOW_ALL.
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Cut<C> canonical(DiscreteDomain<C> domain) {
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return this;
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  // note: overriden by {BELOW,ABOVE}_ALL
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int compareTo(Cut<C> that) {
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (that == belowAll()) {
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return 1;
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (that == aboveAll()) {
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return -1;
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int result = Range.compareOrThrow(endpoint, that.endpoint);
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (result != 0) {
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return result;
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // same value. below comes before above
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Booleans.compare(
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        this instanceof AboveValue, that instanceof AboveValue);
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  C endpoint() {
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return endpoint;
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked") // catching CCE
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override public boolean equals(Object obj) {
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (obj instanceof Cut) {
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // It might not really be a Cut<C>, but we'll catch a CCE if it's not
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Cut<C> that = (Cut<C>) obj;
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        int compareResult = compareTo(that);
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return compareResult == 0;
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (ClassCastException ignored) {
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The implementation neither produces nor consumes any non-null instance of type C, so
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * casting the type parameter is safe.
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked")
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <C extends Comparable> Cut<C> belowAll() {
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (Cut<C>) BelowAll.INSTANCE;
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final long serialVersionUID = 0;
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class BelowAll extends Cut<Comparable<?>> {
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final BelowAll INSTANCE = new BelowAll();
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private BelowAll() {
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(null);
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> endpoint() {
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException("range unbounded on this side");
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override boolean isLessThan(Comparable<?> value) {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return true;
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsLowerBound() {
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException();
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsUpperBound() {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError("this statement should be unreachable");
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException();
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError("this statement should be unreachable");
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsLowerBound(StringBuilder sb) {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append("(-\u221e");
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsUpperBound(StringBuilder sb) {
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> leastValueAbove(
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return domain.minValue();
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> greatestValueBelow(
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<Comparable<?>> canonical(
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      try {
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Cut.<Comparable<?>>belowValue(domain.minValue());
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      } catch (NoSuchElementException e) {
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return this;
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int compareTo(Cut<Comparable<?>> o) {
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (o == this) ? 0 : -1;
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private Object readResolve() {
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return INSTANCE;
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /*
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * The implementation neither produces nor consumes any non-null instance of
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * type C, so casting the type parameter is safe.
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @SuppressWarnings("unchecked")
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <C extends Comparable> Cut<C> aboveAll() {
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (Cut<C>) AboveAll.INSTANCE;
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class AboveAll extends Cut<Comparable<?>> {
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final AboveAll INSTANCE = new AboveAll();
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private AboveAll() {
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(null);
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> endpoint() {
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException("range unbounded on this side");
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override boolean isLessThan(Comparable<?> value) {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsLowerBound() {
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError("this statement should be unreachable");
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsUpperBound() {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException();
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError("this statement should be unreachable");
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new IllegalStateException();
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsLowerBound(StringBuilder sb) {
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsUpperBound(StringBuilder sb) {
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append("+\u221e)");
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> leastValueAbove(
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw new AssertionError();
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Comparable<?> greatestValueBelow(
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        DiscreteDomain<Comparable<?>> domain) {
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return domain.maxValue();
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int compareTo(Cut<Comparable<?>> o) {
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (o == this) ? 0 : 1;
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private Object readResolve() {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return INSTANCE;
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <C extends Comparable> Cut<C> belowValue(C endpoint) {
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new BelowValue<C>(endpoint);
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class BelowValue<C extends Comparable> extends Cut<C> {
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    BelowValue(C endpoint) {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(checkNotNull(endpoint));
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override boolean isLessThan(C value) {
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Range.compareOrThrow(endpoint, value) <= 0;
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsLowerBound() {
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return BoundType.CLOSED;
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsUpperBound() {
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return BoundType.OPEN;
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      switch (boundType) {
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case CLOSED:
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return this;
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case OPEN:
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable C previous = domain.previous(endpoint);
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (previous == null) ? Cut.<C>belowAll() : new AboveValue<C>(previous);
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        default:
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      switch (boundType) {
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case CLOSED:
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable C previous = domain.previous(endpoint);
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (previous == null) ? Cut.<C>aboveAll() : new AboveValue<C>(previous);
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case OPEN:
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return this;
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        default:
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsLowerBound(StringBuilder sb) {
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append('[').append(endpoint);
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsUpperBound(StringBuilder sb) {
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append(endpoint).append(')');
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override C leastValueAbove(DiscreteDomain<C> domain) {
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return endpoint;
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override C greatestValueBelow(DiscreteDomain<C> domain) {
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return domain.previous(endpoint);
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int hashCode() {
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return endpoint.hashCode();
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <C extends Comparable> Cut<C> aboveValue(C endpoint) {
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new AboveValue<C>(endpoint);
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class AboveValue<C extends Comparable> extends Cut<C> {
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    AboveValue(C endpoint) {
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      super(checkNotNull(endpoint));
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override boolean isLessThan(C value) {
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return Range.compareOrThrow(endpoint, value) < 0;
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsLowerBound() {
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return BoundType.OPEN;
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override BoundType typeAsUpperBound() {
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return BoundType.CLOSED;
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      switch (boundType) {
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case OPEN:
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return this;
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case CLOSED:
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable C next = domain.next(endpoint);
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (next == null) ? Cut.<C>belowAll() : belowValue(next);
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        default:
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      switch (boundType) {
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case OPEN:
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Nullable C next = domain.next(endpoint);
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return (next == null) ? Cut.<C>aboveAll() : belowValue(next);
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        case CLOSED:
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          return this;
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        default:
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          throw new AssertionError();
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsLowerBound(StringBuilder sb) {
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append('(').append(endpoint);
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override void describeAsUpperBound(StringBuilder sb) {
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      sb.append(endpoint).append(']');
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override C leastValueAbove(DiscreteDomain<C> domain) {
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return domain.next(endpoint);
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override C greatestValueBelow(DiscreteDomain<C> domain) {
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return endpoint;
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override Cut<C> canonical(DiscreteDomain<C> domain) {
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      C next = leastValueAbove(domain);
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override public int hashCode() {
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return ~endpoint.hashCode();
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
348