001: /*
002: * Copyright 2006 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.opensource.org/licenses/ecl1.php
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.kuali.core.util;
017:
018: /**
019: * This class contains utility methods for making assertions in production code (not test code).
020: * Kuali is not using the {@code assert} keyword because those assertions
021: * are not enabled by default. We can use the methods of this class instead, or throw {@link AssertionError} directly. This makes
022: * assertions effective in production and development, and avoids any risk of changes to functionality because any side-effects that
023: * might be involved in the assertion are done consistently. Although {@code AssertionError} can be thrown directly, and sometimes
024: * the compiler requires this, in many cases these method invocations will be easier to read than the extra {@code if} block with
025: * its negated conditional.
026: *
027: * <p/> These assertions are for use in production code. They should not be confused with
028: * {@link junit.framework.Assert}, {@link junit.framework.AssertionFailedError}, nor {@link org.kuali.test.util.KualiTestAssertionUtils},
029: * which are for test code.
030: *
031: * <p/> These methods
032: * should be used such that when they fail and throw {@code AssertionError}, it indicates that there is a bug in our software.
033: * Drawing attention to the bug this way, as soon as it's discovered, reduces the amount of work required to fix it. So, we should
034: * not catch {@code AssertionError} (or {@link Throwable}) and try to handle or work around it; it indicates a need to change some
035: * source code so that the assertion is never false. For more about why, when, and how to use assertions, see <a
036: * href="https://test.kuali.org/confluence/display/KULDEV/Assert+Keyword+And+AssertionError">Kuali's guide to assertions</a> and <a
037: * href="http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html">Sun's guide to assertions</a>.
038: *
039: * @see org.kuali.test.util.KualiTestAssertionUtils
040: */
041: public class AssertionUtils {
042:
043: /**
044: * Asserts that the {@code isTrue} parameter is true. If this assertion fails, the {@code AssertionError} it throws will have no
045: * detail message, only a stacktrace indicating the source file and line number containing the assertion that failed. <p/> This
046: * method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code), and its
047: * signature is intended to resemble that of the {@code assert} keyword.
048: *
049: * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
050: *
051: * @throws AssertionError if {@code isTrue} is false
052: */
053: public static void assertThat(boolean isTrue) {
054: if (!isTrue) {
055: throw new AssertionError();
056: }
057: }
058:
059: /**
060: * Asserts that the {@code isTrue} parameter is true, with a detail message. The purpose of the detail message is to capture and
061: * communicate details about the assertion failure that will help a developer diagnose and fix the bug that led this assertion
062: * to fail. It's meant to be interpreted in the context of a full stack trace and with the source code containing the failed
063: * assertion. It is <em>not</em> a user-level error message. Details like {@code "assertion failed"} are redundant, not
064: * useful. <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production
065: * code), and its signature is intended to resemble that of the {@code assert} keyword.
066: *
067: * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
068: *
069: * @param detailMessage value to use for the {@code AssertionError}'s detail message. If this is an instance of
070: * {@link Throwable}, then it also becomes the {@code AssertionError}'s cause. (Primitives are auto-boxed by JDK 1.5.)
071: * Objects are converted {@link Object#toString toString}, but only if this assertion fails, so it's better not to
072: * convert this detail in advance. The code will be a little easier to read, and there will be some performance
073: * improvement (altho it may be insignificant). For example, passing just {@code accountingLine} is better than passing
074: * {@code accountingLine.toString()} or {@code "accounting line:"+accountingLine}. Since the assertion has failed, any
075: * inconsistent side-effects from the conversion are not an issue. A {@code null} reference is treated as the String
076: * {@code "null"}.
077: *
078: * @throws AssertionError if {@code isTrue} is false
079: */
080: public static void assertThat(boolean isTrue, Object detailMessage) {
081: if (!isTrue) {
082: throw new AssertionError(detailMessage);
083: }
084: }
085:
086: /**
087: * Asserts that the {@code isTrue} parameter is true. This method is convenient for formatting the detail message, and as an
088: * optimization for detail arguments that are expensive to convert to String. For example, suppose {@code foo} and {@code bar}
089: * are two objects with expensive {@link Object#toString} methods. If you use
090: *
091: * <pre>
092: * AssertionUtils.assertThat(foo.equals(bar), "foo: " + foo + " bar: " + bar);
093: * </pre>
094: *
095: * then both object's {@code toString} methods will be invoked every time this assertion is done, even though those details are
096: * not normally needed because this assertion normally succeeds. You can use this method instead to only do those
097: * {@code toString} invocations if this assertion fails:
098: *
099: * <pre>
100: * AssertionUtils.assertThat(foo.equals(bar), "foo: %s bar: %s", foo, bar);
101: * </pre>
102: *
103: * <p/> This method's name is intended to avoid confusion with JUnit asserts (which are for test code, not production code).
104: *
105: * @param isTrue whether this assertion succeeds. (Boolean objects are auto-unboxed by JDK 1.5.)
106: *
107: * @param detailMessageFormat a {@linkplain String#format format string} to be used in constructing the {@code AssertionError}'s
108: * detail message. The purpose of this message is to capture and communicate details about the assertion failure that
109: * will help a developer diagnose and fix the bug that led the assertion to fail. It's meant to be interpreted in the
110: * context of a full stack trace and with the source code containing the failed assertion. It is <em>not</em> a
111: * user-level error message. Details like {@code "assertion failed"} are redundant, not useful. This detail message
112: * cannot be {@code null}.
113: *
114: * @param detailMessageArgs one or more arguments to the format string. Nulls are allowed by some format conversions, such as
115: * {@code "%s"}. (Primitives are auto-boxed by JDK 1.5.) Zero arguments will invoke {@link #assertThat(boolean, Object)}
116: * instead, so the detail message will not be treated as a format string.
117: *
118: * @throws AssertionError if {@code isTrue} is false
119: *
120: * @throws java.util.IllegalFormatException if {@code detailMessageFormat} contains an illegal syntax, a format specifier that
121: * is incompatible with the given arguments, insufficient arguments given the format string, or other illegal
122: * conditions. For specification of all possible formatting errors, see the Details section of
123: * {@link java.util.Formatter}.
124: *
125: * @throws NullPointerException if the {@code detailMessageFormat} is {@code null}
126: *
127: * @see String#format
128: */
129: public static void assertThat(boolean isTrue,
130: String detailMessageFormat, Object... detailMessageArgs) {
131: if (!isTrue) {
132: throw new AssertionError(String.format(detailMessageFormat,
133: detailMessageArgs));
134: }
135: }
136: }
|