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