• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.base;
18 
19 import com.google.common.annotations.GwtCompatible;
20 import com.google.common.annotations.VisibleForTesting;
21 
22 import java.util.Collection;
23 import java.util.NoSuchElementException;
24 
25 /**
26  * Simple static methods to be called at the start of your own methods to verify
27  * correct arguments and state. This allows constructs such as
28  * <pre>
29  *     if (count <= 0) {
30  *       throw new IllegalArgumentException("must be positive: " + count);
31  *     }</pre>
32  *
33  * to be replaced with the more compact
34  * <pre>
35  *     checkArgument(count > 0, "must be positive: %s", count);</pre>
36  *
37  * Note that the sense of the expression is inverted; with {@code Preconditions}
38  * you declare what you expect to be <i>true</i>, just as you do with an
39  * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html">
40  * {@code assert}</a> or a JUnit {@code assertTrue} call.
41  *
42  * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a
43  * placeholder in these messages, not the full range of {@link
44  * String#format(String, Object[])} specifiers.
45  *
46  * <p>Take care not to confuse precondition checking with other similar types
47  * of checks! Precondition exceptions -- including those provided here, but also
48  * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link
49  * UnsupportedOperationException} and others -- are used to signal that the
50  * <i>calling method</i> has made an error. This tells the caller that it should
51  * not have invoked the method when it did, with the arguments it did, or
52  * perhaps ever. Postcondition or other invariant failures should not throw
53  * these types of exceptions.
54  *
55  * @author Kevin Bourrillion
56  * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
57  */
58 @GwtCompatible
59 public final class Preconditions {
Preconditions()60   private Preconditions() {}
61 
62   /**
63    * Ensures the truth of an expression involving one or more parameters to the
64    * calling method.
65    *
66    * @param expression a boolean expression
67    * @throws IllegalArgumentException if {@code expression} is false
68    */
checkArgument(boolean expression)69   public static void checkArgument(boolean expression) {
70     if (!expression) {
71       throw new IllegalArgumentException();
72     }
73   }
74 
75   /**
76    * Ensures the truth of an expression involving one or more parameters to the
77    * calling method.
78    *
79    * @param expression a boolean expression
80    * @param errorMessage the exception message to use if the check fails; will
81    *     be converted to a string using {@link String#valueOf(Object)}
82    * @throws IllegalArgumentException if {@code expression} is false
83    */
checkArgument(boolean expression, Object errorMessage)84   public static void checkArgument(boolean expression, Object errorMessage) {
85     if (!expression) {
86       throw new IllegalArgumentException(String.valueOf(errorMessage));
87     }
88   }
89 
90   /**
91    * Ensures the truth of an expression involving one or more parameters to the
92    * calling method.
93    *
94    * @param expression a boolean expression
95    * @param errorMessageTemplate a template for the exception message should the
96    *     check fail. The message is formed by replacing each {@code %s}
97    *     placeholder in the template with an argument. These are matched by
98    *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
99    *     Unmatched arguments will be appended to the formatted message in square
100    *     braces. Unmatched placeholders will be left as-is.
101    * @param errorMessageArgs the arguments to be substituted into the message
102    *     template. Arguments are converted to strings using
103    *     {@link String#valueOf(Object)}.
104    * @throws IllegalArgumentException if {@code expression} is false
105    * @throws NullPointerException if the check fails and either {@code
106    *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
107    *     this happen)
108    */
checkArgument(boolean expression, String errorMessageTemplate, Object... errorMessageArgs)109   public static void checkArgument(boolean expression,
110       String errorMessageTemplate, Object... errorMessageArgs) {
111     if (!expression) {
112       throw new IllegalArgumentException(
113           format(errorMessageTemplate, errorMessageArgs));
114     }
115   }
116 
117   /**
118    * Ensures the truth of an expression involving the state of the calling
119    * instance, but not involving any parameters to the calling method.
120    *
121    * @param expression a boolean expression
122    * @throws IllegalStateException if {@code expression} is false
123    */
checkState(boolean expression)124   public static void checkState(boolean expression) {
125     if (!expression) {
126       throw new IllegalStateException();
127     }
128   }
129 
130   /**
131    * Ensures the truth of an expression involving the state of the calling
132    * instance, but not involving any parameters to the calling method.
133    *
134    * @param expression a boolean expression
135    * @param errorMessage the exception message to use if the check fails; will
136    *     be converted to a string using {@link String#valueOf(Object)}
137    * @throws IllegalStateException if {@code expression} is false
138    */
checkState(boolean expression, Object errorMessage)139   public static void checkState(boolean expression, Object errorMessage) {
140     if (!expression) {
141       throw new IllegalStateException(String.valueOf(errorMessage));
142     }
143   }
144 
145   /**
146    * Ensures the truth of an expression involving the state of the calling
147    * instance, but not involving any parameters to the calling method.
148    *
149    * @param expression a boolean expression
150    * @param errorMessageTemplate a template for the exception message should the
151    *     check fail. The message is formed by replacing each {@code %s}
152    *     placeholder in the template with an argument. These are matched by
153    *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
154    *     Unmatched arguments will be appended to the formatted message in square
155    *     braces. Unmatched placeholders will be left as-is.
156    * @param errorMessageArgs the arguments to be substituted into the message
157    *     template. Arguments are converted to strings using
158    *     {@link String#valueOf(Object)}.
159    * @throws IllegalStateException if {@code expression} is false
160    * @throws NullPointerException if the check fails and either {@code
161    *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
162    *     this happen)
163    */
checkState(boolean expression, String errorMessageTemplate, Object... errorMessageArgs)164   public static void checkState(boolean expression,
165       String errorMessageTemplate, Object... errorMessageArgs) {
166     if (!expression) {
167       throw new IllegalStateException(
168           format(errorMessageTemplate, errorMessageArgs));
169     }
170   }
171 
172   /**
173    * Ensures that an object reference passed as a parameter to the calling
174    * method is not null.
175    *
176    * @param reference an object reference
177    * @return the non-null reference that was validated
178    * @throws NullPointerException if {@code reference} is null
179    */
checkNotNull(T reference)180   public static <T> T checkNotNull(T reference) {
181     if (reference == null) {
182       throw new NullPointerException();
183     }
184     return reference;
185   }
186 
187   /**
188    * Ensures that an object reference passed as a parameter to the calling
189    * method is not null.
190    *
191    * @param reference an object reference
192    * @param errorMessage the exception message to use if the check fails; will
193    *     be converted to a string using {@link String#valueOf(Object)}
194    * @return the non-null reference that was validated
195    * @throws NullPointerException if {@code reference} is null
196    */
checkNotNull(T reference, Object errorMessage)197   public static <T> T checkNotNull(T reference, Object errorMessage) {
198     if (reference == null) {
199       throw new NullPointerException(String.valueOf(errorMessage));
200     }
201     return reference;
202   }
203 
204   /**
205    * Ensures that an object reference passed as a parameter to the calling
206    * method is not null.
207    *
208    * @param reference an object reference
209    * @param errorMessageTemplate a template for the exception message should the
210    *     check fail. The message is formed by replacing each {@code %s}
211    *     placeholder in the template with an argument. These are matched by
212    *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
213    *     Unmatched arguments will be appended to the formatted message in square
214    *     braces. Unmatched placeholders will be left as-is.
215    * @param errorMessageArgs the arguments to be substituted into the message
216    *     template. Arguments are converted to strings using
217    *     {@link String#valueOf(Object)}.
218    * @return the non-null reference that was validated
219    * @throws NullPointerException if {@code reference} is null
220    */
checkNotNull(T reference, String errorMessageTemplate, Object... errorMessageArgs)221   public static <T> T checkNotNull(T reference, String errorMessageTemplate,
222       Object... errorMessageArgs) {
223     if (reference == null) {
224       // If either of these parameters is null, the right thing happens anyway
225       throw new NullPointerException(
226           format(errorMessageTemplate, errorMessageArgs));
227     }
228     return reference;
229   }
230 
231   /*
232    * All recent hotspots (as of 2009) *really* like to have the natural code
233    *
234    * if (guardExpression) {
235    *    throw new BadException(messageExpression);
236    * }
237    *
238    * refactored so that messageExpression is moved to a separate
239    * String-returning method.
240    *
241    * if (guardExpression) {
242    *    throw new BadException(badMsg(...));
243    * }
244    *
245    * The alternative natural refactorings into void or Exception-returning
246    * methods are much slower.  This is a big deal - we're talking factors of
247    * 2-8 in microbenchmarks, not just 10-20%.  (This is a hotspot optimizer
248    * bug, which should be fixed, but that's a separate, big project).
249    *
250    * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
251    * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
252    *
253    * But the methods in this class want to throw different exceptions,
254    * depending on the args, so it appears that this pattern is not directly
255    * applicable.  But we can use the ridiculous, devious trick of throwing an
256    * exception in the middle of the construction of another exception.
257    * Hotspot is fine with that.
258    */
259 
260   /**
261    * Ensures that {@code index} specifies a valid <i>element</i> in an array,
262    * list or string of size {@code size}. An element index may range from zero,
263    * inclusive, to {@code size}, exclusive.
264    *
265    * @param index a user-supplied index identifying an element of an array, list
266    *     or string
267    * @param size the size of that array, list or string
268    * @return the value of {@code index}
269    * @throws IndexOutOfBoundsException if {@code index} is negative or is not
270    *     less than {@code size}
271    * @throws IllegalArgumentException if {@code size} is negative
272    */
checkElementIndex(int index, int size)273   public static int checkElementIndex(int index, int size) {
274     return checkElementIndex(index, size, "index");
275   }
276 
277   /**
278    * Ensures that {@code index} specifies a valid <i>element</i> in an array,
279    * list or string of size {@code size}. An element index may range from zero,
280    * inclusive, to {@code size}, exclusive.
281    *
282    * @param index a user-supplied index identifying an element of an array, list
283    *     or string
284    * @param size the size of that array, list or string
285    * @param desc the text to use to describe this index in an error message
286    * @return the value of {@code index}
287    * @throws IndexOutOfBoundsException if {@code index} is negative or is not
288    *     less than {@code size}
289    * @throws IllegalArgumentException if {@code size} is negative
290    */
checkElementIndex(int index, int size, String desc)291   public static int checkElementIndex(int index, int size, String desc) {
292     // Carefully optimized for execution by hotspot (explanatory comment above)
293     if (index < 0 || index >= size) {
294       throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
295     }
296     return index;
297   }
298 
badElementIndex(int index, int size, String desc)299   private static String badElementIndex(int index, int size, String desc) {
300     if (index < 0) {
301       return format("%s (%s) must not be negative", desc, index);
302     } else if (size < 0) {
303       throw new IllegalArgumentException("negative size: " + size);
304     } else { // index >= size
305       return format("%s (%s) must be less than size (%s)", desc, index, size);
306     }
307   }
308 
309   /**
310    * Ensures that {@code index} specifies a valid <i>position</i> in an array,
311    * list or string of size {@code size}. A position index may range from zero
312    * to {@code size}, inclusive.
313    *
314    * @param index a user-supplied index identifying a position in an array, list
315    *     or string
316    * @param size the size of that array, list or string
317    * @return the value of {@code index}
318    * @throws IndexOutOfBoundsException if {@code index} is negative or is
319    *     greater than {@code size}
320    * @throws IllegalArgumentException if {@code size} is negative
321    */
checkPositionIndex(int index, int size)322   public static int checkPositionIndex(int index, int size) {
323     return checkPositionIndex(index, size, "index");
324   }
325 
326   /**
327    * Ensures that {@code index} specifies a valid <i>position</i> in an array,
328    * list or string of size {@code size}. A position index may range from zero
329    * to {@code size}, inclusive.
330    *
331    * @param index a user-supplied index identifying a position in an array, list
332    *     or string
333    * @param size the size of that array, list or string
334    * @param desc the text to use to describe this index in an error message
335    * @return the value of {@code index}
336    * @throws IndexOutOfBoundsException if {@code index} is negative or is
337    *     greater than {@code size}
338    * @throws IllegalArgumentException if {@code size} is negative
339    */
checkPositionIndex(int index, int size, String desc)340   public static int checkPositionIndex(int index, int size, String desc) {
341     // Carefully optimized for execution by hotspot (explanatory comment above)
342     if (index < 0 || index > size) {
343       throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
344     }
345     return index;
346   }
347 
badPositionIndex(int index, int size, String desc)348   private static String badPositionIndex(int index, int size, String desc) {
349     if (index < 0) {
350       return format("%s (%s) must not be negative", desc, index);
351     } else if (size < 0) {
352       throw new IllegalArgumentException("negative size: " + size);
353     } else { // index > size
354       return format("%s (%s) must not be greater than size (%s)",
355                     desc, index, size);
356     }
357   }
358 
359   /**
360    * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
361    * in an array, list or string of size {@code size}, and are in order. A
362    * position index may range from zero to {@code size}, inclusive.
363    *
364    * @param start a user-supplied index identifying a starting position in an
365    *     array, list or string
366    * @param end a user-supplied index identifying a ending position in an array,
367    *     list or string
368    * @param size the size of that array, list or string
369    * @throws IndexOutOfBoundsException if either index is negative or is
370    *     greater than {@code size}, or if {@code end} is less than {@code start}
371    * @throws IllegalArgumentException if {@code size} is negative
372    */
checkPositionIndexes(int start, int end, int size)373   public static void checkPositionIndexes(int start, int end, int size) {
374     // Carefully optimized for execution by hotspot (explanatory comment above)
375     if (start < 0 || end < start || end > size) {
376       throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
377     }
378   }
379 
badPositionIndexes(int start, int end, int size)380   private static String badPositionIndexes(int start, int end, int size) {
381     if (start < 0 || start > size) {
382       return badPositionIndex(start, size, "start index");
383     }
384     if (end < 0 || end > size) {
385       return badPositionIndex(end, size, "end index");
386     }
387     // end < start
388     return format("end index (%s) must not be less than start index (%s)",
389                   end, start);
390   }
391 
392   /**
393    * Substitutes each {@code %s} in {@code template} with an argument. These
394    * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
395    * If there are more arguments than placeholders, the unmatched arguments will
396    * be appended to the end of the formatted message in square braces.
397    *
398    * @param template a non-null string containing 0 or more {@code %s}
399    *     placeholders.
400    * @param args the arguments to be substituted into the message
401    *     template. Arguments are converted to strings using
402    *     {@link String#valueOf(Object)}. Arguments can be null.
403    */
format(String template, Object... args)404   @VisibleForTesting static String format(String template, Object... args) {
405     // start substituting the arguments into the '%s' placeholders
406     StringBuilder builder = new StringBuilder(
407         template.length() + 16 * args.length);
408     int templateStart = 0;
409     int i = 0;
410     while (i < args.length) {
411       int placeholderStart = template.indexOf("%s", templateStart);
412       if (placeholderStart == -1) {
413         break;
414       }
415       builder.append(template.substring(templateStart, placeholderStart));
416       builder.append(args[i++]);
417       templateStart = placeholderStart + 2;
418     }
419     builder.append(template.substring(templateStart));
420 
421     // if we run out of placeholders, append the extra args in square braces
422     if (i < args.length) {
423       builder.append(" [");
424       builder.append(args[i++]);
425       while (i < args.length) {
426         builder.append(", ");
427         builder.append(args[i++]);
428       }
429       builder.append("]");
430     }
431 
432     return builder.toString();
433   }
434 }
435