diff --git a/common/ballcat-common-util/src/main/java/org/ballcat/common/util/Assert.java b/common/ballcat-common-util/src/main/java/org/ballcat/common/util/Assert.java index 7df7328f..16a3de01 100644 --- a/common/ballcat-common-util/src/main/java/org/ballcat/common/util/Assert.java +++ b/common/ballcat-common-util/src/main/java/org/ballcat/common/util/Assert.java @@ -16,23 +16,36 @@ package org.ballcat.common.util; +import java.math.BigDecimal; +import java.text.MessageFormat; +import java.util.Map; +import java.util.Objects; import java.util.function.Supplier; +import java.util.regex.Pattern; /** - * 定制Assert 抛BusinessException + * 断言
+ * 断言某些对象或值是否符合规定,否则抛出异常。经常用于做变量检查 * - * @author evil0th Create on 2023/6/7 + * @author Looly + * @author evil0th */ public final class Assert { private Assert() { } + private static final String TEMPLATE_VALUE_MUST_BE_BETWEEN_AND = "The value must be between {} and {}."; + /** - * Assert a boolean expression, throwing an {@code Throwable} - * @param Throwable - * @param expression expression a boolean expression - * @param supplier supplier + * 断言是否为真,如果为 {@code false} 抛出给定的异常
+ * + *
+	 * Assert.isTrue(i > 0, IllegalArgumentException::new);
+	 * 
+ * @param 异常类型 + * @param expression 布尔值 + * @param supplier 指定断言不通过时抛出的异常 * @throws X if expression is {@code false} */ public static void isTrue(boolean expression, Supplier supplier) throws X { @@ -42,12 +55,146 @@ public static void isTrue(boolean expression, Supplier Throwable - * @param object a object - * @param errorSupplier errorSupplier + * 断言是否为真,如果为 {@code false} 抛出 {@code IllegalArgumentException} 异常
+ * + *
+	 * Assert.isTrue(i > 0, "The value must be greater than zero");
+	 * 
+ * @param expression 布尔值 + * @param errorMsgTemplate 错误抛出异常附带的消息模板,变量用{}代替 + * @param params 参数列表 + * @throws IllegalArgumentException if expression is {@code false} + */ + public static void isTrue(boolean expression, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + isTrue(expression, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言是否为真,如果为 {@code false} 抛出 {@code IllegalArgumentException} 异常
+ * + *
+	 * Assert.isTrue(i > 0);
+	 * 
+ * @param expression 布尔值 + * @throws IllegalArgumentException if expression is {@code false} + */ + public static void isTrue(boolean expression) throws IllegalArgumentException { + isTrue(expression, "[Assertion failed] - this expression must be true"); + } + + /** + * 断言是否为假,如果为 {@code true} 抛出指定类型异常
+ * 并使用指定的函数获取错误信息返回
+	 *  Assert.isFalse(i > 0, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 异常类型 + * @param expression 布尔值 + * @param errorSupplier 指定断言不通过时抛出的异常 * @throws X if expression is {@code false} */ + public static void isFalse(boolean expression, Supplier errorSupplier) throws X { + if (expression) { + throw errorSupplier.get(); + } + } + + /** + * 断言是否为假,如果为 {@code true} 抛出 {@code IllegalArgumentException} 异常
+ * + *
+	 * Assert.isFalse(i < 0, "The value must not be negative");
+	 * 
+ * @param expression 布尔值 + * @param errorMsgTemplate 错误抛出异常附带的消息模板,变量用{}代替 + * @param params 参数列表 + * @throws IllegalArgumentException if expression is {@code false} + */ + public static void isFalse(boolean expression, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + isFalse(expression, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言是否为假,如果为 {@code true} 抛出 {@code IllegalArgumentException} 异常
+ * + *
+	 * Assert.isFalse(i < 0);
+	 * 
+ * @param expression 布尔值 + * @throws IllegalArgumentException if expression is {@code false} + */ + public static void isFalse(boolean expression) throws IllegalArgumentException { + isFalse(expression, "[Assertion failed] - this expression must be false"); + } + + /** + * 断言对象是否为{@code null} ,如果不为{@code null} 抛出指定类型异常 并使用指定的函数获取错误信息返回
+	 * Assert.isNull(value, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 异常类型 + * @param object 被检查的对象 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @throws X if the object is not {@code null} + */ + public static void isNull(Object object, Supplier errorSupplier) throws X { + if (null != object) { + throw errorSupplier.get(); + } + } + + /** + * 断言对象是否为{@code null} ,如果不为{@code null} 抛出{@link IllegalArgumentException} 异常 + * + *
+	 * Assert.isNull(value, "The value must be null");
+	 * 
+ * @param object 被检查的对象 + * @param errorMsgTemplate 消息模板,变量使用{}表示 + * @param params 参数列表 + * @throws IllegalArgumentException if the object is not {@code null} + */ + public static void isNull(Object object, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + isNull(object, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言对象是否为{@code null} ,如果不为{@code null} 抛出{@link IllegalArgumentException} 异常 + * + *
+	 * Assert.isNull(value);
+	 * 
+ * @param object 被检查对象 + * @throws IllegalArgumentException if the object is not {@code null} + */ + public static void isNull(Object object) throws IllegalArgumentException { + isNull(object, "[Assertion failed] - the object argument must be null"); + } + + // ----------------------------------------------------------------------------------------------------------- + // Check not null + + /** + * 断言对象是否不为{@code null} ,如果为{@code null} 抛出指定类型异常 并使用指定的函数获取错误信息返回
+	 * Assert.notNull(clazz, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 被检查对象泛型类型 + * @param 异常类型 + * @param object 被检查对象 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 被检查后的对象 + * @throws X if the object is {@code null} + */ public static T notNull(T object, Supplier errorSupplier) throws X { if (null == object) { throw errorSupplier.get(); @@ -55,4 +202,910 @@ public static T notNull(T object, Supplier errorSupp return object; } + /** + * 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常 Assert + * that an object is not {@code null} . + * + *
+	 * Assert.notNull(clazz, "The class must not be null");
+	 * 
+ * @param 被检查对象泛型类型 + * @param object 被检查对象 + * @param errorMsgTemplate 错误消息模板,变量使用{}表示 + * @param params 参数 + * @return 被检查后的对象 + * @throws IllegalArgumentException if the object is {@code null} + */ + public static T notNull(T object, String errorMsgTemplate, Object... params) throws IllegalArgumentException { + return notNull(object, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言对象是否不为{@code null} ,如果为{@code null} 抛出{@link IllegalArgumentException} 异常 + * + *
+	 * Assert.notNull(clazz);
+	 * 
+ * @param 被检查对象类型 + * @param object 被检查对象 + * @return 非空对象 + * @throws IllegalArgumentException if the object is {@code null} + */ + public static T notNull(T object) throws IllegalArgumentException { + return notNull(object, "[Assertion failed] - this argument is required; it must not be null"); + } + + // ----------------------------------------------------------------------------------------------------------- + // Check empty + + /** + * 检查给定字符串是否为空,为空抛出自定义异常,并使用指定的函数获取错误信息返回。
+	 * Assert.notEmpty(name, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 异常类型 + * @param 字符串类型 + * @param text 被检查字符串 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 非空字符串 + * @throws X 被检查字符串为空抛出此异常 + */ + public static T notEmpty(T text, Supplier errorSupplier) throws X { + if (text == null || text.length() == 0) { + throw errorSupplier.get(); + } + return text; + } + + /** + * 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException} + * + *
+	 * Assert.notEmpty(name, "Name must not be empty");
+	 * 
+ * @param 字符串类型 + * @param text 被检查字符串 + * @param errorMsgTemplate 错误消息模板,变量使用{}表示 + * @param params 参数 + * @return 非空字符串 + * @throws IllegalArgumentException 被检查字符串为空 + */ + public static T notEmpty(T text, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notEmpty(text, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 检查给定字符串是否为空,为空抛出 {@link IllegalArgumentException} + * + *
+	 * Assert.notEmpty(name);
+	 * 
+ * @param 字符串类型 + * @param text 被检查字符串 + * @return 被检查的字符串 + * @throws IllegalArgumentException 被检查字符串为空 + */ + public static T notEmpty(T text) throws IllegalArgumentException { + return notEmpty(text, + "[Assertion failed] - this String argument must have length; it must not be null or empty"); + } + + /** + * 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出自定义异常。 并使用指定的函数获取错误信息返回
+	 * Assert.notBlank(name, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 异常类型 + * @param 字符串类型 + * @param text 被检查字符串 + * @param errorMsgSupplier 错误抛出异常附带的消息生产接口 + * @return 非空字符串 + * @throws X 被检查字符串为空白 + */ + public static T notBlank(T text, Supplier errorMsgSupplier) + throws X { + if (text == null || text.length() == 0 || !StringUtils.containsText(text)) { + throw errorMsgSupplier.get(); + } + return text; + } + + /** + * 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException} + * + *
+	 * Assert.notBlank(name, "Name must not be blank");
+	 * 
+ * @param 字符串类型 + * @param text 被检查字符串 + * @param errorMsgTemplate 错误消息模板,变量使用{}表示 + * @param params 参数 + * @return 非空字符串 + * @throws IllegalArgumentException 被检查字符串为空白 + */ + public static T notBlank(T text, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notBlank(text, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出 {@link IllegalArgumentException} + * + *
+	 * Assert.notBlank(name);
+	 * 
+ * @param 字符串类型 + * @param text 被检查字符串 + * @return 非空字符串 + * @throws IllegalArgumentException 被检查字符串为空白 + */ + public static T notBlank(T text) throws IllegalArgumentException { + return notBlank(text, + "[Assertion failed] - this String argument must have text; it must not be null, empty, or blank"); + } + + /** + * 断言给定字符串是否不被另一个字符串包含(即是否为子串) 并使用指定的函数获取错误信息返回
+	 * Assert.notContain(name, "rod", ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return ");
+	 *  });
+	 * 
+ * @param 字符串类型 + * @param 异常类型 + * @param textToSearch 被搜索的字符串 + * @param substring 被检查的子串 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 被检查的子串 + * @throws X 非子串抛出异常 + */ + public static T notContain(CharSequence textToSearch, T substring, + Supplier errorSupplier) throws X { + if (null != textToSearch && null != substring && textToSearch.toString().contains(substring)) { + throw errorSupplier.get(); + } + return substring; + } + + /** + * 断言给定字符串是否不被另一个字符串包含(即是否为子串) + * + *
+	 * Assert.notContain(name, "rod", "Name must not contain 'rod'");
+	 * 
+ * @param textToSearch 被搜索的字符串 + * @param substring 被检查的子串 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 被检查的子串 + * @throws IllegalArgumentException 非子串抛出异常 + */ + public static String notContain(String textToSearch, String substring, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notContain(textToSearch, substring, + () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言给定字符串是否不被另一个字符串包含(即是否为子串) + * + *
+	 * Assert.notContain(name, "rod");
+	 * 
+ * @param textToSearch 被搜索的字符串 + * @param substring 被检查的子串 + * @return 被检查的子串 + * @throws IllegalArgumentException 非子串抛出异常 + */ + public static String notContain(String textToSearch, String substring) throws IllegalArgumentException { + return notContain(textToSearch, substring, + "[Assertion failed] - this String argument must not contain the substring [{}]", substring); + } + + /** + * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素 并使用指定的函数获取错误信息返回 + * + *
+	 * Assert.notEmpty(array, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 数组元素类型 + * @param 异常类型 + * @param array 被检查的数组 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 被检查的数组 + * @throws X if the object array is {@code null} or has no elements + */ + public static T[] notEmpty(T[] array, Supplier errorSupplier) throws X { + if (array == null || array.length == 0) { + throw errorSupplier.get(); + } + return array; + } + + /** + * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素 + * + *
+	 * Assert.notEmpty(array, "The array must have elements");
+	 * 
+ * @param 数组元素类型 + * @param array 被检查的数组 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 被检查的数组 + * @throws IllegalArgumentException if the object array is {@code null} or has no + * elements + */ + public static T[] notEmpty(T[] array, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notEmpty(array, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言给定数组是否包含元素,数组必须不为 {@code null} 且至少包含一个元素 + * + *
+	 * Assert.notEmpty(array, "The array must have elements");
+	 * 
+ * @param 数组元素类型 + * @param array 被检查的数组 + * @return 被检查的数组 + * @throws IllegalArgumentException if the object array is {@code null} or has no + * elements + */ + public static T[] notEmpty(T[] array) throws IllegalArgumentException { + return notEmpty(array, "[Assertion failed] - this array must not be empty: it must contain at least 1 element"); + } + + /** + * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含 并使用指定的函数获取错误信息返回 + *
+	 * Assert.noNullElements(array, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return ");
+	 *  });
+	 * 
+ * @param 数组元素类型 + * @param 异常类型 + * @param array 被检查的数组 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 被检查的数组 + * @throws X if the object array contains a {@code null} element + */ + public static T[] noNullElements(T[] array, Supplier errorSupplier) throws X { + if (null == array) { + throw errorSupplier.get(); + } + else if (null != array && array.length != 0) { + for (T element : array) { + if (null == element || element.equals(null)) { + throw errorSupplier.get(); + } + } + } + return array; + } + + /** + * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含 + * + *
+	 * Assert.noNullElements(array, "The array must not have null elements");
+	 * 
+ * @param 数组元素类型 + * @param array 被检查的数组 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 被检查的数组 + * @throws IllegalArgumentException if the object array contains a {@code null} + * element + */ + public static T[] noNullElements(T[] array, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return noNullElements(array, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含 + * + *
+	 * Assert.noNullElements(array);
+	 * 
+ * @param 数组元素类型 + * @param array 被检查的数组 + * @return 被检查的数组 + * @throws IllegalArgumentException if the object array contains a {@code null} + * element + */ + public static T[] noNullElements(T[] array) throws IllegalArgumentException { + return noNullElements(array, "[Assertion failed] - this array must not contain any null elements"); + } + + /** + * 断言给定集合非空 并使用指定的函数获取错误信息返回
+	 * Assert.notEmpty(collection, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param 集合元素类型 + * @param 集合类型 + * @param 异常类型 + * @param collection 被检查的集合 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 非空集合 + * @throws X if the collection is {@code null} or has no elements + */ + public static , X extends Throwable> T notEmpty(T collection, Supplier errorSupplier) + throws X { + if (null == collection || null == collection.iterator() || !collection.iterator().hasNext()) { + throw errorSupplier.get(); + } + return collection; + } + + /** + * 断言给定集合非空 + * + *
+	 * Assert.notEmpty(collection, "Collection must have elements");
+	 * 
+ * @param 集合元素类型 + * @param 集合类型 + * @param collection 被检查的集合 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 非空集合 + * @throws IllegalArgumentException if the collection is {@code null} or has no + * elements + */ + public static > T notEmpty(T collection, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notEmpty(collection, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言给定集合非空 + * + *
+	 * Assert.notEmpty(collection);
+	 * 
+ * @param 集合元素类型 + * @param 集合类型 + * @param collection 被检查的集合 + * @return 被检查集合 + * @throws IllegalArgumentException if the collection is {@code null} or has no + * elements + */ + public static > T notEmpty(T collection) throws IllegalArgumentException { + return notEmpty(collection, + "[Assertion failed] - this collection must not be empty: it must contain at least 1 element"); + } + + /** + * 断言给定Map非空 并使用指定的函数获取错误信息返回
+	 * Assert.notEmpty(map, ()->{
+	 *      // to query relation message
+	 *      return new IllegalArgumentException("relation message to return");
+	 *  });
+	 * 
+ * @param Key类型 + * @param Value类型 + * @param Map类型 + * @param 异常类型 + * @param map 被检查的Map + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 被检查的Map + * @throws X if the map is {@code null} or has no entries + */ + public static , X extends Throwable> T notEmpty(T map, Supplier errorSupplier) + throws X { + if (null == map || map.isEmpty()) { + throw errorSupplier.get(); + } + return map; + } + + /** + * 断言给定Map非空 + * + *
+	 * Assert.notEmpty(map, "Map must have entries");
+	 * 
+ * @param Key类型 + * @param Value类型 + * @param Map类型 + * @param map 被检查的Map + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 被检查的Map + * @throws IllegalArgumentException if the map is {@code null} or has no entries + */ + public static > T notEmpty(T map, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + return notEmpty(map, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言给定Map非空 + * + *
+	 * Assert.notEmpty(map, "Map must have entries");
+	 * 
+ * @param Key类型 + * @param Value类型 + * @param Map类型 + * @param map 被检查的Map + * @return 被检查的Map + * @throws IllegalArgumentException if the map is {@code null} or has no entries + */ + public static > T notEmpty(T map) throws IllegalArgumentException { + return notEmpty(map, "[Assertion failed] - this map must not be empty; it must contain at least one entry"); + } + + /** + * 断言给定对象是否是给定类的实例 + * + *
+	 * Assert.instanceOf(Foo.class, foo);
+	 * 
+ * @param 被检查对象泛型类型 + * @param type 被检查对象匹配的类型 + * @param obj 被检查对象 + * @return 被检查的对象 + * @throws IllegalArgumentException if the object is not an instance of clazz + * @see Class#isInstance(Object) + */ + public static T isInstanceOf(Class type, T obj) { + return isInstanceOf(type, obj, "Object [{}] is not instanceof [{}]", obj, type); + } + + /** + * 断言给定对象是否是给定类的实例 + * + *
+	 * Assert.instanceOf(Foo.class, foo, "foo must be an instance of class Foo");
+	 * 
+ * @param 被检查对象泛型类型 + * @param type 被检查对象匹配的类型 + * @param obj 被检查对象 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 被检查对象 + * @throws IllegalArgumentException if the object is not an instance of clazz + * @see Class#isInstance(Object) + */ + public static T isInstanceOf(Class type, T obj, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + notNull(type, "Type to check against must not be null"); + if (!type.isInstance(obj)) { + throw new IllegalArgumentException(format(errorMsgTemplate, params)); + } + return obj; + } + + /** + * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}. + * + *
+	 * Assert.isAssignable(Number.class, myClass);
+	 * 
+ * @param superType 需要检查的父类或接口 + * @param subType 需要检查的子类 + * @throws IllegalArgumentException 如果子类非继承父类,抛出此异常 + */ + public static void isAssignable(Class superType, Class subType) throws IllegalArgumentException { + isAssignable(superType, subType, "{} is not assignable to {})", subType, superType); + } + + /** + * 断言 {@code superType.isAssignableFrom(subType)} 是否为 {@code true}. + * + *
+	 * Assert.isAssignable(Number.class, myClass, "myClass must can be assignable to class Number");
+	 * 
+ * @param superType 需要检查的父类或接口 + * @param subType 需要检查的子类 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @throws IllegalArgumentException 如果子类非继承父类,抛出此异常 + */ + public static void isAssignable(Class superType, Class subType, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + notNull(superType, "Type to check against must not be null"); + if (subType == null || !superType.isAssignableFrom(subType)) { + throw new IllegalArgumentException(format(errorMsgTemplate, params)); + } + } + + /** + * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 并使用指定的函数获取错误信息返回 + *
+	 * Assert.state(id == null, ()->{
+	 *      // to query relation message
+	 *      return "relation message to return ";
+	 *  });
+	 * 
+ * @param expression boolean 表达式 + * @param errorMsgSupplier 错误抛出异常附带的消息生产接口 + * @throws IllegalStateException 表达式为 {@code false} 抛出此异常 + */ + public static void state(boolean expression, Supplier errorMsgSupplier) throws IllegalStateException { + if (!expression) { + throw new IllegalStateException(errorMsgSupplier.get()); + } + } + + /** + * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 + * + *
+	 * Assert.state(id == null, "The id property must not already be initialized");
+	 * 
+ * @param expression boolean 表达式 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @throws IllegalStateException 表达式为 {@code false} 抛出此异常 + */ + public static void state(boolean expression, String errorMsgTemplate, Object... params) + throws IllegalStateException { + if (!expression) { + throw new IllegalStateException(format(errorMsgTemplate, params)); + } + } + + /** + * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。 + * + *
+	 * Assert.state(id == null);
+	 * 
+ * @param expression boolean 表达式 + * @throws IllegalStateException 表达式为 {@code false} 抛出此异常 + */ + public static void state(boolean expression) throws IllegalStateException { + state(expression, "[Assertion failed] - this state invariant must be true"); + } + + /** + * 检查下标(数组、集合、字符串)是否符合要求,下标必须满足: + * + *
+	 * 0 ≤ index < size
+	 * 
+ * @param index 下标 + * @param size 长度 + * @return 检查后的下标 + * @throws IllegalArgumentException 如果size < 0 抛出此异常 + * @throws IndexOutOfBoundsException 如果index < 0或者 index ≥ size 抛出此异常 + */ + public static int checkIndex(int index, int size) throws IllegalArgumentException, IndexOutOfBoundsException { + return checkIndex(index, size, "[Assertion failed]"); + } + + /** + * 检查下标(数组、集合、字符串)是否符合要求,下标必须满足: + * + *
+	 * 0 ≤ index < size
+	 * 
+ * @param index 下标 + * @param size 长度 + * @param errorMsgTemplate 异常时的消息模板 + * @param params 参数列表 + * @return 检查后的下标 + * @throws IllegalArgumentException 如果size < 0 抛出此异常 + * @throws IndexOutOfBoundsException 如果index < 0或者 index ≥ size 抛出此异常 + */ + public static int checkIndex(int index, int size, String errorMsgTemplate, Object... params) + throws IllegalArgumentException, IndexOutOfBoundsException { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(badIndexMsg(index, size, errorMsgTemplate, params)); + } + return index; + } + + /** + * 检查值是否在指定范围内 + * @param 异常类型 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 经过检查后的值 + * @throws X if value is out of bound + */ + public static int checkBetween(int value, int min, int max, + Supplier errorSupplier) throws X { + if (value < min || value > max) { + throw errorSupplier.get(); + } + + return value; + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc" + * @param params 异常信息参数,用于替换"{}"占位符 + * @return 经过检查后的值 + */ + public static int checkBetween(int value, int min, int max, String errorMsgTemplate, Object... params) { + return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @return 检查后的长度值 + */ + public static int checkBetween(int value, int min, int max) { + return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max); + } + + /** + * 检查值是否在指定范围内 + * @param 异常类型 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 经过检查后的值 + * @throws X if value is out of bound + */ + public static long checkBetween(long value, long min, long max, + Supplier errorSupplier) throws X { + if (value < min || value > max) { + throw errorSupplier.get(); + } + + return value; + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc" + * @param params 异常信息参数,用于替换"{}"占位符 + * @return 经过检查后的值 + */ + public static long checkBetween(long value, long min, long max, String errorMsgTemplate, Object... params) { + return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @return 检查后的长度值 + */ + public static long checkBetween(long value, long min, long max) { + return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max); + } + + /** + * 检查值是否在指定范围内 + * @param 异常类型 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @return 经过检查后的值 + * @throws X if value is out of bound + */ + public static double checkBetween(double value, double min, double max, + Supplier errorSupplier) throws X { + if (value < min || value > max) { + throw errorSupplier.get(); + } + + return value; + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc" + * @param params 异常信息参数,用于替换"{}"占位符 + * @return 经过检查后的值 + */ + public static double checkBetween(double value, double min, double max, String errorMsgTemplate, Object... params) { + return checkBetween(value, min, max, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @return 检查后的长度值 + */ + public static double checkBetween(double value, double min, double max) { + return checkBetween(value, min, max, TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max); + } + + /** + * 检查值是否在指定范围内 + * @param value 值 + * @param min 最小值(包含) + * @param max 最大值(包含) + * @return 检查后的长度值 + */ + public static Number checkBetween(Number value, Number min, Number max) { + notNull(value); + notNull(min); + notNull(max); + double valueDouble = value.doubleValue(); + double minDouble = min.doubleValue(); + double maxDouble = max.doubleValue(); + if (valueDouble < minDouble || valueDouble > maxDouble) { + throw new IllegalArgumentException(format(TEMPLATE_VALUE_MUST_BE_BETWEEN_AND, min, max)); + } + return value; + } + + /** + * 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
+	 *   Assert.notEquals(obj1,obj2);
+	 * 
+ * @param obj1 对象1 + * @param obj2 对象2 + * @throws IllegalArgumentException obj1 must be not equals obj2 + */ + public static void notEquals(Object obj1, Object obj2) { + notEquals(obj1, obj2, "({}) must be not equals ({})", obj1, obj2); + } + + /** + * 断言两个对象是否不相等,如果两个对象相等 抛出IllegalArgumentException 异常
+	 *   Assert.notEquals(obj1,obj2,"obj1 must be not equals obj2");
+	 * 
+ * @param obj1 对象1 + * @param obj2 对象2 + * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc" + * @param params 异常信息参数,用于替换"{}"占位符 + * @throws IllegalArgumentException obj1 must be not equals obj2 + */ + public static void notEquals(Object obj1, Object obj2, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + notEquals(obj1, obj2, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言两个对象是否不相等,如果两个对象相等,抛出指定类型异常,并使用指定的函数获取错误信息返回 + * @param obj1 对象1 + * @param obj2 对象2 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @param 异常类型 + * @throws X obj1 must be not equals obj2 + */ + public static void notEquals(Object obj1, Object obj2, Supplier errorSupplier) throws X { + if (objectEquals(obj1, obj2)) { + throw errorSupplier.get(); + } + } + // ----------------------------------------------------------------------------------------------------------- + // Check not equals + + /** + * 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
+	 *   Assert.isEquals(obj1,obj2);
+	 * 
+ * @param obj1 对象1 + * @param obj2 对象2 + * @throws IllegalArgumentException obj1 must be equals obj2 + */ + public static void equals(Object obj1, Object obj2) { + equals(obj1, obj2, "({}) must be equals ({})", obj1, obj2); + } + + /** + * 断言两个对象是否相等,如果两个对象不相等 抛出IllegalArgumentException 异常
+	 *   Assert.isEquals(obj1,obj2,"obj1 must be equals obj2");
+	 * 
+ * @param obj1 对象1 + * @param obj2 对象2 + * @param errorMsgTemplate 异常信息模板,类似于"aa{}bb{}cc" + * @param params 异常信息参数,用于替换"{}"占位符 + * @throws IllegalArgumentException obj1 must be equals obj2 + */ + public static void equals(Object obj1, Object obj2, String errorMsgTemplate, Object... params) + throws IllegalArgumentException { + equals(obj1, obj2, () -> new IllegalArgumentException(format(errorMsgTemplate, params))); + } + + /** + * 断言两个对象是否相等,如果两个对象不相等,抛出指定类型异常,并使用指定的函数获取错误信息返回 + * @param obj1 对象1 + * @param obj2 对象2 + * @param errorSupplier 错误抛出异常附带的消息生产接口 + * @param 异常类型 + * @throws X obj1 must be equals obj2 + */ + public static void equals(Object obj1, Object obj2, Supplier errorSupplier) throws X { + if (!objectEquals(obj1, obj2)) { + throw errorSupplier.get(); + } + } + + // ----------------------------------------------------------------------------------------------------------- + // Check is equals + + // -------------------------------------------------------------------------------------------------------------------------------------------- + // Private method start + + /** + * 错误的下标时显示的消息 + * @param index 下标 + * @param size 长度 + * @param desc 异常时的消息模板 + * @param params 参数列表 + * @return 消息 + */ + private static String badIndexMsg(int index, int size, String desc, Object... params) { + if (index < 0) { + return format("{} ({}) must not be negative", format(desc, params), index); + } + else if (size < 0) { + throw new IllegalArgumentException("negative size: " + size); + } + else { // index >= size + return format("{} ({}) must be less than size ({})", format(desc, params), index, size); + } + + } + + /** + * 对象相等判断 + * @param obj1 对象1 + * @param obj2 对象2 + * @return 是否相等 + */ + private static boolean objectEquals(Object obj1, Object obj2) { + if (obj1 instanceof BigDecimal && obj2 instanceof BigDecimal) { + if (obj1 == obj2) { + return true; + } + if (obj1 == null || obj2 == null) { + return false; + } + return 0 == ((BigDecimal) obj1).compareTo((BigDecimal) obj2); + } + return Objects.equals(obj1, obj2); + } + + /** + * 根据占位符模版+参数输出字符串 + * @param template 占位符模版 + * @param args 参数 + * @return 字符串 + */ + private static String format(String template, Object... args) { + int i = 0; + while (template.contains("{}")) { + template = template.replaceFirst(Pattern.quote("{}"), "{" + i++ + "}"); + } + return MessageFormat.format(template, args); + } + // -------------------------------------------------------------------------------------------------------------------------------------------- + // Private method end + }