This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-lang.git


The following commit(s) were added to refs/heads/master by this push:
     new 2188eb0e2 Add Validate.isTrue(boolean, Supplier<String>)
2188eb0e2 is described below

commit 2188eb0e2e15431b7c4a65f7168392c888f0ecd1
Author: Gary Gregory <garydgreg...@gmail.com>
AuthorDate: Tue Jan 28 10:24:07 2025 -0500

    Add Validate.isTrue(boolean, Supplier<String>)
    
    Don't call TypeUtils.toString(Type) on every array item in
    TypeUtils.parameterize[WithOwner](Type, Class<?>, Map<TypeVariable<?>,
    Type>) unless required
---
 src/changes/changes.xml                            |  2 ++
 .../java/org/apache/commons/lang3/Validate.java    | 26 ++++++++++++++++++++++
 .../apache/commons/lang3/reflect/TypeUtils.java    |  2 +-
 .../org/apache/commons/lang3/ValidateTest.java     | 16 +++++++++++++
 4 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index f9e0f4ea2..960c6a407 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -78,6 +78,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">Fix Spotbugs [ERROR] Medium: The field 
org.apache.commons.lang3.builder.DiffBuilder$SDiff.leftSupplier is transient 
but isn't set by deserialization 
[org.apache.commons.lang3.builder.DiffBuilder$SDiff] In DiffBuilder.java 
SE_TRANSIENT_FIELD_NOT_RESTORED.</action>
     <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">Fix Spotbugs [ERROR] Medium: The field 
org.apache.commons.lang3.builder.DiffBuilder$SDiff.rightSupplier is transient 
but isn't set by deserialization 
[org.apache.commons.lang3.builder.DiffBuilder$SDiff] In DiffBuilder.java 
SE_TRANSIENT_FIELD_NOT_RESTORED.</action>
     <action issue="LANG-1762" type="fix" dev="ggregory" due-to="Alonso 
Gonzalez, Gary Gregory">StopWatch methods should not delegate to deprecated 
methods.</action>
+    <action                   type="fix" dev="ggregory" due-to="Gary 
Gregory">Don't call TypeUtils.toString(Type) on every array item in 
TypeUtils.parameterize[WithOwner](Type, Class, Map, Type>) unless 
required.</action>
     <!-- ADD -->
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add Strings and refactor StringUtils.</action>
     <action issue="LANG-1747" type="add" dev="ggregory" due-to="Oliver B. 
Fischer, Gary Gregory">Add StopWatch.run([Failable]Runnable) and 
get([Failable]Supplier).</action>
@@ -96,6 +97,7 @@ The <action> type attribute can be add,update,fix,remove.
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add RegExUtils methods typed to CharSequence input and deprecate old 
versions typed to String.</action>
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add IterableStringTokenizer.</action>
     <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add FailableIntToFloatFunction.</action>
+    <action                   type="add" dev="ggregory" due-to="Gary 
Gregory">Add Validate.isTrue(boolean, Supplier&lt;String&gt;).</action>
     <!-- UPDATE -->
     <action                   type="update" dev="ggregory" due-to="Gary 
Gregory, Dependabot">Bump org.apache.commons:commons-parent from 73 to 79 
#1267, #1277, #1283, #1288, #1302.</action>
     <action                   type="update" dev="ggregory" due-to="Gary 
Gregory, Dependabot">[site] Bump org.codehaus.mojo:taglist-maven-plugin from 
3.1.0 to 3.2.1 #1300.</action>
diff --git a/src/main/java/org/apache/commons/lang3/Validate.java 
b/src/main/java/org/apache/commons/lang3/Validate.java
index 5f88e6ddc..51743d8ac 100644
--- a/src/main/java/org/apache/commons/lang3/Validate.java
+++ b/src/main/java/org/apache/commons/lang3/Validate.java
@@ -493,6 +493,7 @@ public static void isInstanceOf(final Class<?> type, final 
Object obj, final Str
      * @see #isTrue(boolean, String, long)
      * @see #isTrue(boolean, String, double)
      * @see #isTrue(boolean, String, Object...)
+     * @see #isTrue(boolean, Supplier)
      */
     public static void isTrue(final boolean expression) {
         if (!expression) {
@@ -518,6 +519,7 @@ public static void isTrue(final boolean expression) {
      * @see #isTrue(boolean)
      * @see #isTrue(boolean, String, long)
      * @see #isTrue(boolean, String, Object...)
+     * @see #isTrue(boolean, Supplier)
      */
     public static void isTrue(final boolean expression, final String message, 
final double value) {
         if (!expression) {
@@ -543,6 +545,7 @@ public static void isTrue(final boolean expression, final 
String message, final
      * @see #isTrue(boolean)
      * @see #isTrue(boolean, String, double)
      * @see #isTrue(boolean, String, Object...)
+     * @see #isTrue(boolean, Supplier)
      */
     public static void isTrue(final boolean expression, final String message, 
final long value) {
         if (!expression) {
@@ -566,6 +569,7 @@ public static void isTrue(final boolean expression, final 
String message, final
      * @see #isTrue(boolean)
      * @see #isTrue(boolean, String, long)
      * @see #isTrue(boolean, String, double)
+     * @see #isTrue(boolean, Supplier)
      */
     public static void isTrue(final boolean expression, final String message, 
final Object... values) {
         if (!expression) {
@@ -573,6 +577,28 @@ public static void isTrue(final boolean expression, final 
String message, final
         }
     }
 
+    /**
+     * Validate that the argument condition is {@code true}; otherwise 
throwing an exception with the specified message. This method is useful when 
validating
+     * according to an arbitrary boolean expression, such as validating a 
primitive number or using your own custom validation expression.
+     *
+     * <pre>{@code
+     * Validate.isTrue(i >= min && i <= max, "The value must be between %d and 
%d", min, max);
+     * }</pre>
+     *
+     * @param expression      the boolean expression to check
+     * @param messageSupplier the exception message supplier
+     * @throws IllegalArgumentException if expression is {@code false}
+     * @see #isTrue(boolean)
+     * @see #isTrue(boolean, String, long)
+     * @see #isTrue(boolean, String, double)
+     * @since 3.18.0
+     */
+    public static void isTrue(final boolean expression, final Supplier<String> 
messageSupplier) {
+        if (!expression) {
+            throw new IllegalArgumentException(messageSupplier.get());
+        }
+    }
+
     /**
      * Validate that the specified argument character sequence matches the 
specified regular
      * expression pattern; otherwise throwing an exception.
diff --git a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java 
b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
index e864c8624..3cdc9c119 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
@@ -553,7 +553,7 @@ private static Type[] extractTypeArgumentsFrom(final 
Map<TypeVariable<?>, Type>
         final Type[] result = new Type[variables.length];
         int index = 0;
         for (final TypeVariable<?> var : variables) {
-            Validate.isTrue(mappings.containsKey(var), "missing argument 
mapping for %s", toString(var));
+            Validate.isTrue(mappings.containsKey(var), () -> 
String.format("missing argument mapping for %s", toString(var)));
             result[index++] = mappings.get(var);
         }
         return result;
diff --git a/src/test/java/org/apache/commons/lang3/ValidateTest.java 
b/src/test/java/org/apache/commons/lang3/ValidateTest.java
index 28877f99d..a1b9080fc 100644
--- a/src/test/java/org/apache/commons/lang3/ValidateTest.java
+++ b/src/test/java/org/apache/commons/lang3/ValidateTest.java
@@ -742,6 +742,22 @@ void 
shouldThrowExceptionWithDoubleInsertedIntoTemplateMessageForFalseExpression
             }
         }
 
+        @Nested
+        final class WithMessageSupplier {
+
+            @Test
+            void shouldNotThrowForTrueExpression() {
+                Validate.isTrue(true, () -> "MSG");
+            }
+
+            @Test
+            void 
shouldThrowExceptionWithDoubleInsertedIntoTemplateMessageForFalseExpression() {
+                final IllegalArgumentException ex = 
assertThrows(IllegalArgumentException.class,
+                    () -> Validate.isTrue(false, () -> String.format("MSG %s 
%s", "Object 1", "Object 2")));
+                assertEquals("MSG Object 1 Object 2", ex.getMessage());
+            }
+        }
+
         @Nested
         final class WithoutMessage {
 

Reply via email to