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     * <p>See the Guava User Guide article on <a href=
066     * "http://code.google.com/p/guava-libraries/wiki/RangesExplained">
067     * {@code Range}</a>.
068     *
069     * @author Kevin Bourrillion
070     * @author Gregory Kick
071     * @since 10.0
072     */
073    @GwtCompatible
074    @Beta
075    public final class Ranges {
076      private Ranges() {}
077    
078      static <C extends Comparable<?>> Range<C> create(
079          Cut<C> lowerBound, Cut<C> upperBound) {
080        return new Range<C>(lowerBound, upperBound);
081      }
082    
083      /**
084       * Returns a range that contains all values strictly greater than {@code
085       * lower} and strictly less than {@code upper}.
086       *
087       * @throws IllegalArgumentException if {@code lower} is greater than <i>or
088       *     equal to</i> {@code upper}
089       */
090      public static <C extends Comparable<?>> Range<C> open(C lower, C upper) {
091        return create(Cut.aboveValue(lower), Cut.belowValue(upper));
092      }
093    
094      /**
095       * Returns a range that contains all values greater than or equal to
096       * {@code lower} and less than or equal to {@code upper}.
097       *
098       * @throws IllegalArgumentException if {@code lower} is greater than {@code
099       *     upper}
100       */
101      public static <C extends Comparable<?>> Range<C> closed(C lower, C upper) {
102        return create(Cut.belowValue(lower), Cut.aboveValue(upper));
103      }
104    
105      /**
106       * Returns a range that contains all values greater than or equal to
107       * {@code lower} and strictly less than {@code upper}.
108       *
109       * @throws IllegalArgumentException if {@code lower} is greater than {@code
110       *     upper}
111       */
112      public static <C extends Comparable<?>> Range<C> closedOpen(
113          C lower, C upper) {
114        return create(Cut.belowValue(lower), Cut.belowValue(upper));
115      }
116    
117      /**
118       * Returns a range that contains all values strictly greater than {@code
119       * lower} and less than or equal to {@code upper}.
120       *
121       * @throws IllegalArgumentException if {@code lower} is greater than {@code
122       *     upper}
123       */
124      public static <C extends Comparable<?>> Range<C> openClosed(
125          C lower, C upper) {
126        return create(Cut.aboveValue(lower), Cut.aboveValue(upper));
127      }
128    
129      /**
130       * Returns a range that contains any value from {@code lower} to {@code
131       * upper}, where each endpoint may be either inclusive (closed) or exclusive
132       * (open).
133       *
134       * @throws IllegalArgumentException if {@code lower} is greater than {@code
135       *     upper}
136       */
137      public static <C extends Comparable<?>> Range<C> range(
138          C lower, BoundType lowerType, C upper, BoundType upperType) {
139        checkNotNull(lowerType);
140        checkNotNull(upperType);
141    
142        Cut<C> lowerBound = (lowerType == BoundType.OPEN)
143            ? Cut.aboveValue(lower)
144            : Cut.belowValue(lower);
145        Cut<C> upperBound = (upperType == BoundType.OPEN)
146            ? Cut.belowValue(upper)
147            : Cut.aboveValue(upper);
148        return create(lowerBound, upperBound);
149      }
150    
151      /**
152       * Returns a range that contains all values strictly less than {@code
153       * endpoint}.
154       */
155      public static <C extends Comparable<?>> Range<C> lessThan(C endpoint) {
156        return create(Cut.<C>belowAll(), Cut.belowValue(endpoint));
157      }
158    
159      /**
160       * Returns a range that contains all values less than or equal to
161       * {@code endpoint}.
162       */
163      public static <C extends Comparable<?>> Range<C> atMost(C endpoint) {
164        return create(Cut.<C>belowAll(), Cut.aboveValue(endpoint));
165      }
166    
167      /**
168       * Returns a range with no lower bound up to the given endpoint, which may be
169       * either inclusive (closed) or exclusive (open).
170       */
171      public static <C extends Comparable<?>> Range<C> upTo(
172          C endpoint, BoundType boundType) {
173        switch (boundType) {
174          case OPEN:
175            return lessThan(endpoint);
176          case CLOSED:
177            return atMost(endpoint);
178          default:
179            throw new AssertionError();
180        }
181      }
182    
183      /**
184       * Returns a range that contains all values strictly greater than {@code
185       * endpoint}.
186       */
187      public static <C extends Comparable<?>> Range<C> greaterThan(C endpoint) {
188        return create(Cut.aboveValue(endpoint), Cut.<C>aboveAll());
189      }
190    
191      /**
192       * Returns a range that contains all values greater than or equal to
193       * {@code endpoint}.
194       */
195      public static <C extends Comparable<?>> Range<C> atLeast(C endpoint) {
196        return create(Cut.belowValue(endpoint), Cut.<C>aboveAll());
197      }
198    
199      /**
200       * Returns a range from the given endpoint, which may be either inclusive
201       * (closed) or exclusive (open), with no upper bound.
202       */
203      public static <C extends Comparable<?>> Range<C> downTo(
204          C endpoint, BoundType boundType) {
205        switch (boundType) {
206          case OPEN:
207            return greaterThan(endpoint);
208          case CLOSED:
209            return atLeast(endpoint);
210          default:
211            throw new AssertionError();
212        }
213      }
214    
215      /** Returns a range that contains every value of type {@code C}. */
216      public static <C extends Comparable<?>> Range<C> all() {
217        return create(Cut.<C>belowAll(), Cut.<C>aboveAll());
218      }
219    
220      /**
221       * Returns a range that {@linkplain Range#contains(Comparable) contains} only
222       * the given value. The returned range is {@linkplain BoundType#CLOSED closed}
223       * on both ends.
224       */
225      public static <C extends Comparable<?>> Range<C> singleton(C value) {
226        return closed(value, value);
227      }
228    
229      /**
230       * Returns the minimal range that
231       * {@linkplain Range#contains(Comparable) contains} all of the given values.
232       * The returned range is {@linkplain BoundType#CLOSED closed} on both ends.
233       *
234       * @throws ClassCastException if the parameters are not <i>mutually
235       *     comparable</i>
236       * @throws NoSuchElementException if {@code values} is empty
237       * @throws NullPointerException if any of {@code values} is null
238       */
239      public static <C extends Comparable<?>> Range<C> encloseAll(
240          Iterable<C> values) {
241        checkNotNull(values);
242        if (values instanceof ContiguousSet) {
243          return ((ContiguousSet<C>) values).range();
244        }
245        Iterator<C> valueIterator = values.iterator();
246        C min = checkNotNull(valueIterator.next());
247        C max = min;
248        while (valueIterator.hasNext()) {
249          C value = checkNotNull(valueIterator.next());
250          min = Ordering.natural().min(min, value);
251          max = Ordering.natural().max(max, value);
252        }
253        return closed(min, max);
254      }
255    }