001    /*
002     * Copyright (C) 2009 The Guava Authors
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package com.google.common.collect;
018    
019    import static com.google.common.base.Preconditions.checkNotNull;
020    
021    import com.google.common.annotations.Beta;
022    import com.google.common.annotations.GwtCompatible;
023    
024    import java.util.Iterator;
025    import java.util.NoSuchElementException;
026    
027    /**
028     * Static methods pertaining to {@link Range} instances.  Each of the
029     * {@link Range nine types of ranges} can be constructed with a corresponding
030     * factory method:
031     *
032     * <dl>
033     * <dt>{@code (a..b)}
034     * <dd>{@link #open}
035     * <dt>{@code [a..b]}
036     * <dd>{@link #closed}
037     * <dt>{@code [a..b)}
038     * <dd>{@link #closedOpen}
039     * <dt>{@code (a..b]}
040     * <dd>{@link #openClosed}
041     * <dt>{@code (a..+∞)}
042     * <dd>{@link #greaterThan}
043     * <dt>{@code [a..+∞)}
044     * <dd>{@link #atLeast}
045     * <dt>{@code (-∞..b)}
046     * <dd>{@link #lessThan}
047     * <dt>{@code (-∞..b]}
048     * <dd>{@link #atMost}
049     * <dt>{@code (-∞..+∞)}
050     * <dd>{@link #all}
051     * </dl>
052     *
053     * <p>Additionally, {@link Range} instances can be constructed by passing the
054     * {@link BoundType bound types} explicitly.
055     *
056     * <dl>
057     * <dt>Bounded on both ends
058     * <dd>{@link #range}
059     * <dt>Unbounded on top ({@code (a..+∞)} or {@code (a..+∞)})
060     * <dd>{@link #downTo}
061     * <dt>Unbounded on bottom ({@code (-∞..b)} or {@code (-∞..b]})
062     * <dd>{@link #upTo}
063     * </dl>
064     *
065     * @author Kevin Bourrillion
066     * @author Gregory Kick
067     * @since 10.0
068     */
069    @GwtCompatible
070    @Beta
071    public final class Ranges {
072      private Ranges() {}
073    
074      static <C extends Comparable<?>> Range<C> create(
075          Cut<C> lowerBound, Cut<C> upperBound) {
076        return new Range<C>(lowerBound, upperBound);
077      }
078    
079      /**
080       * Returns a range that contains all values strictly greater than {@code
081       * lower} and strictly less than {@code upper}.
082       *
083       * @throws IllegalArgumentException if {@code lower} is greater than <i>or
084       *     equal to</i> {@code upper}
085       */
086      public static <C extends Comparable<?>> Range<C> open(C lower, C upper) {
087        return create(Cut.aboveValue(lower), Cut.belowValue(upper));
088      }
089    
090      /**
091       * Returns a range that contains all values greater than or equal to
092       * {@code lower} and less than or equal to {@code upper}.
093       *
094       * @throws IllegalArgumentException if {@code lower} is greater than {@code
095       *     upper}
096       */
097      public static <C extends Comparable<?>> Range<C> closed(C lower, C upper) {
098        return create(Cut.belowValue(lower), Cut.aboveValue(upper));
099      }
100    
101      /**
102       * Returns a range that contains all values greater than or equal to
103       * {@code lower} and strictly less than {@code upper}.
104       *
105       * @throws IllegalArgumentException if {@code lower} is greater than {@code
106       *     upper}
107       */
108      public static <C extends Comparable<?>> Range<C> closedOpen(
109          C lower, C upper) {
110        return create(Cut.belowValue(lower), Cut.belowValue(upper));
111      }
112    
113      /**
114       * Returns a range that contains all values strictly greater than {@code
115       * lower} and less than or equal to {@code upper}.
116       *
117       * @throws IllegalArgumentException if {@code lower} is greater than {@code
118       *     upper}
119       */
120      public static <C extends Comparable<?>> Range<C> openClosed(
121          C lower, C upper) {
122        return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
123      }
124    
125      /**
126       * Returns a range that contains any value from {@code lower} to {@code
127       * upper}, where each endpoint may be either inclusive (closed) or exclusive
128       * (open).
129       *
130       * @throws IllegalArgumentException if {@code lower} is greater than {@code
131       *     upper}
132       */
133      public static <C extends Comparable<?>> Range<C> range(
134          C lower, BoundType lowerType, C upper, BoundType upperType) {
135        checkNotNull(lowerType);
136        checkNotNull(upperType);
137    
138        Cut<C> lowerBound = (lowerType == BoundType.OPEN)
139            ? Cut.aboveValue(lower)
140            : Cut.belowValue(lower);
141        Cut<C> upperBound = (upperType == BoundType.OPEN)
142            ? Cut.belowValue(upper)
143            : Cut.aboveValue(upper);
144        return create(lowerBound, upperBound);
145      }
146    
147      /**
148       * Returns a range that contains all values strictly less than {@code
149       * endpoint}.
150       */
151      public static <C extends Comparable<?>> Range<C> lessThan(C endpoint) {
152        return create(Cut.<C>belowAll(), Cut.belowValue(endpoint));
153      }
154    
155      /**
156       * Returns a range that contains all values less than or equal to
157       * {@code endpoint}.
158       */
159      public static <C extends Comparable<?>> Range<C> atMost(C endpoint) {
160        return create(Cut.<C>belowAll(), Cut.aboveValue(endpoint));
161      }
162    
163      /**
164       * Returns a range with no lower bound up to the given endpoint, which may be
165       * either inclusive (closed) or exclusive (open).
166       */
167      public static <C extends Comparable<?>> Range<C> upTo(
168          C endpoint, BoundType boundType) {
169        switch (boundType) {
170          case OPEN:
171            return lessThan(endpoint);
172          case CLOSED:
173            return atMost(endpoint);
174          default:
175            throw new AssertionError();
176        }
177      }
178    
179      /**
180       * Returns a range that contains all values strictly greater than {@code
181       * endpoint}.
182       */
183      public static <C extends Comparable<?>> Range<C> greaterThan(C endpoint) {
184        return create(Cut.aboveValue(endpoint), Cut.<C>aboveAll());
185      }
186    
187      /**
188       * Returns a range that contains all values greater than or equal to
189       * {@code endpoint}.
190       */
191      public static <C extends Comparable<?>> Range<C> atLeast(C endpoint) {
192        return create(Cut.belowValue(endpoint), Cut.<C>aboveAll());
193      }
194    
195      /**
196       * Returns a range from the given endpoint, which may be either inclusive
197       * (closed) or exclusive (open), with no upper bound.
198       */
199      public static <C extends Comparable<?>> Range<C> downTo(
200          C endpoint, BoundType boundType) {
201        switch (boundType) {
202          case OPEN:
203            return greaterThan(endpoint);
204          case CLOSED:
205            return atLeast(endpoint);
206          default:
207            throw new AssertionError();
208        }
209      }
210    
211      /** Returns a range that contains every value of type {@code C}. */
212      public static <C extends Comparable<?>> Range<C> all() {
213        return create(Cut.<C>belowAll(), Cut.<C>aboveAll());
214      }
215    
216      /**
217       * Returns a range that {@linkplain Range#contains(Comparable) contains} only
218       * the given value. The returned range is {@linkplain BoundType#CLOSED closed}
219       * on both ends.
220       */
221      public static <C extends Comparable<?>> Range<C> singleton(C value) {
222        return closed(value, value);
223      }
224    
225      /**
226       * Returns the minimal range that
227       * {@linkplain Range#contains(Comparable) contains} all of the given values.
228       * The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
229       *
230       * @throws ClassCastException if the parameters are not <i>mutually
231       *     comparable</i>
232       * @throws NoSuchElementException if {@code values} is empty
233       * @throws NullPointerException if any of {@code values} is null
234       */
235      public static <C extends Comparable<?>> Range<C> encloseAll(
236          Iterable<C> values) {
237        checkNotNull(values);
238        if (values instanceof ContiguousSet) {
239          return ((ContiguousSet<C>) values).range();
240        }
241        Iterator<C> valueIterator = values.iterator();
242        C min = checkNotNull(valueIterator.next());
243        C max = min;
244        while (valueIterator.hasNext()) {
245          C value = checkNotNull(valueIterator.next());
246          min = Ordering.natural().min(min, value);
247          max = Ordering.natural().max(max, value);
248        }
249        return closed(min, max);
250      }
251    }