• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the License
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing permissions and limitations under
12  * the License.
13  */
14 
15 package com.google.common.collect;
16 
17 import static com.google.common.base.Preconditions.checkNotNull;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.primitives.Booleans;
21 
22 import java.io.Serializable;
23 import java.util.NoSuchElementException;
24 
25 import javax.annotation.Nullable;
26 
27 /**
28  * Implementation detail for the internal structure of {@link Range} instances. Represents
29  * a unique way of "cutting" a "number line" (actually of instances of type {@code C}, not
30  * necessarily "numbers") into two sections; this can be done below a certain value, above
31  * a certain value, below all values or above all values. With this object defined in this
32  * way, an interval can always be represented by a pair of {@code Cut} instances.
33  *
34  * @author Kevin Bourrillion
35  */
36 @GwtCompatible
37 abstract class Cut<C extends Comparable> implements Comparable<Cut<C>>, Serializable {
38   final C endpoint;
39 
Cut(@ullable C endpoint)40   Cut(@Nullable C endpoint) {
41     this.endpoint = endpoint;
42   }
43 
isLessThan(C value)44   abstract boolean isLessThan(C value);
45 
typeAsLowerBound()46   abstract BoundType typeAsLowerBound();
typeAsUpperBound()47   abstract BoundType typeAsUpperBound();
48 
withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain)49   abstract Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain);
withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain)50   abstract Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain);
51 
describeAsLowerBound(StringBuilder sb)52   abstract void describeAsLowerBound(StringBuilder sb);
describeAsUpperBound(StringBuilder sb)53   abstract void describeAsUpperBound(StringBuilder sb);
54 
leastValueAbove(DiscreteDomain<C> domain)55   abstract C leastValueAbove(DiscreteDomain<C> domain);
greatestValueBelow(DiscreteDomain<C> domain)56   abstract C greatestValueBelow(DiscreteDomain<C> domain);
57 
58   /*
59    * The canonical form is a BelowValue cut whenever possible, otherwise ABOVE_ALL, or
60    * (only in the case of types that are unbounded below) BELOW_ALL.
61    */
canonical(DiscreteDomain<C> domain)62   Cut<C> canonical(DiscreteDomain<C> domain) {
63     return this;
64   }
65 
66   // note: overriden by {BELOW,ABOVE}_ALL
67   @Override
compareTo(Cut<C> that)68   public int compareTo(Cut<C> that) {
69     if (that == belowAll()) {
70       return 1;
71     }
72     if (that == aboveAll()) {
73       return -1;
74     }
75     int result = Range.compareOrThrow(endpoint, that.endpoint);
76     if (result != 0) {
77       return result;
78     }
79     // same value. below comes before above
80     return Booleans.compare(
81         this instanceof AboveValue, that instanceof AboveValue);
82   }
83 
endpoint()84   C endpoint() {
85     return endpoint;
86   }
87 
88   @SuppressWarnings("unchecked") // catching CCE
equals(Object obj)89   @Override public boolean equals(Object obj) {
90     if (obj instanceof Cut) {
91       // It might not really be a Cut<C>, but we'll catch a CCE if it's not
92       Cut<C> that = (Cut<C>) obj;
93       try {
94         int compareResult = compareTo(that);
95         return compareResult == 0;
96       } catch (ClassCastException ignored) {
97       }
98     }
99     return false;
100   }
101 
102   /*
103    * The implementation neither produces nor consumes any non-null instance of type C, so
104    * casting the type parameter is safe.
105    */
106   @SuppressWarnings("unchecked")
belowAll()107   static <C extends Comparable> Cut<C> belowAll() {
108     return (Cut<C>) BelowAll.INSTANCE;
109   }
110 
111   private static final long serialVersionUID = 0;
112 
113   private static final class BelowAll extends Cut<Comparable<?>> {
114     private static final BelowAll INSTANCE = new BelowAll();
115 
BelowAll()116     private BelowAll() {
117       super(null);
118     }
endpoint()119     @Override Comparable<?> endpoint() {
120       throw new IllegalStateException("range unbounded on this side");
121     }
isLessThan(Comparable<?> value)122     @Override boolean isLessThan(Comparable<?> value) {
123       return true;
124     }
typeAsLowerBound()125     @Override BoundType typeAsLowerBound() {
126       throw new IllegalStateException();
127     }
typeAsUpperBound()128     @Override BoundType typeAsUpperBound() {
129       throw new AssertionError("this statement should be unreachable");
130     }
withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain)131     @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
132         DiscreteDomain<Comparable<?>> domain) {
133       throw new IllegalStateException();
134     }
withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain)135     @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
136         DiscreteDomain<Comparable<?>> domain) {
137       throw new AssertionError("this statement should be unreachable");
138     }
describeAsLowerBound(StringBuilder sb)139     @Override void describeAsLowerBound(StringBuilder sb) {
140       sb.append("(-\u221e");
141     }
describeAsUpperBound(StringBuilder sb)142     @Override void describeAsUpperBound(StringBuilder sb) {
143       throw new AssertionError();
144     }
leastValueAbove( DiscreteDomain<Comparable<?>> domain)145     @Override Comparable<?> leastValueAbove(
146         DiscreteDomain<Comparable<?>> domain) {
147       return domain.minValue();
148     }
greatestValueBelow( DiscreteDomain<Comparable<?>> domain)149     @Override Comparable<?> greatestValueBelow(
150         DiscreteDomain<Comparable<?>> domain) {
151       throw new AssertionError();
152     }
canonical( DiscreteDomain<Comparable<?>> domain)153     @Override Cut<Comparable<?>> canonical(
154         DiscreteDomain<Comparable<?>> domain) {
155       try {
156         return Cut.<Comparable<?>>belowValue(domain.minValue());
157       } catch (NoSuchElementException e) {
158         return this;
159       }
160     }
compareTo(Cut<Comparable<?>> o)161     @Override public int compareTo(Cut<Comparable<?>> o) {
162       return (o == this) ? 0 : -1;
163     }
readResolve()164     private Object readResolve() {
165       return INSTANCE;
166     }
167     private static final long serialVersionUID = 0;
168   }
169 
170   /*
171    * The implementation neither produces nor consumes any non-null instance of
172    * type C, so casting the type parameter is safe.
173    */
174   @SuppressWarnings("unchecked")
aboveAll()175   static <C extends Comparable> Cut<C> aboveAll() {
176     return (Cut<C>) AboveAll.INSTANCE;
177   }
178 
179   private static final class AboveAll extends Cut<Comparable<?>> {
180     private static final AboveAll INSTANCE = new AboveAll();
181 
AboveAll()182     private AboveAll() {
183       super(null);
184     }
endpoint()185     @Override Comparable<?> endpoint() {
186       throw new IllegalStateException("range unbounded on this side");
187     }
isLessThan(Comparable<?> value)188     @Override boolean isLessThan(Comparable<?> value) {
189       return false;
190     }
typeAsLowerBound()191     @Override BoundType typeAsLowerBound() {
192       throw new AssertionError("this statement should be unreachable");
193     }
typeAsUpperBound()194     @Override BoundType typeAsUpperBound() {
195       throw new IllegalStateException();
196     }
withLowerBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain)197     @Override Cut<Comparable<?>> withLowerBoundType(BoundType boundType,
198         DiscreteDomain<Comparable<?>> domain) {
199       throw new AssertionError("this statement should be unreachable");
200     }
withUpperBoundType(BoundType boundType, DiscreteDomain<Comparable<?>> domain)201     @Override Cut<Comparable<?>> withUpperBoundType(BoundType boundType,
202         DiscreteDomain<Comparable<?>> domain) {
203       throw new IllegalStateException();
204     }
describeAsLowerBound(StringBuilder sb)205     @Override void describeAsLowerBound(StringBuilder sb) {
206       throw new AssertionError();
207     }
describeAsUpperBound(StringBuilder sb)208     @Override void describeAsUpperBound(StringBuilder sb) {
209       sb.append("+\u221e)");
210     }
leastValueAbove( DiscreteDomain<Comparable<?>> domain)211     @Override Comparable<?> leastValueAbove(
212         DiscreteDomain<Comparable<?>> domain) {
213       throw new AssertionError();
214     }
greatestValueBelow( DiscreteDomain<Comparable<?>> domain)215     @Override Comparable<?> greatestValueBelow(
216         DiscreteDomain<Comparable<?>> domain) {
217       return domain.maxValue();
218     }
compareTo(Cut<Comparable<?>> o)219     @Override public int compareTo(Cut<Comparable<?>> o) {
220       return (o == this) ? 0 : 1;
221     }
readResolve()222     private Object readResolve() {
223       return INSTANCE;
224     }
225     private static final long serialVersionUID = 0;
226   }
227 
belowValue(C endpoint)228   static <C extends Comparable> Cut<C> belowValue(C endpoint) {
229     return new BelowValue<C>(endpoint);
230   }
231 
232   private static final class BelowValue<C extends Comparable> extends Cut<C> {
BelowValue(C endpoint)233     BelowValue(C endpoint) {
234       super(checkNotNull(endpoint));
235     }
236 
isLessThan(C value)237     @Override boolean isLessThan(C value) {
238       return Range.compareOrThrow(endpoint, value) <= 0;
239     }
typeAsLowerBound()240     @Override BoundType typeAsLowerBound() {
241       return BoundType.CLOSED;
242     }
typeAsUpperBound()243     @Override BoundType typeAsUpperBound() {
244       return BoundType.OPEN;
245     }
withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain)246     @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
247       switch (boundType) {
248         case CLOSED:
249           return this;
250         case OPEN:
251           @Nullable C previous = domain.previous(endpoint);
252           return (previous == null) ? Cut.<C>belowAll() : new AboveValue<C>(previous);
253         default:
254           throw new AssertionError();
255       }
256     }
withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain)257     @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
258       switch (boundType) {
259         case CLOSED:
260           @Nullable C previous = domain.previous(endpoint);
261           return (previous == null) ? Cut.<C>aboveAll() : new AboveValue<C>(previous);
262         case OPEN:
263           return this;
264         default:
265           throw new AssertionError();
266       }
267     }
describeAsLowerBound(StringBuilder sb)268     @Override void describeAsLowerBound(StringBuilder sb) {
269       sb.append('[').append(endpoint);
270     }
describeAsUpperBound(StringBuilder sb)271     @Override void describeAsUpperBound(StringBuilder sb) {
272       sb.append(endpoint).append(')');
273     }
leastValueAbove(DiscreteDomain<C> domain)274     @Override C leastValueAbove(DiscreteDomain<C> domain) {
275       return endpoint;
276     }
greatestValueBelow(DiscreteDomain<C> domain)277     @Override C greatestValueBelow(DiscreteDomain<C> domain) {
278       return domain.previous(endpoint);
279     }
hashCode()280     @Override public int hashCode() {
281       return endpoint.hashCode();
282     }
283     private static final long serialVersionUID = 0;
284   }
285 
aboveValue(C endpoint)286   static <C extends Comparable> Cut<C> aboveValue(C endpoint) {
287     return new AboveValue<C>(endpoint);
288   }
289 
290   private static final class AboveValue<C extends Comparable> extends Cut<C> {
AboveValue(C endpoint)291     AboveValue(C endpoint) {
292       super(checkNotNull(endpoint));
293     }
294 
isLessThan(C value)295     @Override boolean isLessThan(C value) {
296       return Range.compareOrThrow(endpoint, value) < 0;
297     }
typeAsLowerBound()298     @Override BoundType typeAsLowerBound() {
299       return BoundType.OPEN;
300     }
typeAsUpperBound()301     @Override BoundType typeAsUpperBound() {
302       return BoundType.CLOSED;
303     }
withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain)304     @Override Cut<C> withLowerBoundType(BoundType boundType, DiscreteDomain<C> domain) {
305       switch (boundType) {
306         case OPEN:
307           return this;
308         case CLOSED:
309           @Nullable C next = domain.next(endpoint);
310           return (next == null) ? Cut.<C>belowAll() : belowValue(next);
311         default:
312           throw new AssertionError();
313       }
314     }
withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain)315     @Override Cut<C> withUpperBoundType(BoundType boundType, DiscreteDomain<C> domain) {
316       switch (boundType) {
317         case OPEN:
318           @Nullable C next = domain.next(endpoint);
319           return (next == null) ? Cut.<C>aboveAll() : belowValue(next);
320         case CLOSED:
321           return this;
322         default:
323           throw new AssertionError();
324       }
325     }
describeAsLowerBound(StringBuilder sb)326     @Override void describeAsLowerBound(StringBuilder sb) {
327       sb.append('(').append(endpoint);
328     }
describeAsUpperBound(StringBuilder sb)329     @Override void describeAsUpperBound(StringBuilder sb) {
330       sb.append(endpoint).append(']');
331     }
leastValueAbove(DiscreteDomain<C> domain)332     @Override C leastValueAbove(DiscreteDomain<C> domain) {
333       return domain.next(endpoint);
334     }
greatestValueBelow(DiscreteDomain<C> domain)335     @Override C greatestValueBelow(DiscreteDomain<C> domain) {
336       return endpoint;
337     }
canonical(DiscreteDomain<C> domain)338     @Override Cut<C> canonical(DiscreteDomain<C> domain) {
339       C next = leastValueAbove(domain);
340       return (next != null) ? belowValue(next) : Cut.<C>aboveAll();
341     }
hashCode()342     @Override public int hashCode() {
343       return ~endpoint.hashCode();
344     }
345     private static final long serialVersionUID = 0;
346   }
347 }
348