This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new 024909ddc New juneau-bct module
024909ddc is described below
commit 024909ddcd729e9e856b0b193827304d1de05587
Author: James Bognar <[email protected]>
AuthorDate: Fri Sep 12 15:28:59 2025 -0400
New juneau-bct module
---
build-and-push.sh | 68 +++++++
juneau-core/juneau-bct/.gitignore | 6 +
{juneau-utest => juneau-core/juneau-bct}/pom.xml | 85 +-------
.../org/apache/juneau/junit/bct/AssertionArgs.java | 0
.../juneau/junit/bct/BasicBeanConverter.java | 0
.../org/apache/juneau/junit/bct/BctAssertions.java | 0
.../org/apache/juneau/junit/bct/BeanConverter.java | 0
.../org/apache/juneau/junit/bct/Listifier.java | 0
.../org/apache/juneau/junit/bct/Listifiers.java | 0
.../apache/juneau/junit/bct/NestedTokenizer.java | 0
.../apache/juneau/junit/bct/PropertyExtractor.java | 0
.../juneau/junit/bct/PropertyExtractors.java | 0
.../junit/bct/PropertyNotFoundException.java | 0
.../org/apache/juneau/junit/bct/Stringifier.java | 0
.../org/apache/juneau/junit/bct/Stringifiers.java | 0
.../java/org/apache/juneau/junit/bct/Swapper.java | 0
.../java/org/apache/juneau/junit/bct/Swappers.java | 0
.../apache/juneau/junit/bct/ThrowingSupplier.java | 0
.../java/org/apache/juneau/junit/bct/Utils.java | 0
.../org/apache/juneau/junit/bct/package-info.java | 221 +++++++++++++++++++++
.../apache/juneau/common/internal/StringUtils.java | 20 +-
.../juneau/common/internal/ThrowingSupplier.java | 7 +
.../org/apache/juneau/common/internal/Utils.java | 190 ++++++++++++++----
juneau-core/pom.xml | 1 +
juneau-utest/pom.xml | 5 +
25 files changed, 486 insertions(+), 117 deletions(-)
diff --git a/build-and-push.sh b/build-and-push.sh
new file mode 100755
index 000000000..56657be0d
--- /dev/null
+++ b/build-and-push.sh
@@ -0,0 +1,68 @@
+#!/bin/bash
+#
***************************************************************************************************************************
+# * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+# * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+# * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+# * with the License. You may obtain a copy of the License at
*
+# *
*
+# * http://www.apache.org/licenses/LICENSE-2.0
*
+# *
*
+# * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+# * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+# * specific language governing permissions and limitations under the License.
*
+#
***************************************************************************************************************************
+
+# Build and Push Script for Juneau
+# Usage: ./build-and-push.sh "commit message"
+
+set -e # Exit immediately if a command exits with a non-zero status
+
+# Check if commit message is provided
+if [ -z "$1" ]; then
+ echo "โ Error: Commit message is required"
+ echo "Usage: $0 \"commit message\""
+ exit 1
+fi
+
+COMMIT_MESSAGE="$1"
+
+echo "๐ Starting build and push process..."
+
+echo "๐งช Step 1: Running tests..."
+if ! mvn test; then
+ echo "โ Step 1 FAILED: Tests failed! Aborting build process."
+ exit 1
+fi
+echo "โ
Step 1: All tests passed."
+
+echo "๐๏ธ Step 2: Building and installing project..."
+if ! mvn clean package install; then
+ echo "โ Step 2 FAILED: Build failed! Aborting."
+ exit 1
+fi
+echo "โ
Step 2: Build and install completed."
+
+echo "๐ Step 3: Generating Javadocs..."
+if ! mvn javadoc:javadoc; then
+ echo "โ Step 3 FAILED: Javadoc generation failed! Aborting."
+ exit 1
+fi
+echo "โ
Step 3: Javadoc generation completed."
+
+echo "๐ Step 4: Committing changes to Git..."
+git add .
+if ! git commit -m "$COMMIT_MESSAGE"; then
+ echo "โ Step 4 FAILED: Git commit failed! Aborting."
+ exit 1
+fi
+echo "โ
Step 4: Git commit completed."
+
+echo "๐ Step 5: Pushing changes to remote repository..."
+if ! git push; then
+ echo "โ Step 5 FAILED: Git push failed!"
+ exit 1
+fi
+echo "โ
Step 5: Git push completed."
+
+echo "๐ All operations completed successfully!"
+echo "๐ฆ Commit message: $COMMIT_MESSAGE"
diff --git a/juneau-core/juneau-bct/.gitignore
b/juneau-core/juneau-bct/.gitignore
new file mode 100644
index 000000000..34acf885c
--- /dev/null
+++ b/juneau-core/juneau-bct/.gitignore
@@ -0,0 +1,6 @@
+/target/
+**/.DS_Store
+.classpath
+.project
+/.settings/
+/bin/
diff --git a/juneau-utest/pom.xml b/juneau-core/juneau-bct/pom.xml
similarity index 58%
copy from juneau-utest/pom.xml
copy to juneau-core/juneau-bct/pom.xml
index 9b6d38505..567dc2d1e 100644
--- a/juneau-utest/pom.xml
+++ b/juneau-core/juneau-bct/pom.xml
@@ -19,85 +19,29 @@
<parent>
<groupId>org.apache.juneau</groupId>
- <artifactId>juneau</artifactId>
+ <artifactId>juneau-core</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
- <artifactId>juneau-utest</artifactId>
- <name>juneau/utest</name>
- <description>Apache Juneau Core API Unit Tests</description>
+ <artifactId>juneau-bct</artifactId>
+ <name>juneau/core/bct</name>
+ <description>Apache Juneau Bean-Centric Testing API</description>
<packaging>bundle</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <!-- Skip javadoc generation since we generate them in the
aggregate pom -->
- <maven.javadoc.skip>true</maven.javadoc.skip>
</properties>
<dependencies>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-marshall</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-config</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-bean-atom</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-bean-common</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-bean-html5</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-bean-jsonschema</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-bean-openapi3</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.juneau</groupId>
- <artifactId>juneau-rest-mock</artifactId>
- <version>${project.version}</version>
- </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.13.4</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.opentest4j</groupId>
<artifactId>opentest4j</artifactId>
<version>1.3.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.openjdk.jmh</groupId>
- <artifactId>jmh-core</artifactId>
- <version>1.36</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.openjdk.jmh</groupId>
- <artifactId>jmh-generator-annprocess</artifactId>
- <version>1.36</version>
- <scope>test</scope>
</dependency>
</dependencies>
@@ -109,7 +53,7 @@
<extensions>true</extensions>
<configuration>
<instructions>
-
<Automatic-Module-Name>org.apache.juneau.core.test</Automatic-Module-Name>
+
<Automatic-Module-Name>org.apache.juneau.assertions</Automatic-Module-Name>
</instructions>
</configuration>
</plugin>
@@ -129,25 +73,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <includes>
-
<include>**/*Test.class</include>
- </includes>
- <systemPropertyVariables>
-
<java.locale.providers>JRE,COMPAT,SPI,CLDR</java.locale.providers>
- </systemPropertyVariables>
- </configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/AssertionArgs.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/AssertionArgs.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/AssertionArgs.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/AssertionArgs.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BasicBeanConverter.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BasicBeanConverter.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/BasicBeanConverter.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BasicBeanConverter.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BctAssertions.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctAssertions.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/BctAssertions.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BctAssertions.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/BeanConverter.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BeanConverter.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/BeanConverter.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/BeanConverter.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Listifier.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Listifier.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/Listifier.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Listifier.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Listifiers.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Listifiers.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/Listifiers.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Listifiers.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/NestedTokenizer.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/NestedTokenizer.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/NestedTokenizer.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/NestedTokenizer.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyExtractor.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyExtractor.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyExtractor.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyExtractor.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyExtractors.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyExtractors.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyExtractors.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyExtractors.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyNotFoundException.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyNotFoundException.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/PropertyNotFoundException.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/PropertyNotFoundException.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Stringifier.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Stringifier.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/Stringifier.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Stringifier.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Stringifiers.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Stringifiers.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/Stringifiers.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Stringifiers.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Swapper.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Swapper.java
similarity index 100%
rename from juneau-utest/src/test/java/org/apache/juneau/junit/bct/Swapper.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Swapper.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Swappers.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Swappers.java
similarity index 100%
rename from juneau-utest/src/test/java/org/apache/juneau/junit/bct/Swappers.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Swappers.java
diff --git
a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/ThrowingSupplier.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/ThrowingSupplier.java
similarity index 100%
rename from
juneau-utest/src/test/java/org/apache/juneau/junit/bct/ThrowingSupplier.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/ThrowingSupplier.java
diff --git a/juneau-utest/src/test/java/org/apache/juneau/junit/bct/Utils.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Utils.java
similarity index 100%
rename from juneau-utest/src/test/java/org/apache/juneau/junit/bct/Utils.java
rename to
juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/Utils.java
diff --git
a/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/package-info.java
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/package-info.java
new file mode 100644
index 000000000..15d49b289
--- /dev/null
+++
b/juneau-core/juneau-bct/src/main/java/org/apache/juneau/junit/bct/package-info.java
@@ -0,0 +1,221 @@
+//
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+// * with the License. You may obtain a copy of the License at
*
+// *
*
+// * http://www.apache.org/licenses/LICENSE-2.0
*
+// *
*
+// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+// * specific language governing permissions and limitations under the
License. *
+//
***************************************************************************************************************************
+
+/**
+ * Bean-Centric Testing Framework.
+ *
+ * <p>This package provides a comprehensive testing framework that extends
JUnit with streamlined assertion methods
+ * for Java objects. The Bean-Centric Testing (BCT) framework eliminates
verbose test code while providing
+ * comprehensive object introspection and comparison capabilities.</p>
+ *
+ * <h5 class='section'>Key Features:</h5>
+ * <ul>
+ * <li><b>Concise Assertions:</b> Replace multiple lines of manual property
extraction with single assertion calls</li>
+ * <li><b>Powerful Property Access:</b> Nested objects, collections,
arrays, and maps with unified syntax</li>
+ * <li><b>Flexible Comparison:</b> Support for custom converters,
formatters, and comparison logic</li>
+ * <li><b>Type Safety:</b> Comprehensive error messages with clear property
paths</li>
+ * <li><b>Extensible:</b> Custom property extractors, stringifiers, and
conversion logic</li>
+ * </ul>
+ *
+ * <h5 class='section'>Core Classes:</h5>
+ * <ul>
+ * <li><b>{@link BctAssertions}:</b> Main assertion methods for BCT</li>
+ * <li><b>{@link BeanConverter}:</b> Interface for object conversion and
property access</li>
+ * <li><b>{@link BasicBeanConverter}:</b> Default implementation with
extensible type handlers</li>
+ * <li><b>{@link AssertionArgs}:</b> Configuration for assertions with
custom messages and converters</li>
+ * </ul>
+ *
+ * <h5 class='section'>Quick Start:</h5>
+ * <p class='bjava'>
+ * <jk>import static</jk> com.sfdc.junit.bct.BctAssertions.*;
+ *
+ * <ja>@Test</ja>
+ * <jk>void</jk> testUser() {
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Alice"</js>, 25,
<jk>true</jk>);
+ *
+ * <jc>// Test multiple properties at once</jc>
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"name,age,active"</js>,
<js>"Alice,25,true"</js>);
+ *
+ * <jc>// Test nested objects</jc>
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"address{street,city}"</js>,
<js>"{123 Main St,Springfield}"</js>);
+ * }
+ * </p>
+ *
+ * <h5 class='section'>Assertion Method Examples:</h5>
+ *
+ * <h6 class='figure'>1. {@link BctAssertions#assertBean(Object,String,String)
assertBean()}</h6>
+ * <p>Tests object properties with support for nested syntax and collection
iteration.</p>
+ * <p class='bjava'>
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Bob"</js>, 30);
+ * <jv>user</jv>.setAddress(<jk>new</jk> Address(<js>"456 Oak Ave"</js>,
<js>"Denver"</js>));
+ *
+ * <jc>// Test simple properties</jc>
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"name"</js>, <js>"Bob"</js>);
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"name,age"</js>,
<js>"Bob,30"</js>);
+ *
+ * <jc>// Test nested properties</jc>
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"address.street"</js>, <js>"456
Oak Ave"</js>);
+ * <jsm>assertBean</jsm>(<jv>user</jv>, <js>"address{street,city}"</js>,
<js>"{456 Oak Ave,Denver}"</js>);
+ * </p>
+ *
+ * <h6 class='figure'>2. {@link
BctAssertions#assertBeans(Object,String,String...) assertBeans()}</h6>
+ * <p>Tests collections of objects by extracting and comparing specific
fields.</p>
+ * <p class='bjava'>
+ * List<User> <jv>users</jv> = Arrays.<jsm>asList</jsm>(
+ * <jk>new</jk> User(<js>"Alice"</js>, 25),
+ * <jk>new</jk> User(<js>"Bob"</js>, 30),
+ * <jk>new</jk> User(<js>"Carol"</js>, 35)
+ * );
+ *
+ * <jc>// Test single field across collection</jc>
+ * <jsm>assertBeans</jsm>(<jv>users</jv>, <js>"name"</js>,
<js>"Alice"</js>, <js>"Bob"</js>, <js>"Carol"</js>);
+ *
+ * <jc>// Test multiple fields</jc>
+ * <jsm>assertBeans</jsm>(<jv>users</jv>, <js>"name,age"</js>,
<js>"Alice,25"</js>, <js>"Bob,30"</js>, <js>"Carol,35"</js>);
+ * </p>
+ *
+ * <h6 class='figure'>3. {@link
BctAssertions#assertMapped(Object,java.util.function.BiFunction,String,String)
assertMapped()}</h6>
+ * <p>Tests custom property access using BiFunction for non-standard
objects.</p>
+ * <p class='bjava'>
+ * Map<String,Object> <jv>data</jv> = <jk>new</jk> HashMap<>();
+ * <jv>data</jv>.put(<js>"name"</js>, <js>"Alice"</js>);
+ * <jv>data</jv>.put(<js>"score"</js>, 95);
+ *
+ * <jc>// Custom property extractor for Map objects</jc>
+ * <jsm>assertMapped</jsm>(<jv>data</jv>, (obj, key) -> obj.get(key),
<js>"name,score"</js>, <js>"Alice,95"</js>);
+ * </p>
+ *
+ * <h6 class='figure'>4. {@link BctAssertions#assertList(Object,Object...)
assertList()}</h6>
+ * <p>Tests list/collection elements with varargs for expected values.</p>
+ * <p class='bjava'>
+ * List<String> <jv>names</jv> =
Arrays.<jsm>asList</jsm>(<js>"Alice"</js>, <js>"Bob"</js>, <js>"Carol"</js>);
+ * String[] <jv>colors</jv> = {<js>"red"</js>, <js>"green"</js>,
<js>"blue"</js>};
+ *
+ * <jc>// Test list contents</jc>
+ * <jsm>assertList</jsm>(<jv>names</jv>, <js>"Alice"</js>, <js>"Bob"</js>,
<js>"Carol"</js>);
+ * <jsm>assertList</jsm>(<jv>colors</jv>, <js>"red"</js>, <js>"green"</js>,
<js>"blue"</js>);
+ * </p>
+ *
+ * <h6 class='figure'>5. {@link BctAssertions#assertContains(String,Object)
assertContains()}</h6>
+ * <p>Tests that a string appears somewhere within the stringified object.</p>
+ * <p class='bjava'>
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Alice Smith"</js>, 25);
+ * List<String> <jv>items</jv> =
Arrays.<jsm>asList</jsm>(<js>"apple"</js>, <js>"banana"</js>,
<js>"cherry"</js>);
+ *
+ * <jc>// Test substring presence</jc>
+ * <jsm>assertContains</jsm>(<js>"Alice"</js>, <jv>user</jv>);
+ * <jsm>assertContains</jsm>(<js>"banana"</js>, <jv>items</jv>);
+ * </p>
+ *
+ * <h6 class='figure'>6. {@link
BctAssertions#assertContainsAll(Object,String...) assertContainsAll()}</h6>
+ * <p>Tests that all specified strings appear within the stringified
object.</p>
+ * <p class='bjava'>
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Alice Smith"</js>, 25);
+ * <jv>user</jv>.setEmail(<js>"[email protected]"</js>);
+ *
+ * <jc>// Test multiple substrings</jc>
+ * <jsm>assertContainsAll</jsm>(<jv>user</jv>, <js>"Alice"</js>,
<js>"Smith"</js>, <js>"25"</js>);
+ * <jsm>assertContainsAll</jsm>(<jv>user</jv>, <js>"alice"</js>,
<js>"example.com"</js>);
+ * </p>
+ *
+ * <h6 class='figure'>7. {@link BctAssertions#assertEmpty(Object)
assertEmpty()}</h6>
+ * <p>Tests that collections, arrays, maps, or strings are empty.</p>
+ * <p class='bjava'>
+ * List<String> <jv>emptyList</jv> = <jk>new</jk> ArrayList<>();
+ * String[] <jv>emptyArray</jv> = {};
+ * Map<String,String> <jv>emptyMap</jv> = <jk>new</jk>
HashMap<>();
+ * String <jv>emptyString</jv> = <js>""</js>;
+ *
+ * <jc>// Test empty collections</jc>
+ * <jsm>assertEmpty</jsm>(<jv>emptyList</jv>);
+ * <jsm>assertEmpty</jsm>(<jv>emptyArray</jv>);
+ * <jsm>assertEmpty</jsm>(<jv>emptyMap</jv>);
+ * <jsm>assertEmpty</jsm>(<jv>emptyString</jv>);
+ * </p>
+ *
+ * <h6 class='figure'>8. {@link BctAssertions#assertNotEmpty(Object)
assertNotEmpty()}</h6>
+ * <p>Tests that collections, arrays, maps, or strings are not empty.</p>
+ * <p class='bjava'>
+ * List<String> <jv>names</jv> =
Arrays.<jsm>asList</jsm>(<js>"Alice"</js>);
+ * String[] <jv>colors</jv> = {<js>"red"</js>};
+ * Map<String,String> <jv>config</jv> =
Map.<jsm>of</jsm>(<js>"key"</js>, <js>"value"</js>);
+ * String <jv>message</jv> = <js>"Hello"</js>;
+ *
+ * <jc>// Test non-empty collections</jc>
+ * <jsm>assertNotEmpty</jsm>(<jv>names</jv>);
+ * <jsm>assertNotEmpty</jsm>(<jv>colors</jv>);
+ * <jsm>assertNotEmpty</jsm>(<jv>config</jv>);
+ * <jsm>assertNotEmpty</jsm>(<jv>message</jv>);
+ * </p>
+ *
+ * <h6 class='figure'>9. {@link BctAssertions#assertSize(int,Object)
assertSize()}</h6>
+ * <p>Tests the size/length of collections, arrays, maps, or strings.</p>
+ * <p class='bjava'>
+ * List<String> <jv>names</jv> =
Arrays.<jsm>asList</jsm>(<js>"Alice"</js>, <js>"Bob"</js>, <js>"Carol"</js>);
+ * String[] <jv>colors</jv> = {<js>"red"</js>, <js>"green"</js>};
+ * Map<String,Integer> <jv>scores</jv> =
Map.<jsm>of</jsm>(<js>"Alice"</js>, 95, <js>"Bob"</js>, 87);
+ * String <jv>message</jv> = <js>"Hello"</js>;
+ *
+ * <jc>// Test collection sizes</jc>
+ * <jsm>assertSize</jsm>(3, <jv>names</jv>);
+ * <jsm>assertSize</jsm>(2, <jv>colors</jv>);
+ * <jsm>assertSize</jsm>(2, <jv>scores</jv>);
+ * <jsm>assertSize</jsm>(5, <jv>message</jv>);
+ * </p>
+ *
+ * <h6 class='figure'>10. {@link BctAssertions#assertString(String,Object)
assertString()}</h6>
+ * <p>Tests the string representation of an object using the configured
converter.</p>
+ * <p class='bjava'>
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Alice"</js>, 25);
+ * List<Integer> <jv>numbers</jv> = Arrays.<jsm>asList</jsm>(1, 2, 3);
+ * Date <jv>date</jv> = <jk>new</jk> Date(1609459200000L); <jc>//
2021-01-01</jc>
+ *
+ * <jc>// Test string representations</jc>
+ * <jsm>assertString</jsm>(<js>"User(name=Alice, age=25)"</js>,
<jv>user</jv>);
+ * <jsm>assertString</jsm>(<js>"[1, 2, 3]"</js>, <jv>numbers</jv>);
+ * <jsm>assertString</jsm>(<js>"2021-01-01"</js>, <jv>date</jv>);
+ * </p>
+ *
+ * <h6 class='figure'>11. {@link
BctAssertions#assertMatchesGlob(String,Object) assertMatchesGlob()}</h6>
+ * <p>Tests that the stringified object matches a glob-style pattern (* and ?
wildcards).</p>
+ * <p class='bjava'>
+ * User <jv>user</jv> = <jk>new</jk> User(<js>"Alice Smith"</js>, 25);
+ * String <jv>filename</jv> = <js>"report.pdf"</js>;
+ * String <jv>email</jv> = <js>"[email protected]"</js>;
+ *
+ * <jc>// Test pattern matching</jc>
+ * <jsm>assertMatchesGlob</jsm>(<js>"*Alice*"</js>, <jv>user</jv>);
+ * <jsm>assertMatchesGlob</jsm>(<js>"*.pdf"</js>, <jv>filename</jv>);
+ * <jsm>assertMatchesGlob</jsm>(<js>"*@*.com"</js>, <jv>email</jv>);
+ * <jsm>assertMatchesGlob</jsm>(<js>"User(name=Alice*, age=25)"</js>,
<jv>user</jv>);
+ * </p>
+ *
+ * <h5 class='section'>Custom Configuration with {@link AssertionArgs}:</h5>
+ * <p>All assertion methods support custom configuration through {@link
AssertionArgs}:</p>
+ * <p class='bjava'>
+ * <jc>// Custom error message</jc>
+ * <jsm>assertBean</jsm>(<jsm>args</jsm>(<js>"User validation
failed"</js>), <jv>user</jv>, <js>"name,age"</js>, <js>"Alice,25"</js>);
+ *
+ * <jc>// Custom converter configuration</jc>
+ * AssertionArgs <jv>args</jv> = <jsm>args</jsm>()
+ *
.setConverter(BasicBeanConverter.<jsm>builder</jsm>().<jsm>defaultSettings</jsm>()
+ * .setSetting(<js>"nullValue"</js>, <js>"<empty>"</js>)
+ * .build());
+ * <jsm>assertBean</jsm>(<jv>args</jv>, <jv>user</jv>,
<js>"name,nickname"</js>, <js>"Alice,<empty>"</js>);
+ * </p>
+ *
+ * @see BctAssertions
+ * @see BeanConverter
+ * @see BasicBeanConverter
+ */
+package org.apache.juneau.junit.bct;
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
index 8f288879c..834b19ce1 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
@@ -1690,6 +1690,12 @@ public final class StringUtils {
return sb.toString();
}
+ /**
+ * Converts the contents of the specified input stream to a hex string.
+ *
+ * @param is The input stream to convert.
+ * @return The hex string representation of the input stream contents,
or <jk>null</jk> if the stream is <jk>null</jk>.
+ */
public static String toHex(InputStream is) {
return safe(()->is == null ? null : toHex(readBytes(is)));
}
@@ -1817,10 +1823,22 @@ public final class StringUtils {
}
}
+ /**
+ * Converts the specified byte array to a UTF-8 string.
+ *
+ * @param b The byte array to convert.
+ * @return The UTF-8 string representation, or <jk>null</jk> if the
array is <jk>null</jk>.
+ */
public static String toUtf8(byte[] b) {
return b == null ? null : new String(b, IOUtils.UTF8);
}
+ /**
+ * Converts the contents of the specified input stream to a UTF-8
string.
+ *
+ * @param is The input stream to convert.
+ * @return The UTF-8 string representation of the input stream
contents, or <jk>null</jk> if the stream is <jk>null</jk>.
+ */
public static String toUtf8(InputStream is) {
return safe(()->is == null ? null : new String(readBytes(is),
IOUtils.UTF8));
}
@@ -2134,4 +2152,4 @@ public final class StringUtils {
* Constructor.
*/
protected StringUtils() {}
-}
\ No newline at end of file
+}
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowingSupplier.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowingSupplier.java
index f2733a17c..81e9b29a1 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowingSupplier.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowingSupplier.java
@@ -17,5 +17,12 @@ package org.apache.juneau.common.internal;
*/
@FunctionalInterface
public interface ThrowingSupplier<T> {
+
+ /**
+ * Gets a result.
+ *
+ * @return A result.
+ * @throws Exception If an error occurs.
+ */
T get() throws Exception;
}
\ No newline at end of file
diff --git
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
index 1b7146bfb..bb442fe50 100644
---
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
+++
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
@@ -28,7 +28,11 @@ import java.util.stream.*;
import org.apache.juneau.common.utils.*;
-
+/**
+ * Common utility methods.
+ *
+ * <p>This class contains various static utility methods for working with
collections, strings, objects, and other common operations.
+ */
public class Utils {
private static final Map<Class<?>,Function<String,?>> ENV_FUNCTIONS =
new IdentityHashMap<>();
@@ -42,6 +46,10 @@ public class Utils {
/**
* Creates an array of objects.
+ *
+ * @param <T> The component type of the array.
+ * @param x The objects to place in the array.
+ * @return A new array containing the specified objects.
*/
@SafeVarargs
public static <T> T[] a(T...x) {
@@ -53,7 +61,7 @@ public class Utils {
*
* @param <T> The element type.
* @param o The object to traverse.
- * @param c The consumer of the objects.
+ * @return A list containing all accumulated elements.
*/
public static <T> List<T> accumulate(Object o) {
var l = list();
@@ -63,6 +71,10 @@ public class Utils {
/**
* Shortcut for creating an unmodifiable list out of an array of values.
+ *
+ * @param <T> The element type.
+ * @param values The values to add to the list.
+ * @return An unmodifiable list containing the specified values, or
<jk>null</jk> if the input is <jk>null</jk>.
*/
@SafeVarargs
public static <T> List<T> alist(T...values) { // NOSONAR
@@ -276,6 +288,10 @@ public class Utils {
/**
* Null-safe {@link String#contains(CharSequence)} operation.
+ *
+ * @param s The string to check.
+ * @param values The characters to check for.
+ * @return <jk>true</jk> if the string contains any of the specified
characters.
*/
public static boolean contains(String s, char...values) {
if (s == null || values == null || values.length == 0)
@@ -289,6 +305,10 @@ public class Utils {
/**
* Null-safe {@link String#contains(CharSequence)} operation.
+ *
+ * @param s The string to check.
+ * @param values The substrings to check for.
+ * @return <jk>true</jk> if the string contains any of the specified
substrings.
*/
public static boolean contains(String s, String...values) {
if (s == null || values == null || values.length == 0)
@@ -306,6 +326,10 @@ public class Utils {
/**
* Shortcut for creating an empty list of the specified type.
+ *
+ * @param <T> The element type.
+ * @param type The element type class.
+ * @return An empty list.
*/
public static <T> List<T> elist(Class<T> type) {
return Collections.emptyList();
@@ -327,6 +351,9 @@ public class Utils {
/**
* Returns the specified string, or blank if that string is null.
+ *
+ * @param value The value to convert to a string.
+ * @return The string representation of the value, or an empty string
if <jk>null</jk>.
*/
public static String emptyIfNull(Object value) {
return value == null ? "" : value.toString();
@@ -410,7 +437,7 @@ public class Utils {
* Example:
* <code>
* public boolean equals(Object o)
- * return eq(this, (Role)o, (x,y)->eq(x.id,y.id) &&
eq(x.name,y.name) && eq(x.created,y.created) && eq(x.createdBy,y.createdBy));
+ * return eq(this, (Role)o, (x,y)->eq(x.id,y.id)
&& eq(x.name,y.name) && eq(x.created,y.created) &&
eq(x.createdBy,y.createdBy));
* }
* </code>
*
@@ -445,6 +472,10 @@ public class Utils {
/**
* Same as MessageFormat.format().
+ *
+ * @param pattern The message pattern.
+ * @param args The arguments to substitute into the pattern.
+ * @return The formatted string.
*/
public static String f(String pattern, Object...args) {
if (args.length == 0)
@@ -530,6 +561,9 @@ public class Utils {
/**
* Shortcut for calling {@link Objects#hash(Object...)}.
+ *
+ * @param values The values to hash.
+ * @return A hash code value for the given values.
*/
public static final int hash(Object...values) {
return Objects.hash(values);
@@ -537,6 +571,10 @@ public class Utils {
/**
* Creates an {@link IllegalArgumentException}.
+ *
+ * @param msg The exception message.
+ * @param args The arguments to substitute into the message.
+ * @return A new IllegalArgumentException with the formatted message.
*/
public static IllegalArgumentException illegalArg(String msg,
Object...args) {
return new IllegalArgumentException(args.length == 0 ? msg :
f(msg, args));
@@ -576,7 +614,10 @@ public class Utils {
}
/**
- * @return True if string is null or empty.
+ * Returns <jk>true</jk> if string is <jk>null</jk> or empty.
+ *
+ * @param o The string to check.
+ * @return <jk>true</jk> if string is <jk>null</jk> or empty.
*/
public static boolean isEmpty(String o) {
return o == null || o.isEmpty();
@@ -611,7 +652,10 @@ public class Utils {
}
/**
- * @return True if string is not null or empty.
+ * Returns <jk>true</jk> if string is not <jk>null</jk> and not empty.
+ *
+ * @param o The string to check.
+ * @return <jk>true</jk> if string is not <jk>null</jk> and not empty.
*/
public static boolean isNotEmpty(String o) {
return ! isEmpty(o);
@@ -835,6 +879,10 @@ public class Utils {
/**
* Shortcut for creating a modifiable list out of an array of values.
+ *
+ * @param <T> The element type.
+ * @param values The values to add to the list.
+ * @return A modifiable list containing the specified values.
*/
@SafeVarargs
public static <T> List<T> list(T...values) { // NOSONAR
@@ -853,7 +901,12 @@ public class Utils {
}
/**
- * Shortcut for creating a modifiable set out of an array of values.
+ * Shortcut for creating a modifiable map out of an array of key-value
pairs.
+ *
+ * @param <K> The key type.
+ * @param <V> The value type.
+ * @param values The key-value pairs (alternating keys and values).
+ * @return A modifiable LinkedHashMap containing the specified
key-value pairs.
*/
@SafeVarargs
public static <K,V> LinkedHashMap<K,V> map(Object...values) { //
NOSONAR
@@ -872,7 +925,14 @@ public class Utils {
return null;
}
- /** Not equals */
+ /**
+ * Null-safe not-equals check.
+ *
+ * @param <T> The object type.
+ * @param s1 Object 1.
+ * @param s2 Object 2.
+ * @return <jk>true</jk> if the objects are not equal.
+ */
public static <T> boolean ne(T s1, T s2) {
return ! eq(s1, s2);
}
@@ -908,23 +968,46 @@ public class Utils {
return ! eqic(s1, s2);
}
+ /**
+ * Returns a null list.
+ *
+ * @param <T> The element type.
+ * @param type The element type class.
+ * @return <jk>null</jk>.
+ */
public static <T> List<T> nlist(Class<T> type) {
return null;
}
+ /**
+ * Returns a null map.
+ *
+ * @param <K> The key type.
+ * @param <V> The value type.
+ * @param keyType The key type class.
+ * @param valueType The value type class.
+ * @return <jk>null</jk>.
+ */
public static <K,V> Map<K,V> nmap(Class<K> keyType, Class<V> valueType)
{
return null;
}
/**
- * Null-safe {@link String#contains(CharSequence)} operation.
+ * Null-safe string not-contains operation.
+ *
+ * @param s The string to check.
+ * @param values The characters to check for.
+ * @return <jk>true</jk> if the string does not contain any of the
specified characters.
*/
public static boolean notContains(String s, char...values) {
return ! contains(s, values);
}
/**
- * Returns the specified string, or null if that string is null or
empty.
+ * Returns the specified string, or <jk>null</jk> if that string is
<jk>null</jk> or empty.
+ *
+ * @param value The string value to check.
+ * @return The string value, or <jk>null</jk> if the string is
<jk>null</jk> or empty.
*/
public static String nullIfEmpty(String value) {
return isEmpty(value) ? null : value;
@@ -944,6 +1027,9 @@ public class Utils {
/**
* Returns an obfuscated version of the specified string.
+ *
+ * @param s The string to obfuscate.
+ * @return The obfuscated string with most characters replaced by
asterisks.
*/
public static String obfuscate(String s) {
if (s == null || s.length() < 2)
@@ -953,17 +1039,29 @@ public class Utils {
/**
* Shortcut for calling {@link Optional#ofNullable(Object)}.
+ *
+ * @param <T> The object type.
+ * @param t The object to wrap in an Optional.
+ * @return An Optional containing the specified object, or empty if
<jk>null</jk>.
*/
public static final <T> Optional<T> opt(T t) {
return Optional.ofNullable(t);
}
+ /**
+ * Returns an empty Optional.
+ *
+ * @param <T> The object type.
+ * @return An empty Optional.
+ */
public static final <T> Optional<T> opte() {
return Optional.empty();
}
/**
* Prints all the specified lines to System.out.
+ *
+ * @param lines The lines to print.
*/
public static final void printLines(String[] lines) {
for (var i = 0; i < lines.length; i++)
@@ -978,23 +1076,23 @@ public class Utils {
* the Juneau framework for test assertions and debugging output.</p>
*
* <h5 class='section'>Type-Specific Formatting:</h5>
- * <ul>
- * <li><b>null:</b> Returns <js>null</js></li>
- * <li><b>Optional:</b> Recursively formats the contained value (or
<js>null</js> if empty)</li>
- * <li><b>Collections:</b> Formats as <js>"[item1,item2,item3]"</js> with
comma-separated elements</li>
- * <li><b>Maps:</b> Formats as <js>"{key1=value1,key2=value2}"</js> with
comma-separated entries</li>
- * <li><b>Map.Entry:</b> Formats as <js>"key=value"</js></li>
- * <li><b>Arrays:</b> Converts to list format
<js>"[item1,item2,item3]"</js></li>
- * <li><b>Iterables/Iterators/Enumerations:</b> Converts to list and
formats recursively</li>
- * <li><b>GregorianCalendar:</b> Formats as ISO instant timestamp</li>
- * <li><b>Date:</b> Formats as ISO instant string (e.g.,
<js>"2023-12-25T10:30:00Z"</js>)</li>
- * <li><b>InputStream:</b> Converts to hexadecimal representation</li>
- * <li><b>Reader:</b> Reads content and returns as string</li>
- * <li><b>File:</b> Reads file content and returns as string</li>
- * <li><b>byte[]:</b> Converts to hexadecimal representation</li>
- * <li><b>Enum:</b> Returns the enum name via {@link Enum#name()}</li>
- * <li><b>All other types:</b> Uses {@link Object#toString()}</li>
- * </ul>
+ * <ul>
+ * <li><b>null:</b> Returns <js>null</js></li>
+ * <li><b>Optional:</b> Recursively formats the contained value
(or <js>null</js> if empty)</li>
+ * <li><b>Collections:</b> Formats as
<js>"[item1,item2,item3]"</js> with comma-separated elements</li>
+ * <li><b>Maps:</b> Formats as
<js>"{key1=value1,key2=value2}"</js> with comma-separated entries</li>
+ * <li><b>Map.Entry:</b> Formats as <js>"key=value"</js></li>
+ * <li><b>Arrays:</b> Converts to list format
<js>"[item1,item2,item3]"</js></li>
+ * <li><b>Iterables/Iterators/Enumerations:</b> Converts to list
and formats recursively</li>
+ * <li><b>GregorianCalendar:</b> Formats as ISO instant
timestamp</li>
+ * <li><b>Date:</b> Formats as ISO instant string (e.g.,
<js>"2023-12-25T10:30:00Z"</js>)</li>
+ * <li><b>InputStream:</b> Converts to hexadecimal
representation</li>
+ * <li><b>Reader:</b> Reads content and returns as string</li>
+ * <li><b>File:</b> Reads file content and returns as string</li>
+ * <li><b>byte[]:</b> Converts to hexadecimal representation</li>
+ * <li><b>Enum:</b> Returns the enum name via {@link
Enum#name()}</li>
+ * <li><b>All other types:</b> Uses {@link Object#toString()}</li>
+ * </ul>
*
* <h5 class='section'>Examples:</h5>
* <p class='bjava'>
@@ -1013,10 +1111,10 @@ public class Utils {
* r(List.of(Map.of("x", 1), Set.of("a", "b"))) <jc>// Returns:
"[{x=1},[a,b]]"</jc>
*
* <jc>// Special types</jc>
- * r(Optional.of("test")) <jc>// Returns: "test"</jc>
- * r(Optional.empty()) <jc>// Returns: null</jc>
- * r(new Date(1640995200000L)) <jc>// Returns: "2022-01-01T00:00:00Z"</jc>
- * r(MyEnum.FOO) <jc>// Returns: "FOO"</jc>
+ * r(Optional.of("test")) <jc>// Returns: "test"</jc>
+ * r(Optional.empty()) <jc>// Returns: null</jc>
+ * r(new Date(1640995200000L)) <jc>// Returns:
"2022-01-01T00:00:00Z"</jc>
+ * r(MyEnum.FOO) <jc>// Returns: "FOO"</jc>
* </p>
*
* <h5 class='section'>Recursive Processing:</h5>
@@ -1090,6 +1188,10 @@ public class Utils {
/**
* Creates a {@link RuntimeException}.
+ *
+ * @param msg The exception message.
+ * @param args The arguments to substitute into the message.
+ * @return A new RuntimeException with the formatted message.
*/
public static RuntimeException runtimeException(String msg,
Object...args) {
return new RuntimeException(args.length == 0 ? msg : f(msg,
args));
@@ -1097,6 +1199,9 @@ public class Utils {
/**
* Shortcut for converting an object to a string.
+ *
+ * @param val The object to convert.
+ * @return The string representation of the object, or <jk>null</jk> if
the object is <jk>null</jk>.
*/
public static String s(Object val) {
return val == null ? null : val.toString();
@@ -1121,6 +1226,10 @@ public class Utils {
* Used to wrap code that returns a value but throws an exception.
* Useful in cases where you're trying to execute code in a fluent
method call
* or are trying to eliminate untestable catch blocks in code.
+ *
+ * @param <T> The return type.
+ * @param s The supplier that may throw an exception.
+ * @return The result of the supplier execution.
*/
public static <T> T safe(ThrowingSupplier<T> s) {
try {
@@ -1152,6 +1261,10 @@ public class Utils {
/**
* Shortcut for creating a modifiable set out of an array of values.
+ *
+ * @param <T> The element type.
+ * @param values The values to add to the set.
+ * @return A modifiable LinkedHashSet containing the specified values.
*/
@SafeVarargs
public static <T> LinkedHashSet<T> set(T...values) { // NOSONAR
@@ -1160,6 +1273,9 @@ public class Utils {
/**
* Splits a comma-delimited list into a list of strings.
+ *
+ * @param s The string to split.
+ * @return A list of split strings, or an empty list if the input is
<jk>null</jk>.
*/
public static List<String> split(String s) {
return s == null ? Collections.emptyList() : split(s, ',');
@@ -1274,7 +1390,7 @@ public class Utils {
}
/**
- * Same as {@link #split3(String)} but consumes the tokens instead of
creating an array.
+ * Same as {@link #splita(String)} but consumes the tokens instead of
creating an array.
*
* @param s The string to split.
* @param consumer The consumer of the tokens.
@@ -1285,6 +1401,9 @@ public class Utils {
/**
* Splits a comma-delimited list into an array of strings.
+ *
+ * @param s The string to split.
+ * @return An array of split strings.
*/
public static String[] splita(String s) {
return splita(s, ',');
@@ -1721,16 +1840,15 @@ public class Utils {
* assertList(toList(<jv>myQueue</jv>), <js>"first"</js>,
<js>"second"</js>);
* </p>
*
- * <h5 class='section'>Integration with assertList:</h5>
- * <p>This method is specifically designed to work with {@link
#assertList(List, Object...)} to provide
+ * <h5 class='section'>Integration with Testing:</h5>
+ * <p>This method is specifically designed to work with testing
frameworks to provide
* a unified testing approach for all collection-like types. Instead of
having separate assertion methods
- * for arrays, sets, and other collections, you can convert them all to
Lists and use the single
- * {@code assertList} method.</p>
+ * for arrays, sets, and other collections, you can convert them all to
Lists and use standard
+ * list assertion methods.</p>
*
* @param o The object to convert to a List. Must not be null and must
be a supported collection-like type.
* @return A {@link List} containing the elements from the input object.
* @throws IllegalArgumentException if the input object cannot be
converted to a List.
- * @see #assertList(List, Object...)
* @see #arrayToList(Object)
*/
public static final List<?> toList(Object o) { // NOSONAR
diff --git a/juneau-core/pom.xml b/juneau-core/pom.xml
index f72907786..9a7fb83ec 100644
--- a/juneau-core/pom.xml
+++ b/juneau-core/pom.xml
@@ -33,5 +33,6 @@
<module>juneau-marshall</module>
<module>juneau-config</module>
<module>juneau-assertions</module>
+ <module>juneau-bct</module>
</modules>
</project>
diff --git a/juneau-utest/pom.xml b/juneau-utest/pom.xml
index 9b6d38505..06b310aad 100644
--- a/juneau-utest/pom.xml
+++ b/juneau-utest/pom.xml
@@ -75,6 +75,11 @@
<artifactId>juneau-rest-mock</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.juneau</groupId>
+ <artifactId>juneau-bct</artifactId>
+ <version>${project.version}</version>
+ </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>