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