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 java.util.Collection;
20 
21 /**
22  * Simple static methods to be called at the start of your own methods to verify
23  * correct arguments and state.
24  */
25 public class Preconditions {
26 
checkArgument(boolean expression)27     public static void checkArgument(boolean expression) {
28         if (!expression) {
29             throw new IllegalArgumentException();
30         }
31     }
32 
33     /**
34      * Ensures that an object reference passed as a parameter to the calling
35      * method is not null.
36      *
37      * @param reference an object reference
38      * @return the non-null reference that was validated
39      * @throws NullPointerException if {@code reference} is null
40      */
checkNotNull(final T reference)41     public static <T> T checkNotNull(final T reference) {
42         if (reference == null) {
43             throw new NullPointerException();
44         }
45         return reference;
46     }
47 
48     /**
49      * Ensures that an object reference passed as a parameter to the calling
50      * method is not null.
51      *
52      * @param reference an object reference
53      * @param errorMessage the exception message to use if the check fails; will
54      *     be converted to a string using {@link String#valueOf(Object)}
55      * @return the non-null reference that was validated
56      * @throws NullPointerException if {@code reference} is null
57      */
checkNotNull(final T reference, final Object errorMessage)58     public static <T> T checkNotNull(final T reference, final Object errorMessage) {
59         if (reference == null) {
60             throw new NullPointerException(String.valueOf(errorMessage));
61         }
62         return reference;
63     }
64 
65     /**
66      * Ensures the truth of an expression involving the state of the calling
67      * instance, but not involving any parameters to the calling method.
68      *
69      * @param expression a boolean expression
70      * @throws IllegalStateException if {@code expression} is false
71      */
checkState(final boolean expression)72     public static void checkState(final boolean expression) {
73         if (!expression) {
74             throw new IllegalStateException();
75         }
76     }
77 
78     /**
79      * Check the requested flags, throwing if any requested flags are outside
80      * the allowed set.
81      */
checkFlagsArgument(final int requestedFlags, final int allowedFlags)82     public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
83         if ((requestedFlags & allowedFlags) != requestedFlags) {
84             throw new IllegalArgumentException("Requested flags 0x"
85                     + Integer.toHexString(requestedFlags) + ", but only 0x"
86                     + Integer.toHexString(allowedFlags) + " are allowed");
87         }
88     }
89 
90     /**
91      * Ensures that that the argument numeric value is non-negative.
92      *
93      * @param value a numeric int value
94      * @param errorMessage the exception message to use if the check fails
95      * @return the validated numeric value
96      * @throws IllegalArgumentException if {@code value} was negative
97      */
checkArgumentNonnegative(final int value, final String errorMessage)98     public static int checkArgumentNonnegative(final int value, final String errorMessage) {
99         if (value < 0) {
100             throw new IllegalArgumentException(errorMessage);
101         }
102 
103         return value;
104     }
105 
106     /**
107      * Ensures that that the argument numeric value is non-negative.
108      *
109      * @param value a numeric long value
110      * @param errorMessage the exception message to use if the check fails
111      * @return the validated numeric value
112      * @throws IllegalArgumentException if {@code value} was negative
113      */
checkArgumentNonnegative(final long value, final String errorMessage)114     public static long checkArgumentNonnegative(final long value, final String errorMessage) {
115         if (value < 0) {
116             throw new IllegalArgumentException(errorMessage);
117         }
118 
119         return value;
120     }
121 
122     /**
123      * Ensures that that the argument numeric value is positive.
124      *
125      * @param value a numeric int value
126      * @param errorMessage the exception message to use if the check fails
127      * @return the validated numeric value
128      * @throws IllegalArgumentException if {@code value} was not positive
129      */
checkArgumentPositive(final int value, final String errorMessage)130     public static int checkArgumentPositive(final int value, final String errorMessage) {
131         if (value <= 0) {
132             throw new IllegalArgumentException(errorMessage);
133         }
134 
135         return value;
136     }
137 
138     /**
139      * Ensures that the argument floating point value is a finite number.
140      *
141      * <p>A finite number is defined to be both representable (that is, not NaN) and
142      * not infinite (that is neither positive or negative infinity).</p>
143      *
144      * @param value a floating point value
145      * @param valueName the name of the argument to use if the check fails
146      *
147      * @return the validated floating point value
148      *
149      * @throws IllegalArgumentException if {@code value} was not finite
150      */
checkArgumentFinite(final float value, final String valueName)151     public static float checkArgumentFinite(final float value, final String valueName) {
152         if (Float.isNaN(value)) {
153             throw new IllegalArgumentException(valueName + " must not be NaN");
154         } else if (Float.isInfinite(value)) {
155             throw new IllegalArgumentException(valueName + " must not be infinite");
156         }
157 
158         return value;
159     }
160 
161     /**
162      * Ensures that the argument floating point value is within the inclusive range.
163      *
164      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
165      * will always be out of range.</p>
166      *
167      * @param value a floating point value
168      * @param lower the lower endpoint of the inclusive range
169      * @param upper the upper endpoint of the inclusive range
170      * @param valueName the name of the argument to use if the check fails
171      *
172      * @return the validated floating point value
173      *
174      * @throws IllegalArgumentException if {@code value} was not within the range
175      */
checkArgumentInRange(float value, float lower, float upper, String valueName)176     public static float checkArgumentInRange(float value, float lower, float upper,
177             String valueName) {
178         if (Float.isNaN(value)) {
179             throw new IllegalArgumentException(valueName + " must not be NaN");
180         } else if (value < lower) {
181             throw new IllegalArgumentException(
182                     String.format(
183                             "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
184         } else if (value > upper) {
185             throw new IllegalArgumentException(
186                     String.format(
187                             "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
188         }
189 
190         return value;
191     }
192 
193     /**
194      * Ensures that the argument int value is within the inclusive range.
195      *
196      * @param value a int value
197      * @param lower the lower endpoint of the inclusive range
198      * @param upper the upper endpoint of the inclusive range
199      * @param valueName the name of the argument to use if the check fails
200      *
201      * @return the validated int value
202      *
203      * @throws IllegalArgumentException if {@code value} was not within the range
204      */
checkArgumentInRange(int value, int lower, int upper, String valueName)205     public static int checkArgumentInRange(int value, int lower, int upper,
206             String valueName) {
207         if (value < lower) {
208             throw new IllegalArgumentException(
209                     String.format(
210                             "%s is out of range of [%d, %d] (too low)", valueName, lower, upper));
211         } else if (value > upper) {
212             throw new IllegalArgumentException(
213                     String.format(
214                             "%s is out of range of [%d, %d] (too high)", valueName, lower, upper));
215         }
216 
217         return value;
218     }
219 
220     /**
221      * Ensures that the array is not {@code null}, and none of its elements are {@code null}.
222      *
223      * @param value an array of boxed objects
224      * @param valueName the name of the argument to use if the check fails
225      *
226      * @return the validated array
227      *
228      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
229      */
checkArrayElementsNotNull(final T[] value, final String valueName)230     public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
231         if (value == null) {
232             throw new NullPointerException(valueName + " must not be null");
233         }
234 
235         for (int i = 0; i < value.length; ++i) {
236             if (value[i] == null) {
237                 throw new NullPointerException(
238                         String.format("%s[%d] must not be null", valueName, i));
239             }
240         }
241 
242         return value;
243     }
244 
245     /**
246      * Ensures that the {@link Collection} is not {@code null}, and none of its elements are
247      * {@code null}.
248      *
249      * @param value a {@link Collection} of boxed objects
250      * @param valueName the name of the argument to use if the check fails
251      *
252      * @return the validated {@link Collection}
253      *
254      * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
255      */
checkCollectionElementsNotNull(final Collection<T> value, final String valueName)256     public static <T> Collection<T> checkCollectionElementsNotNull(final Collection<T> value,
257             final String valueName) {
258         if (value == null) {
259             throw new NullPointerException(valueName + " must not be null");
260         }
261 
262         long ctr = 0;
263         for (T elem : value) {
264             if (elem == null) {
265                 throw new NullPointerException(
266                         String.format("%s[%d] must not be null", valueName, ctr));
267             }
268             ++ctr;
269         }
270 
271         return value;
272     }
273 
274     /**
275      * Ensures that the {@link Collection} is not {@code null}, and contains at least one element.
276      *
277      * @param value a {@link Collection} of boxed elements.
278      * @param valueName the name of the argument to use if the check fails.
279 
280      * @return the validated {@link Collection}
281      *
282      * @throws NullPointerException if the {@code value} was {@code null}
283      * @throws IllegalArgumentException if the {@code value} was empty
284      */
checkCollectionNotEmpty(final Collection<T> value, final String valueName)285     public static <T> Collection<T> checkCollectionNotEmpty(final Collection<T> value,
286             final String valueName) {
287         if (value == null) {
288             throw new NullPointerException(valueName + " must not be null");
289         }
290         if (value.isEmpty()) {
291             throw new IllegalArgumentException(valueName + " is empty");
292         }
293         return value;
294     }
295 
296     /**
297      * Ensures that all elements in the argument floating point array are within the inclusive range
298      *
299      * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
300      * will always be out of range.</p>
301      *
302      * @param value a floating point array of values
303      * @param lower the lower endpoint of the inclusive range
304      * @param upper the upper endpoint of the inclusive range
305      * @param valueName the name of the argument to use if the check fails
306      *
307      * @return the validated floating point value
308      *
309      * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
310      * @throws NullPointerException if the {@code value} was {@code null}
311      */
checkArrayElementsInRange(float[] value, float lower, float upper, String valueName)312     public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
313             String valueName) {
314         checkNotNull(value, valueName + " must not be null");
315 
316         for (int i = 0; i < value.length; ++i) {
317             float v = value[i];
318 
319             if (Float.isNaN(v)) {
320                 throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
321             } else if (v < lower) {
322                 throw new IllegalArgumentException(
323                         String.format("%s[%d] is out of range of [%f, %f] (too low)",
324                                 valueName, i, lower, upper));
325             } else if (v > upper) {
326                 throw new IllegalArgumentException(
327                         String.format("%s[%d] is out of range of [%f, %f] (too high)",
328                                 valueName, i, lower, upper));
329             }
330         }
331 
332         return value;
333     }
334 }
335