• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
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.android.internal.util;
18 
19 import android.annotation.IntRange;
20 import android.annotation.NonNull;
21 import android.annotation.UnsupportedAppUsage;
22 import android.text.TextUtils;
23 
24 import java.util.Collection;
25 
26 /**
27  * Simple static methods to be called at the start of your own methods to verify
28  * correct arguments and state.
29  */
30 public class Preconditions {
31 
32     @UnsupportedAppUsage
checkArgument(boolean expression)33     public static void checkArgument(boolean expression) {
34         if (!expression) {
35             throw new IllegalArgumentException();
36         }
37     }
38 
39     /**
40      * Ensures that an expression checking an argument is true.
41      *
42      * @param expression the expression to check
43      * @param errorMessage the exception message to use if the check fails; will
44      *     be converted to a string using {@link String#valueOf(Object)}
45      * @throws IllegalArgumentException if {@code expression} is false
46      */
47     @UnsupportedAppUsage
checkArgument(boolean expression, final Object errorMessage)48     public static void checkArgument(boolean expression, final Object errorMessage) {
49         if (!expression) {
50             throw new IllegalArgumentException(String.valueOf(errorMessage));
51         }
52     }
53 
54     /**
55      * Ensures that an expression checking an argument is true.
56      *
57      * @param expression the expression to check
58      * @param messageTemplate a printf-style message template to use if the check fails; will
59      *     be converted to a string using {@link String#format(String, Object...)}
60      * @param messageArgs arguments for {@code messageTemplate}
61      * @throws IllegalArgumentException if {@code expression} is false
62      */
checkArgument(boolean expression, final String messageTemplate, final Object... messageArgs)63     public static void checkArgument(boolean expression,
64             final String messageTemplate,
65             final Object... messageArgs) {
66         if (!expression) {
67             throw new IllegalArgumentException(String.format(messageTemplate, messageArgs));
68         }
69     }
70 
71     /**
72      * Ensures that an string reference passed as a parameter to the calling
73      * method is not empty.
74      *
75      * @param string an string reference
76      * @return the string reference that was validated
77      * @throws IllegalArgumentException if {@code string} is empty
78      */
checkStringNotEmpty(final T string)79     public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string) {
80         if (TextUtils.isEmpty(string)) {
81             throw new IllegalArgumentException();
82         }
83         return string;
84     }
85 
86     /**
87      * Ensures that an string reference passed as a parameter to the calling
88      * method is not empty.
89      *
90      * @param string an string reference
91      * @param errorMessage the exception message to use if the check fails; will
92      *     be converted to a string using {@link String#valueOf(Object)}
93      * @return the string reference that was validated
94      * @throws IllegalArgumentException if {@code string} is empty
95      */
checkStringNotEmpty(final T string, final Object errorMessage)96     public static @NonNull <T extends CharSequence> T checkStringNotEmpty(final T string,
97             final Object errorMessage) {
98         if (TextUtils.isEmpty(string)) {
99             throw new IllegalArgumentException(String.valueOf(errorMessage));
100         }
101         return string;
102     }
103 
104     /**
105      * Ensures that an object reference passed as a parameter to the calling
106      * method is not null.
107      *
108      * @param reference an object reference
109      * @return the non-null reference that was validated
110      * @throws NullPointerException if {@code reference} is null
111      */
112     @UnsupportedAppUsage
checkNotNull(final T reference)113     public static @NonNull <T> T checkNotNull(final T reference) {
114         if (reference == null) {
115             throw new NullPointerException();
116         }
117         return reference;
118     }
119 
120     /**
121      * Ensures that an object reference passed as a parameter to the calling
122      * method is not null.
123      *
124      * @param reference an object reference
125      * @param errorMessage the exception message to use if the check fails; will
126      *     be converted to a string using {@link String#valueOf(Object)}
127      * @return the non-null reference that was validated
128      * @throws NullPointerException if {@code reference} is null
129      */
130     @UnsupportedAppUsage
checkNotNull(final T reference, final Object errorMessage)131     public static @NonNull <T> T checkNotNull(final T reference, final Object errorMessage) {
132         if (reference == null) {
133             throw new NullPointerException(String.valueOf(errorMessage));
134         }
135         return reference;
136     }
137 
138     /**
139      * Ensures that an object reference passed as a parameter to the calling
140      * method is not null.
141      *
142      * @param reference an object reference
143      * @param messageTemplate a printf-style message template to use if the check fails; will
144      *     be converted to a string using {@link String#format(String, Object...)}
145      * @param messageArgs arguments for {@code messageTemplate}
146      * @return the non-null reference that was validated
147      * @throws NullPointerException if {@code reference} is null
148      */
checkNotNull(final T reference, final String messageTemplate, final Object... messageArgs)149     public static @NonNull <T> T checkNotNull(final T reference,
150             final String messageTemplate,
151             final Object... messageArgs) {
152         if (reference == null) {
153             throw new NullPointerException(String.format(messageTemplate, messageArgs));
154         }
155         return reference;
156     }
157 
158     /**
159      * Ensures the truth of an expression involving the state of the calling
160      * instance, but not involving any parameters to the calling method.
161      *
162      * @param expression a boolean expression
163      * @param message exception message
164      * @throws IllegalStateException if {@code expression} is false
165      */
166     @UnsupportedAppUsage
checkState(final boolean expression, String message)167     public static void checkState(final boolean expression, String message) {
168         if (!expression) {
169             throw new IllegalStateException(message);
170         }
171     }
172 
173     /**
174      * Ensures the truth of an expression involving the state of the calling
175      * instance, but not involving any parameters to the calling method.
176      *
177      * @param expression a boolean expression
178      * @throws IllegalStateException if {@code expression} is false
179      */
180     @UnsupportedAppUsage
checkState(final boolean expression)181     public static void checkState(final boolean expression) {
182         checkState(expression, null);
183     }
184 
185     /**
186      * Check the requested flags, throwing if any requested flags are outside
187      * the allowed set.
188      *
189      * @return the validated requested flags.
190      */
checkFlagsArgument(final int requestedFlags, final int allowedFlags)191     public static int checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
192         if ((requestedFlags & allowedFlags) != requestedFlags) {
193             throw new IllegalArgumentException("Requested flags 0x"
194                     + Integer.toHexString(requestedFlags) + ", but only 0x"
195                     + Integer.toHexString(allowedFlags) + " are allowed");
196         }
197 
198         return requestedFlags;
199     }
200 
201     /**
202      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
203      *
204      * @param value a numeric int value
205      * @param errorMessage the exception message to use if the check fails
206      * @return the validated numeric value
207      * @throws IllegalArgumentException if {@code value} was negative
208      */
checkArgumentNonnegative(final int value, final String errorMessage)209     public static @IntRange(from = 0) int checkArgumentNonnegative(final int value,
210             final String errorMessage) {
211         if (value < 0) {
212             throw new IllegalArgumentException(errorMessage);
213         }
214 
215         return value;
216     }
217 
218     /**
219      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
220      *
221      * @param value a numeric int value
222      *
223      * @return the validated numeric value
224      * @throws IllegalArgumentException if {@code value} was negative
225      */
checkArgumentNonnegative(final int value)226     public static @IntRange(from = 0) int checkArgumentNonnegative(final int value) {
227         if (value < 0) {
228             throw new IllegalArgumentException();
229         }
230 
231         return value;
232     }
233 
234     /**
235      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
236      *
237      * @param value a numeric long value
238      * @return the validated numeric value
239      * @throws IllegalArgumentException if {@code value} was negative
240      */
checkArgumentNonnegative(final long value)241     public static long checkArgumentNonnegative(final long value) {
242         if (value < 0) {
243             throw new IllegalArgumentException();
244         }
245 
246         return value;
247     }
248 
249     /**
250      * Ensures that that the argument numeric value is non-negative (greater than or equal to 0).
251      *
252      * @param value a numeric long value
253      * @param errorMessage the exception message to use if the check fails
254      * @return the validated numeric value
255      * @throws IllegalArgumentException if {@code value} was negative
256      */
checkArgumentNonnegative(final long value, final String errorMessage)257     public static long checkArgumentNonnegative(final long value, final String errorMessage) {
258         if (value < 0) {
259             throw new IllegalArgumentException(errorMessage);
260         }
261 
262         return value;
263     }
264 
265     /**
266      * Ensures that that the argument numeric value is positive (greater than 0).
267      *
268      * @param value a numeric int value
269      * @param errorMessage the exception message to use if the check fails
270      * @return the validated numeric value
271      * @throws IllegalArgumentException if {@code value} was not positive
272      */
checkArgumentPositive(final int value, final String errorMessage)273     public static int checkArgumentPositive(final int value, final String errorMessage) {
274         if (value <= 0) {
275             throw new IllegalArgumentException(errorMessage);
276         }
277 
278         return value;
279     }
280 
281     /**
282      * Ensures that the argument floating point value is non-negative (greater than or equal to 0).
283      * @param value a floating point value
284      * @param errorMessage the exteption message to use if the check fails
285      * @return the validated numeric value
286      * @throws IllegalArgumentException if {@code value} was negative
287      */
checkArgumentNonNegative(final float value, final String errorMessage)288     public static float checkArgumentNonNegative(final float value, final String errorMessage) {
289         if (value < 0) {
290             throw new IllegalArgumentException(errorMessage);
291         }
292 
293         return value;
294     }
295 
296     /**
297      * Ensures that the argument floating point value is positive (greater than 0).
298      * @param value a floating point value
299      * @param errorMessage the exteption message to use if the check fails
300      * @return the validated numeric value
301      * @throws IllegalArgumentException if {@code value} was not positive
302      */
checkArgumentPositive(final float value, final String errorMessage)303     public static float checkArgumentPositive(final float value, final String errorMessage) {
304         if (value <= 0) {
305             throw new IllegalArgumentException(errorMessage);
306         }
307 
308         return value;
309     }
310 
311     /**
312      * Ensures that the argument floating point value is a finite number.
313      *
314      * <p>A finite number is defined to be both representable (that is, not NaN) and
315      * not infinite (that is neither positive or negative infinity).</p>
316      *
317      * @param value a floating point value
318      * @param valueName the name of the argument to use if the check fails
319      *
320      * @return the validated floating point value
321      *
322      * @throws IllegalArgumentException if {@code value} was not finite
323      */
checkArgumentFinite(final float value, final String valueName)324     public static float checkArgumentFinite(final float value, final String valueName) {
325         if (Float.isNaN(value)) {
326             throw new IllegalArgumentException(valueName + " must not be NaN");
327         } else if (Float.isInfinite(value)) {
328             throw new IllegalArgumentException(valueName + " must not be infinite");
329         }
330 
331         return value;
332     }
333 
334     /**
335      * Ensures that the argument floating point value is within the inclusive range.
336      *
337      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
338      * will always be out of range.</p>
339      *
340      * @param value a floating point value
341      * @param lower the lower endpoint of the inclusive range
342      * @param upper the upper endpoint of the inclusive range
343      * @param valueName the name of the argument to use if the check fails
344      *
345      * @return the validated floating point value
346      *
347      * @throws IllegalArgumentException if {@code value} was not within the range
348      */
checkArgumentInRange(float value, float lower, float upper, String valueName)349     public static float checkArgumentInRange(float value, float lower, float upper,
350             String valueName) {
351         if (Float.isNaN(value)) {
352             throw new IllegalArgumentException(valueName + " must not be NaN");
353         } else if (value < lower) {
354             throw new IllegalArgumentException(
355                     String.format(
356                             "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
357         } else if (value > upper) {
358             throw new IllegalArgumentException(
359                     String.format(
360                             "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
361         }
362 
363         return value;
364     }
365 
366     /**
367      * Ensures that the argument int value is within the inclusive range.
368      *
369      * @param value a int value
370      * @param lower the lower endpoint of the inclusive range
371      * @param upper the upper endpoint of the inclusive range
372      * @param valueName the name of the argument to use if the check fails
373      *
374      * @return the validated int value
375      *
376      * @throws IllegalArgumentException if {@code value} was not within the range
377      */
378     @UnsupportedAppUsage
checkArgumentInRange(int value, int lower, int upper, String valueName)379     public static int checkArgumentInRange(int value, int lower, int upper,
380             String valueName) {
381         if (value < lower) {
382             throw new IllegalArgumentException(
383                     String.format(
384                             "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
385         } else if (value > upper) {
386             throw new IllegalArgumentException(
387                     String.format(
388                             "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
389         }
390 
391         return value;
392     }
393 
394     /**
395      * Ensures that the argument long value is within the inclusive range.
396      *
397      * @param value a long value
398      * @param lower the lower endpoint of the inclusive range
399      * @param upper the upper endpoint of the inclusive range
400      * @param valueName the name of the argument to use if the check fails
401      *
402      * @return the validated long value
403      *
404      * @throws IllegalArgumentException if {@code value} was not within the range
405      */
checkArgumentInRange(long value, long lower, long upper, String valueName)406     public static long checkArgumentInRange(long value, long lower, long upper,
407             String valueName) {
408         if (value < lower) {
409             throw new IllegalArgumentException(
410                     String.format(
411                             "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
412         } else if (value > upper) {
413             throw new IllegalArgumentException(
414                     String.format(
415                             "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
416         }
417 
418         return value;
419     }
420 
421     /**
422      * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
423      *
424      * @param value an array of boxed objects
425      * @param valueName the name of the argument to use if the check fails
426      *
427      * @return the validated array
428      *
429      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
430      */
checkArrayElementsNotNull(final T[] value, final String valueName)431     public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
432         if (value == null) {
433             throw new NullPointerException(valueName + " must not be null");
434         }
435 
436         for (int i = 0; i < value.length; ++i) {
437             if (value[i] == null) {
438                 throw new NullPointerException(
439                         String.format("%s[%d] must not be null", valueName, i));
440             }
441         }
442 
443         return value;
444     }
445 
446     /**
447      * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
448      * {@code null}.
449      *
450      * @param value a {@link Collection} of boxed objects
451      * @param valueName the name of the argument to use if the check fails
452      *
453      * @return the validated {@link Collection}
454      *
455      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
456      */
checkCollectionElementsNotNull( final C value, final String valueName)457     public static @NonNull <C extends Collection<T>, T> C checkCollectionElementsNotNull(
458             final C value, final String valueName) {
459         if (value == null) {
460             throw new NullPointerException(valueName + " must not be null");
461         }
462 
463         long ctr = 0;
464         for (T elem : value) {
465             if (elem == null) {
466                 throw new NullPointerException(
467                         String.format("%s[%d] must not be null", valueName, ctr));
468             }
469             ++ctr;
470         }
471 
472         return value;
473     }
474 
475     /**
476      * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
477      *
478      * @param value a {@link Collection} of boxed elements.
479      * @param valueName the name of the argument to use if the check fails.
480 
481      * @return the validated {@link Collection}
482      *
483      * @throws NullPointerException if the {@code value} was {@code null}
484      * @throws IllegalArgumentException if the {@code value} was empty
485      */
checkCollectionNotEmpty(final Collection<T> value, final String valueName)486     public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
487             final String valueName) {
488         if (value == null) {
489             throw new NullPointerException(valueName + " must not be null");
490         }
491         if (value.isEmpty()) {
492             throw new IllegalArgumentException(valueName + " is empty");
493         }
494         return value;
495     }
496 
497     /**
498      * Ensures that all elements in the argument floating point array are within the inclusive range
499      *
500      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
501      * will always be out of range.</p>
502      *
503      * @param value a floating point array of values
504      * @param lower the lower endpoint of the inclusive range
505      * @param upper the upper endpoint of the inclusive range
506      * @param valueName the name of the argument to use if the check fails
507      *
508      * @return the validated floating point value
509      *
510      * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
511      * @throws NullPointerException if the {@code value} was {@code null}
512      */
checkArrayElementsInRange(float[] value, float lower, float upper, String valueName)513     public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
514             String valueName) {
515         checkNotNull(value, valueName + " must not be null");
516 
517         for (int i = 0; i < value.length; ++i) {
518             float v = value[i];
519 
520             if (Float.isNaN(v)) {
521                 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
522             } else if (v < lower) {
523                 throw new IllegalArgumentException(
524                         String.format("%s[%d] is out of range of [%f, %f] (too low)",
525                                 valueName, i, lower, upper));
526             } else if (v > upper) {
527                 throw new IllegalArgumentException(
528                         String.format("%s[%d] is out of range of [%f, %f] (too high)",
529                                 valueName, i, lower, upper));
530             }
531         }
532 
533         return value;
534     }
535 
536     /**
537      * Ensures that all elements in the argument integer array are within the inclusive range
538      *
539      * @param value an integer array of values
540      * @param lower the lower endpoint of the inclusive range
541      * @param upper the upper endpoint of the inclusive range
542      * @param valueName the name of the argument to use if the check fails
543      *
544      * @return the validated integer array
545      *
546      * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
547      * @throws NullPointerException if the {@code value} was {@code null}
548      */
checkArrayElementsInRange(int[] value, int lower, int upper, String valueName)549     public static int[] checkArrayElementsInRange(int[] value, int lower, int upper,
550             String valueName) {
551         checkNotNull(value, valueName + " must not be null");
552 
553         for (int i = 0; i < value.length; ++i) {
554             int v = value[i];
555 
556             if (v < lower) {
557                 throw new IllegalArgumentException(
558                         String.format("%s[%d] is out of range of [%d, %d] (too low)",
559                                 valueName, i, lower, upper));
560             } else if (v > upper) {
561                 throw new IllegalArgumentException(
562                         String.format("%s[%d] is out of range of [%d, %d] (too high)",
563                                 valueName, i, lower, upper));
564             }
565         }
566 
567         return value;
568     }
569 }
570