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