summaryrefslogtreecommitdiffstats
path: root/guava/src/com/google/common/collect/GeneralRange.java
diff options
context:
space:
mode:
authorYohann Roussel <yroussel@google.com>2014-03-19 16:25:37 +0100
committerYohann Roussel <yroussel@google.com>2014-03-20 15:13:33 +0100
commit4eceb95409e844fdc33c9c706e1dc307bfd40303 (patch)
treeee9f4f3fc79f757c79081c336bce4f1782c6ccd8 /guava/src/com/google/common/collect/GeneralRange.java
parent3d2402901b1a6462e2cf47a6fd09711f327961c3 (diff)
downloadtoolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.zip
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.gz
toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.bz2
Initial Jack import.
Change-Id: I953cf0a520195a7187d791b2885848ad0d5a9b43
Diffstat (limited to 'guava/src/com/google/common/collect/GeneralRange.java')
-rw-r--r--guava/src/com/google/common/collect/GeneralRange.java304
1 files changed, 304 insertions, 0 deletions
diff --git a/guava/src/com/google/common/collect/GeneralRange.java b/guava/src/com/google/common/collect/GeneralRange.java
new file mode 100644
index 0000000..c083d83
--- /dev/null
+++ b/guava/src/com/google/common/collect/GeneralRange.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2011 The Guava Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.common.collect;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.BoundType.CLOSED;
+import static com.google.common.collect.BoundType.OPEN;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+import javax.annotation.Nullable;
+
+/**
+ * A generalized interval on any ordering, for internal use. Supports {@code null}. Unlike
+ * {@link Range}, this allows the use of an arbitrary comparator. This is designed for use in the
+ * implementation of subcollections of sorted collection types.
+ *
+ * <p>Whenever possible, use {@code Range} instead, which is better supported.
+ *
+ * @author Louis Wasserman
+ */
+@GwtCompatible(serializable = true)
+final class GeneralRange<T> implements Serializable {
+ /**
+ * Converts a Range to a GeneralRange.
+ */
+ static <T extends Comparable> GeneralRange<T> from(Range<T> range) {
+ @Nullable
+ T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null;
+ BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN;
+
+ @Nullable
+ T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null;
+ BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN;
+ return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint,
+ lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType);
+ }
+
+ /**
+ * Returns the whole range relative to the specified comparator.
+ */
+ static <T> GeneralRange<T> all(Comparator<? super T> comparator) {
+ return new GeneralRange<T>(comparator, false, null, OPEN, false, null, OPEN);
+ }
+
+ /**
+ * Returns everything above the endpoint relative to the specified comparator, with the specified
+ * endpoint behavior.
+ */
+ static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint,
+ BoundType boundType) {
+ return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN);
+ }
+
+ /**
+ * Returns everything below the endpoint relative to the specified comparator, with the specified
+ * endpoint behavior.
+ */
+ static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint,
+ BoundType boundType) {
+ return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType);
+ }
+
+ /**
+ * Returns everything between the endpoints relative to the specified comparator, with the
+ * specified endpoint behavior.
+ */
+ static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower,
+ BoundType lowerType, @Nullable T upper, BoundType upperType) {
+ return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType);
+ }
+
+ private final Comparator<? super T> comparator;
+ private final boolean hasLowerBound;
+ @Nullable
+ private final T lowerEndpoint;
+ private final BoundType lowerBoundType;
+ private final boolean hasUpperBound;
+ @Nullable
+ private final T upperEndpoint;
+ private final BoundType upperBoundType;
+
+ private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound,
+ @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound,
+ @Nullable T upperEndpoint, BoundType upperBoundType) {
+ this.comparator = checkNotNull(comparator);
+ this.hasLowerBound = hasLowerBound;
+ this.hasUpperBound = hasUpperBound;
+ this.lowerEndpoint = lowerEndpoint;
+ this.lowerBoundType = checkNotNull(lowerBoundType);
+ this.upperEndpoint = upperEndpoint;
+ this.upperBoundType = checkNotNull(upperBoundType);
+
+ if (hasLowerBound) {
+ comparator.compare(lowerEndpoint, lowerEndpoint);
+ }
+ if (hasUpperBound) {
+ comparator.compare(upperEndpoint, upperEndpoint);
+ }
+ if (hasLowerBound && hasUpperBound) {
+ int cmp = comparator.compare(lowerEndpoint, upperEndpoint);
+ // be consistent with Range
+ checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint,
+ upperEndpoint);
+ if (cmp == 0) {
+ checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN);
+ }
+ }
+ }
+
+ Comparator<? super T> comparator() {
+ return comparator;
+ }
+
+ boolean hasLowerBound() {
+ return hasLowerBound;
+ }
+
+ boolean hasUpperBound() {
+ return hasUpperBound;
+ }
+
+ boolean isEmpty() {
+ return (hasUpperBound() && tooLow(getUpperEndpoint()))
+ || (hasLowerBound() && tooHigh(getLowerEndpoint()));
+ }
+
+ boolean tooLow(@Nullable T t) {
+ if (!hasLowerBound()) {
+ return false;
+ }
+ T lbound = getLowerEndpoint();
+ int cmp = comparator.compare(t, lbound);
+ return cmp < 0 | (cmp == 0 & getLowerBoundType() == OPEN);
+ }
+
+ boolean tooHigh(@Nullable T t) {
+ if (!hasUpperBound()) {
+ return false;
+ }
+ T ubound = getUpperEndpoint();
+ int cmp = comparator.compare(t, ubound);
+ return cmp > 0 | (cmp == 0 & getUpperBoundType() == OPEN);
+ }
+
+ boolean contains(@Nullable T t) {
+ return !tooLow(t) && !tooHigh(t);
+ }
+
+ /**
+ * Returns the intersection of the two ranges, or an empty range if their intersection is empty.
+ */
+ GeneralRange<T> intersect(GeneralRange<T> other) {
+ checkNotNull(other);
+ checkArgument(comparator.equals(other.comparator));
+
+ boolean hasLowBound = this.hasLowerBound;
+ @Nullable
+ T lowEnd = getLowerEndpoint();
+ BoundType lowType = getLowerBoundType();
+ if (!hasLowerBound()) {
+ hasLowBound = other.hasLowerBound;
+ lowEnd = other.getLowerEndpoint();
+ lowType = other.getLowerBoundType();
+ } else if (other.hasLowerBound()) {
+ int cmp = comparator.compare(getLowerEndpoint(), other.getLowerEndpoint());
+ if (cmp < 0 || (cmp == 0 && other.getLowerBoundType() == OPEN)) {
+ lowEnd = other.getLowerEndpoint();
+ lowType = other.getLowerBoundType();
+ }
+ }
+
+ boolean hasUpBound = this.hasUpperBound;
+ @Nullable
+ T upEnd = getUpperEndpoint();
+ BoundType upType = getUpperBoundType();
+ if (!hasUpperBound()) {
+ hasUpBound = other.hasUpperBound;
+ upEnd = other.getUpperEndpoint();
+ upType = other.getUpperBoundType();
+ } else if (other.hasUpperBound()) {
+ int cmp = comparator.compare(getUpperEndpoint(), other.getUpperEndpoint());
+ if (cmp > 0 || (cmp == 0 && other.getUpperBoundType() == OPEN)) {
+ upEnd = other.getUpperEndpoint();
+ upType = other.getUpperBoundType();
+ }
+ }
+
+ if (hasLowBound && hasUpBound) {
+ int cmp = comparator.compare(lowEnd, upEnd);
+ if (cmp > 0 || (cmp == 0 && lowType == OPEN && upType == OPEN)) {
+ // force allowed empty range
+ lowEnd = upEnd;
+ lowType = OPEN;
+ upType = CLOSED;
+ }
+ }
+
+ return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj instanceof GeneralRange) {
+ GeneralRange<?> r = (GeneralRange<?>) obj;
+ return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound
+ && hasUpperBound == r.hasUpperBound && getLowerBoundType().equals(r.getLowerBoundType())
+ && getUpperBoundType().equals(r.getUpperBoundType())
+ && Objects.equal(getLowerEndpoint(), r.getLowerEndpoint())
+ && Objects.equal(getUpperEndpoint(), r.getUpperEndpoint());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(),
+ getUpperBoundType());
+ }
+
+ private transient GeneralRange<T> reverse;
+
+ /**
+ * Returns the same range relative to the reversed comparator.
+ */
+ GeneralRange<T> reverse() {
+ GeneralRange<T> result = reverse;
+ if (result == null) {
+ result = new GeneralRange<T>(
+ Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(),
+ getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType());
+ result.reverse = this;
+ return this.reverse = result;
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(comparator).append(":");
+ switch (getLowerBoundType()) {
+ case CLOSED:
+ builder.append('[');
+ break;
+ case OPEN:
+ builder.append('(');
+ break;
+ }
+ if (hasLowerBound()) {
+ builder.append(getLowerEndpoint());
+ } else {
+ builder.append("-\u221e");
+ }
+ builder.append(',');
+ if (hasUpperBound()) {
+ builder.append(getUpperEndpoint());
+ } else {
+ builder.append("\u221e");
+ }
+ switch (getUpperBoundType()) {
+ case CLOSED:
+ builder.append(']');
+ break;
+ case OPEN:
+ builder.append(')');
+ break;
+ }
+ return builder.toString();
+ }
+
+ T getLowerEndpoint() {
+ return lowerEndpoint;
+ }
+
+ BoundType getLowerBoundType() {
+ return lowerBoundType;
+ }
+
+ T getUpperEndpoint() {
+ return upperEndpoint;
+ }
+
+ BoundType getUpperBoundType() {
+ return upperBoundType;
+ }
+}