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
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * express or implied. See the License for the specific language governing permissions and
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under 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 Bringertimport static com.google.common.collect.BoundType.OPEN;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.io.Serializable;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Comparator;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport javax.annotation.Nullable;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Objects;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * A generalized interval on any ordering, for internal use. Supports {@code null}. Unlike
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link Range}, this allows the use of an arbitrary comparator. This is designed for use in the
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * implementation of subcollections of sorted collection types.
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Whenever possible, use {@code Range} instead, which is better supported.
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Louis Wasserman
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(serializable = true)
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertfinal class GeneralRange<T> implements Serializable {
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Converts a Range to a GeneralRange.
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <T extends Comparable> GeneralRange<T> from(Range<T> range) {
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN;
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN;
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint,
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType);
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the whole range relative to the specified comparator.
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <T> GeneralRange<T> all(Comparator<? super T> comparator) {
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(comparator, false, null, OPEN, false, null, OPEN);
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns everything above the endpoint relative to the specified comparator, with the specified
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * endpoint behavior.
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint,
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BoundType boundType) {
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN);
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns everything below the endpoint relative to the specified comparator, with the specified
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * endpoint behavior.
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint,
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BoundType boundType) {
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType);
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns everything between the endpoints relative to the specified comparator, with the
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * specified endpoint behavior.
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower,
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      BoundType lowerType, @Nullable T upper, BoundType upperType) {
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType);
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final Comparator<? super T> comparator;
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final boolean hasLowerBound;
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final T lowerEndpoint;
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final BoundType lowerBoundType;
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final boolean hasUpperBound;
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Nullable
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final T upperEndpoint;
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final BoundType upperBoundType;
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound,
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound,
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Nullable T upperEndpoint, BoundType upperBoundType) {
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.comparator = checkNotNull(comparator);
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.hasLowerBound = hasLowerBound;
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.hasUpperBound = hasUpperBound;
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.lowerEndpoint = lowerEndpoint;
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.lowerBoundType = checkNotNull(lowerBoundType);
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.upperEndpoint = upperEndpoint;
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this.upperBoundType = checkNotNull(upperBoundType);
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasLowerBound) {
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      comparator.compare(lowerEndpoint, lowerEndpoint);
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasUpperBound) {
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      comparator.compare(upperEndpoint, upperEndpoint);
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasLowerBound && hasUpperBound) {
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int cmp = comparator.compare(lowerEndpoint, upperEndpoint);
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      // be consistent with Range
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint,
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          upperEndpoint);
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (cmp == 0) {
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN);
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Comparator<? super T> comparator() {
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return comparator;
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean hasLowerBound() {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return hasLowerBound;
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean hasUpperBound() {
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return hasUpperBound;
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean isEmpty() {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return (hasUpperBound() && tooLow(upperEndpoint))
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        || (hasLowerBound() && tooHigh(lowerEndpoint));
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean tooLow(@Nullable T t) {
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!hasLowerBound()) {
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T lbound = lowerEndpoint;
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int cmp = comparator.compare(t, lbound);
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return cmp < 0 | (cmp == 0 & lowerBoundType == OPEN);
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean tooHigh(@Nullable T t) {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!hasUpperBound()) {
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T ubound = upperEndpoint;
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    int cmp = comparator.compare(t, ubound);
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return cmp > 0 | (cmp == 0 & upperBoundType == OPEN);
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  boolean contains(@Nullable T t) {
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return !tooLow(t) && !tooHigh(t);
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the intersection of the two ranges, or an empty range if their intersection is empty.
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  GeneralRange<T> intersect(GeneralRange<T> other) {
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkNotNull(other);
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    checkArgument(comparator.equals(other.comparator));
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean hasLowBound = this.hasLowerBound;
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T lowEnd = lowerEndpoint;
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    BoundType lowType = lowerBoundType;
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!hasLowerBound()) {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      hasLowBound = other.hasLowerBound;
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lowEnd = other.lowerEndpoint;
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      lowType = other.lowerBoundType;
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else if (other.hasLowerBound()) {
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int cmp = comparator.compare(lowerEndpoint, other.lowerEndpoint);
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (cmp < 0 || (cmp == 0 && other.lowerBoundType == OPEN)) {
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lowEnd = other.lowerEndpoint;
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lowType = other.lowerBoundType;
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean hasUpBound = this.hasUpperBound;
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Nullable
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    T upEnd = upperEndpoint;
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    BoundType upType = upperBoundType;
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!hasUpperBound()) {
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      hasUpBound = other.hasUpperBound;
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      upEnd = other.upperEndpoint;
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      upType = other.upperBoundType;
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else if (other.hasUpperBound()) {
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int cmp = comparator.compare(upperEndpoint, other.upperEndpoint);
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (cmp > 0 || (cmp == 0 && other.upperBoundType == OPEN)) {
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        upEnd = other.upperEndpoint;
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        upType = other.upperBoundType;
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasLowBound && hasUpBound) {
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      int cmp = comparator.compare(lowEnd, upEnd);
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (cmp > 0 || (cmp == 0 && lowType == OPEN && upType == OPEN)) {
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        // force allowed empty range
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lowEnd = upEnd;
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        lowType = OPEN;
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        upType = CLOSED;
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType);
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public boolean equals(@Nullable Object obj) {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (obj instanceof GeneralRange) {
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      GeneralRange<?> r = (GeneralRange<?>) obj;
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          && hasUpperBound == r.hasUpperBound && lowerBoundType.equals(r.lowerBoundType)
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          && upperBoundType.equals(r.upperBoundType)
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          && Objects.equal(lowerEndpoint, r.lowerEndpoint)
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          && Objects.equal(upperEndpoint, r.upperEndpoint);
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return false;
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public int hashCode() {
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return Objects.hashCode(comparator, lowerEndpoint, lowerBoundType, upperEndpoint,
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        upperBoundType);
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private transient GeneralRange<T> reverse;
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns the same range relative to the reversed comparator.
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public GeneralRange<T> reverse() {
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    GeneralRange<T> result = reverse;
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (result == null) {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      result =
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          new GeneralRange<T>(Ordering.from(comparator).reverse(), hasUpperBound, upperEndpoint,
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              upperBoundType, hasLowerBound, lowerEndpoint, lowerBoundType);
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      result.reverse = this;
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return this.reverse = result;
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return result;
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @Override
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public String toString() {
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    StringBuilder builder = new StringBuilder();
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    builder.append(comparator).append(":");
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    switch (lowerBoundType) {
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case CLOSED:
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.append('[');
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case OPEN:
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.append('(');
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasLowerBound()) {
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.append(lowerEndpoint);
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.append("-\u221e");
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    builder.append(',');
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (hasUpperBound()) {
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.append(upperEndpoint);
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } else {
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      builder.append("\u221e");
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    switch (upperBoundType) {
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case CLOSED:
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.append(']');
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      case OPEN:
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        builder.append(')');
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        break;
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return builder.toString();
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
289