18b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/*
28b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Copyright (C) 2007 Google Inc.
38b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
48b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License");
58b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * you may not use this file except in compliance with the License.
68b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * You may obtain a copy of the License at
78b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
88b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0
98b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Unless required by applicable law or agreed to in writing, software
118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS,
128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * See the License for the specific language governing permissions and
148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * limitations under the License.
158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */
168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.lib.base;
188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereiraimport java.util.NoSuchElementException;
208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira/**
228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Simple static methods to be called at the start of your own methods to verify
238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * correct arguments and state. This allows constructs such as
248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <pre>
258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *     if (count <= 0) {
268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *       throw new IllegalArgumentException("must be positive: " + count);
278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *     }</pre>
288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * to be replaced with the more compact
308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <pre>
318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *     checkArgument(count > 0, "must be positive: %s", count);</pre>
328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * Note that the sense of the expression is inverted; with {@code Preconditions}
348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * you declare what you expect to be <i>true</i>, just as you do with an
358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <a href="http://java.sun.com/j2se/1.5.0/docs/guide/language/assert.html">
368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@code assert}</a> or a JUnit {@code assertTrue} call.
378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p><b>Warning:</b> only the {@code "%s"} specifier is recognized as a
398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * placeholder in these messages, not the full range of {@link
408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * String#format(String, Object[])} specifiers.
418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <p>Take care not to confuse precondition checking with other similar types
438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * of checks! Precondition exceptions -- including those provided here, but also
448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * {@link IndexOutOfBoundsException}, {@link NoSuchElementException}, {@link
458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * UnsupportedOperationException} and others -- are used to signal that the
468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * <i>calling method</i> has made an error. This tells the caller that it should
478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * not have invoked the method when it did, with the arguments it did, or
488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * perhaps ever. Postcondition or other invariant failures should not throw
498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * these types of exceptions.
508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira *
518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @author Kevin Bourrillion
528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira * @since 2010.01.04 <b>stable</b> (imported from Google Collections Library)
538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira */
548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereirapublic class Preconditions {
558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private Preconditions() {}
568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving one or more parameters to the
598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * calling method.
608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code expression} is false
638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkArgument(boolean expression) {
658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalArgumentException();
678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving one or more parameters to the
728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * calling method.
738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessage the exception message to use if the check fails; will
768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     be converted to a string using {@link String#valueOf(Object)}
778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code expression} is false
788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkArgument(boolean expression, Object errorMessage) {
808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalArgumentException(String.valueOf(errorMessage));
828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving one or more parameters to the
878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * calling method.
888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageTemplate a template for the exception message should the
918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     check fail. The message is formed by replacing each {@code %s}
928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     placeholder in the template with an argument. These are matched by
938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     Unmatched arguments will be appended to the formatted message in square
958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     braces. Unmatched placeholders will be left as-is.
968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageArgs the arguments to be substituted into the message
978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     template. Arguments are converted to strings using
988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     {@link String#valueOf(Object)}.
998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code expression} is false
1008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws NullPointerException if the check fails and either {@code
1018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
1028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     this happen)
1038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkArgument(boolean expression,
1058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      String errorMessageTemplate, Object... errorMessageArgs) {
1068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
1078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalArgumentException(
1088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          format(errorMessageTemplate, errorMessageArgs));
1098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving the state of the calling
1148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * instance, but not involving any parameters to the calling method.
1158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
1178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalStateException if {@code expression} is false
1188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkState(boolean expression) {
1208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
1218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalStateException();
1228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving the state of the calling
1278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * instance, but not involving any parameters to the calling method.
1288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
1308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessage the exception message to use if the check fails; will
1318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     be converted to a string using {@link String#valueOf(Object)}
1328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalStateException if {@code expression} is false
1338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkState(boolean expression, Object errorMessage) {
1358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
1368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalStateException(String.valueOf(errorMessage));
1378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures the truth of an expression involving the state of the calling
1428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * instance, but not involving any parameters to the calling method.
1438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param expression a boolean expression
1458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageTemplate a template for the exception message should the
1468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     check fail. The message is formed by replacing each {@code %s}
1478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     placeholder in the template with an argument. These are matched by
1488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
1498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     Unmatched arguments will be appended to the formatted message in square
1508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     braces. Unmatched placeholders will be left as-is.
1518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageArgs the arguments to be substituted into the message
1528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     template. Arguments are converted to strings using
1538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     {@link String#valueOf(Object)}.
1548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalStateException if {@code expression} is false
1558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws NullPointerException if the check fails and either {@code
1568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     errorMessageTemplate} or {@code errorMessageArgs} is null (don't let
1578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     this happen)
1588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkState(boolean expression,
1608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      String errorMessageTemplate, Object... errorMessageArgs) {
1618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (!expression) {
1628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalStateException(
1638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          format(errorMessageTemplate, errorMessageArgs));
1648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that an object reference passed as a parameter to the calling
1698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * method is not null.
1708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param reference an object reference
1728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the non-null reference that was validated
1738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws NullPointerException if {@code reference} is null
1748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static <T> T checkNotNull(T reference) {
1768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (reference == null) {
1778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new NullPointerException();
1788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return reference;
1808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
1838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that an object reference passed as a parameter to the calling
1848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * method is not null.
1858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
1868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param reference an object reference
1878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessage the exception message to use if the check fails; will
1888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     be converted to a string using {@link String#valueOf(Object)}
1898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the non-null reference that was validated
1908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws NullPointerException if {@code reference} is null
1918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
1928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static <T> T checkNotNull(T reference, Object errorMessage) {
1938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (reference == null) {
1948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new NullPointerException(String.valueOf(errorMessage));
1958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
1968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return reference;
1978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
1988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
1998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that an object reference passed as a parameter to the calling
2018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * method is not null.
2028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param reference an object reference
2048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageTemplate a template for the exception message should the
2058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     check fail. The message is formed by replacing each {@code %s}
2068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     placeholder in the template with an argument. These are matched by
2078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     position - the first {@code %s} gets {@code errorMessageArgs[0]}, etc.
2088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     Unmatched arguments will be appended to the formatted message in square
2098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     braces. Unmatched placeholders will be left as-is.
2108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param errorMessageArgs the arguments to be substituted into the message
2118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     template. Arguments are converted to strings using
2128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     {@link String#valueOf(Object)}.
2138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the non-null reference that was validated
2148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws NullPointerException if {@code reference} is null
2158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static <T> T checkNotNull(T reference, String errorMessageTemplate,
2178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      Object... errorMessageArgs) {
2188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (reference == null) {
2198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      // If either of these parameters is null, the right thing happens anyway
2208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new NullPointerException(
2218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira          format(errorMessageTemplate, errorMessageArgs));
2228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
2238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return reference;
2248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /*
2278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * All recent hotspots (as of 2009) *really* like to have the natural code
2288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * if (guardExpression) {
2308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *    throw new BadException(messageExpression);
2318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * }
2328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * refactored so that messageExpression is moved to a separate
2348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * String-returning method.
2358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * if (guardExpression) {
2378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *    throw new BadException(badMsg(...));
2388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * }
2398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * The alternative natural refactorings into void or Exception-returning
2418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * methods are much slower.  This is a big deal - we're talking factors of
2428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * 2-8 in microbenchmarks, not just 10-20%.  (This is a hotspot optimizer
2438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * bug, which should be fixed, but that's a separate, big project).
2448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * The coding pattern above is heavily used in java.util, e.g. in ArrayList.
2468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * There is a RangeCheckMicroBenchmark in the JDK that was used to test this.
2478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * But the methods in this class want to throw different exceptions,
2498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * depending on the args, so it appears that this pattern is not directly
2508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * applicable.  But we can use the ridiculous, devious trick of throwing an
2518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * exception in the middle of the construction of another exception.
2528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Hotspot is fine with that.
2538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that {@code index} specifies a valid <i>element</i> in an array,
2578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * list or string of size {@code size}. An element index may range from zero,
2588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * inclusive, to {@code size}, exclusive.
2598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param index a user-supplied index identifying an element of an array, list
2618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     or string
2628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param size the size of that array, list or string
2638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the value of {@code index}
2648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IndexOutOfBoundsException if {@code index} is negative or is not
2658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     less than {@code size}
2668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code size} is negative
2678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static int checkElementIndex(int index, int size) {
2698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return checkElementIndex(index, size, "index");
2708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
2738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that {@code index} specifies a valid <i>element</i> in an array,
2748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * list or string of size {@code size}. An element index may range from zero,
2758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * inclusive, to {@code size}, exclusive.
2768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
2778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param index a user-supplied index identifying an element of an array, list
2788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     or string
2798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param size the size of that array, list or string
2808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param desc the text to use to describe this index in an error message
2818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the value of {@code index}
2828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IndexOutOfBoundsException if {@code index} is negative or is not
2838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     less than {@code size}
2848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code size} is negative
2858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
2868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static int checkElementIndex(int index, int size, String desc) {
2878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // Carefully optimized for execution by hotspot (explanatory comment above)
2888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (index < 0 || index >= size) {
2898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IndexOutOfBoundsException(badElementIndex(index, size, desc));
2908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
2918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return index;
2928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
2938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
2948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private static String badElementIndex(int index, int size, String desc) {
2958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (index < 0) {
2968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return format("%s (%s) must not be negative", desc, index);
2978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    } else if (size < 0) {
2988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalArgumentException("negative size: " + size);
2998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    } else { // index >= size
3008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return format("%s (%s) must be less than size (%s)", desc, index, size);
3018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that {@code index} specifies a valid <i>position</i> in an array,
3068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * list or string of size {@code size}. A position index may range from zero
3078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * to {@code size}, inclusive.
3088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param index a user-supplied index identifying a position in an array, list
3108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     or string
3118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param size the size of that array, list or string
3128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the value of {@code index}
3138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IndexOutOfBoundsException if {@code index} is negative or is
3148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     greater than {@code size}
3158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code size} is negative
3168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static int checkPositionIndex(int index, int size) {
3188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return checkPositionIndex(index, size, "index");
3198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that {@code index} specifies a valid <i>position</i> in an array,
3238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * list or string of size {@code size}. A position index may range from zero
3248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * to {@code size}, inclusive.
3258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param index a user-supplied index identifying a position in an array, list
3278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     or string
3288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param size the size of that array, list or string
3298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param desc the text to use to describe this index in an error message
3308b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @return the value of {@code index}
3318b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IndexOutOfBoundsException if {@code index} is negative or is
3328b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     greater than {@code size}
3338b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code size} is negative
3348b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3358b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static int checkPositionIndex(int index, int size, String desc) {
3368b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // Carefully optimized for execution by hotspot (explanatory comment above)
3378b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (index < 0 || index > size) {
3388b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IndexOutOfBoundsException(badPositionIndex(index, size, desc));
3398b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3408b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return index;
3418b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3428b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3438b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private static String badPositionIndex(int index, int size, String desc) {
3448b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (index < 0) {
3458b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return format("%s (%s) must not be negative", desc, index);
3468b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    } else if (size < 0) {
3478b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IllegalArgumentException("negative size: " + size);
3488b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    } else { // index > size
3498b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return format("%s (%s) must not be greater than size (%s)",
3508b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                    desc, index, size);
3518b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3528b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3538b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3548b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3558b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Ensures that {@code start} and {@code end} specify a valid <i>positions</i>
3568b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * in an array, list or string of size {@code size}, and are in order. A
3578b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * position index may range from zero to {@code size}, inclusive.
3588b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3598b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param start a user-supplied index identifying a starting position in an
3608b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     array, list or string
3618b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param end a user-supplied index identifying a ending position in an array,
3628b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     list or string
3638b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param size the size of that array, list or string
3648b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IndexOutOfBoundsException if either index is negative or is
3658b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     greater than {@code size}, or if {@code end} is less than {@code start}
3668b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @throws IllegalArgumentException if {@code size} is negative
3678b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3688b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  public static void checkPositionIndexes(int start, int end, int size) {
3698b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // Carefully optimized for execution by hotspot (explanatory comment above)
3708b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (start < 0 || end < start || end > size) {
3718b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      throw new IndexOutOfBoundsException(badPositionIndexes(start, end, size));
3728b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3738b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3748b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3758b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  private static String badPositionIndexes(int start, int end, int size) {
3768b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (start < 0 || start > size) {
3778b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return badPositionIndex(start, size, "start index");
3788b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3798b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (end < 0 || end > size) {
3808b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      return badPositionIndex(end, size, "end index");
3818b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
3828b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // end < start
3838b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return format("end index (%s) must not be less than start index (%s)",
3848b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira                  end, start);
3858b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
3868b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
3878b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  /**
3888b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * Substitutes each {@code %s} in {@code template} with an argument. These
3898b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * are matched by position - the first {@code %s} gets {@code args[0]}, etc.
3908b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * If there are more arguments than placeholders, the unmatched arguments will
3918b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * be appended to the end of the formatted message in square braces.
3928b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *
3938b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param template a non-null string containing 0 or more {@code %s}
3948b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     placeholders.
3958b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   * @param args the arguments to be substituted into the message
3968b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     template. Arguments are converted to strings using
3978b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   *     {@link String#valueOf(Object)}. Arguments can be null.
3988b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira   */
3998b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  static String format(String template, Object... args) {
4008b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // start substituting the arguments into the '%s' placeholders
4018b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    StringBuilder builder = new StringBuilder(
4028b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        template.length() + 16 * args.length);
4038b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    int templateStart = 0;
4048b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    int i = 0;
4058b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    while (i < args.length) {
4068b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      int placeholderStart = template.indexOf("%s", templateStart);
4078b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      if (placeholderStart == -1) {
4088b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        break;
4098b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
4108b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      builder.append(template.substring(templateStart, placeholderStart));
4118b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      builder.append(args[i++]);
4128b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      templateStart = placeholderStart + 2;
4138b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4148b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    builder.append(template.substring(templateStart));
4158b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4168b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    // if we run out of placeholders, append the extra args in square braces
4178b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    if (i < args.length) {
4188b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      builder.append(" [");
4198b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      builder.append(args[i++]);
4208b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      while (i < args.length) {
4218b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        builder.append(", ");
4228b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira        builder.append(args[i++]);
4238b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      }
4248b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira      builder.append("]");
4258b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    }
4268b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira
4278b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira    return builder.toString();
4288b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira  }
4298b99ba451db6973978e60f91da2199686a9c85e7Mindy Pereira}
430