Preconditions.java revision b3a78b2ca9655396e2d73950221d187b7e5bb3ba
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
17package com.android.internal.util;
18
19/**
20 * Simple static methods to be called at the start of your own methods to verify
21 * correct arguments and state.
22 */
23public class Preconditions {
24
25    /**
26     * Ensures that an object reference passed as a parameter to the calling
27     * method is not null.
28     *
29     * @param reference an object reference
30     * @return the non-null reference that was validated
31     * @throws NullPointerException if {@code reference} is null
32     */
33    public static <T> T checkNotNull(final T reference) {
34        if (reference == null) {
35            throw new NullPointerException();
36        }
37        return reference;
38    }
39
40    /**
41     * Ensures that an object reference passed as a parameter to the calling
42     * method is not null.
43     *
44     * @param reference an object reference
45     * @param errorMessage the exception message to use if the check fails; will
46     *     be converted to a string using {@link String#valueOf(Object)}
47     * @return the non-null reference that was validated
48     * @throws NullPointerException if {@code reference} is null
49     */
50    public static <T> T checkNotNull(final T reference, final Object errorMessage) {
51        if (reference == null) {
52            throw new NullPointerException(String.valueOf(errorMessage));
53        }
54        return reference;
55    }
56
57    /**
58     * Ensures the truth of an expression involving the state of the calling
59     * instance, but not involving any parameters to the calling method.
60     *
61     * @param expression a boolean expression
62     * @throws IllegalStateException if {@code expression} is false
63     */
64    public static void checkState(final boolean expression) {
65        if (!expression) {
66            throw new IllegalStateException();
67        }
68    }
69
70    /**
71     * Check the requested flags, throwing if any requested flags are outside
72     * the allowed set.
73     */
74    public static void checkFlagsArgument(final int requestedFlags, final int allowedFlags) {
75        if ((requestedFlags & allowedFlags) != requestedFlags) {
76            throw new IllegalArgumentException("Requested flags 0x"
77                    + Integer.toHexString(requestedFlags) + ", but only 0x"
78                    + Integer.toHexString(allowedFlags) + " are allowed");
79        }
80    }
81
82    /**
83     * Ensures that that the argument numeric value is non-negative.
84     *
85     * @param value a numeric int value
86     * @param errorMessage the exception message to use if the check fails
87     * @return the validated numeric value
88     * @throws IllegalArgumentException if {@code value} was negative
89     */
90    public static int checkArgumentNonnegative(final int value, final String errorMessage) {
91        if (value < 0) {
92            throw new IllegalArgumentException(errorMessage);
93        }
94
95        return value;
96    }
97
98    /**
99     * Ensures that that the argument numeric value is non-negative.
100     *
101     * @param value a numeric long value
102     * @param errorMessage the exception message to use if the check fails
103     * @return the validated numeric value
104     * @throws IllegalArgumentException if {@code value} was negative
105     */
106    public static long checkArgumentNonnegative(final long value, final String errorMessage) {
107        if (value < 0) {
108            throw new IllegalArgumentException(errorMessage);
109        }
110
111        return value;
112    }
113
114    /**
115     * Ensures that that the argument numeric value is positive.
116     *
117     * @param value a numeric int value
118     * @param errorMessage the exception message to use if the check fails
119     * @return the validated numeric value
120     * @throws IllegalArgumentException if {@code value} was not positive
121     */
122    public static int checkArgumentPositive(final int value, final String errorMessage) {
123        if (value <= 0) {
124            throw new IllegalArgumentException(errorMessage);
125        }
126
127        return value;
128    }
129
130    /**
131     * Ensures that the argument floating point value is a finite number.
132     *
133     * <p>A finite number is defined to be both representable (that is, not NaN) and
134     * not infinite (that is neither positive or negative infinity).</p>
135     *
136     * @param value a floating point value
137     * @param valueName the name of the argument to use if the check fails
138     *
139     * @return the validated floating point value
140     *
141     * @throws IllegalArgumentException if {@code value} was not finite
142     */
143    public static float checkArgumentFinite(final float value, final String valueName) {
144        if (Float.isNaN(value)) {
145            throw new IllegalArgumentException(valueName + " must not be NaN");
146        } else if (Float.isInfinite(value)) {
147            throw new IllegalArgumentException(valueName + " must not be infinite");
148        }
149
150        return value;
151    }
152
153    /**
154     * Ensures that the argument floating point value is within the inclusive range.
155     *
156     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
157     * will always be out of range.</p>
158     *
159     * @param value a floating point value
160     * @param lower the lower endpoint of the inclusive range
161     * @param upper the upper endpoint of the inclusive range
162     * @param valueName the name of the argument to use if the check fails
163     *
164     * @return the validated floating point value
165     *
166     * @throws IllegalArgumentException if {@code value} was not within the range
167     */
168    public static float checkArgumentInRange(float value, float lower, float upper,
169            String valueName) {
170        if (Float.isNaN(value)) {
171            throw new IllegalArgumentException(valueName + " must not be NaN");
172        } else if (value < lower) {
173            throw new IllegalArgumentException(
174                    String.format(
175                            "%s is out of range of [%f, %f] (too low)", valueName, lower, upper));
176        } else if (value > upper) {
177            throw new IllegalArgumentException(
178                    String.format(
179                            "%s is out of range of [%f, %f] (too high)", valueName, lower, upper));
180        }
181
182        return value;
183    }
184
185    /**
186     * Ensures that the array is not {@code null}, and none if its elements are {@code null}.
187     *
188     * @param value an array of boxed objects
189     * @param valueName the name of the argument to use if the check fails
190     *
191     * @return the validated array
192     *
193     * @throws NullPointerException if the {@code value} or any of its elements were {@code null}
194     */
195    public static <T> T[] checkArrayElementsNotNull(final T[] value, final String valueName) {
196        if (value == null) {
197            throw new NullPointerException(valueName + " must not be null");
198        }
199
200        for (int i = 0; i < value.length; ++i) {
201            if (value[i] == null) {
202                throw new NullPointerException(
203                        String.format("%s[%d] must not be null", valueName, i));
204            }
205        }
206
207        return value;
208    }
209
210    /**
211     * Ensures that all elements in the argument floating point array are within the inclusive range
212     *
213     * <p>While this can be used to range check against +/- infinity, note that all NaN numbers
214     * will always be out of range.</p>
215     *
216     * @param value a floating point array of values
217     * @param lower the lower endpoint of the inclusive range
218     * @param upper the upper endpoint of the inclusive range
219     * @param valueName the name of the argument to use if the check fails
220     *
221     * @return the validated floating point value
222     *
223     * @throws IllegalArgumentException if any of the elements in {@code value} were out of range
224     * @throws NullPointerException if the {@code value} was {@code null}
225     */
226    public static float[] checkArrayElementsInRange(float[] value, float lower, float upper,
227            String valueName) {
228        checkNotNull(value, valueName + " must not be null");
229
230        for (int i = 0; i < value.length; ++i) {
231            float v = value[i];
232
233            if (Float.isNaN(v)) {
234                throw new IllegalArgumentException(valueName + "[" + i + "] must not be NaN");
235            } else if (v < lower) {
236                throw new IllegalArgumentException(
237                        String.format("%s[%d] is out of range of [%f, %f] (too low)",
238                                valueName, i, lower, upper));
239            } else if (v > upper) {
240                throw new IllegalArgumentException(
241                        String.format("%s[%d] is out of range of [%f, %f] (too high)",
242                                valueName, i, lower, upper));
243            }
244        }
245
246        return value;
247    }
248}
249