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 dd0ea450aa Bean API improvements
dd0ea450aa is described below

commit dd0ea450aa905c19093046315b98d1e12934bb1d
Author: James Bognar <[email protected]>
AuthorDate: Mon Feb 2 11:12:28 2026 -0500

    Bean API improvements
---
 .../juneau/commons/utils/CollectionUtils.java      | 57 ++++++++++++++++++++--
 .../src/main/java/org/apache/juneau/BeanMeta.java  |  2 +-
 .../src/main/java/org/apache/juneau/ClassMeta.java |  8 ++-
 .../org/apache/juneau/collections/JsonMap.java     |  2 +-
 .../apache/juneau/csv/CsvSerializerSession.java    |  4 +-
 .../main/java/org/apache/juneau/parser/Parser.java |  2 +-
 .../org/apache/juneau/serializer/Serializer.java   |  2 +-
 .../juneau/commons/utils/CollectionUtils_Test.java | 16 +++---
 8 files changed, 71 insertions(+), 22 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
index 6a2a3e5eac..789eafb829 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
@@ -710,14 +710,61 @@ public class CollectionUtils {
        }
 
        /**
-        * Returns the first element in a list.
+        * Returns the next value from an iterator, or an empty Optional if 
there are no more elements.
+        *
+        * <p>
+        * This is a null-safe operation. Returns an empty Optional if the 
iterator is <jk>null</jk> or
+        * has no more elements.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      Iterator&lt;String&gt; <jv>it</jv> = list.iterator();
+        *      Optional&lt;String&gt; <jv>first</jv> = 
<jsm>next</jsm>(<jv>it</jv>);  <jc>// Optional.of("first")</jc>
+        *      Optional&lt;String&gt; <jv>second</jv> = 
<jsm>next</jsm>(<jv>it</jv>);  <jc>// Optional.of("second")</jc>
+        *      Optional&lt;String&gt; <jv>empty</jv> = 
<jsm>next</jsm>(<jv>it</jv>);   <jc>// Optional.empty()</jc>
+        *      Optional&lt;String&gt; <jv>nullResult</jv> = 
<jsm>next</jsm>(<jk>null</jk>);  <jc>// Optional.empty()</jc>
+        * </p>
         *
         * @param <E> The element type.
-        * @param l The list. Can be <jk>null</jk>.
-        * @return The first element in the list, or <jk>null</jk> if the list 
is <jk>null</jk> or empty.
+        * @param iterator The iterator. Can be <jk>null</jk>.
+        * @return An Optional containing the next element, or empty if the 
iterator is <jk>null</jk> or has no more elements.
         */
-       public static <E> E first(List<E> l) {
-               return e(l) ? null : l.get(0);
+       public static <E> Optional<E> next(Iterator<? extends E> iterator) {
+               if (iterator == null || !iterator.hasNext())
+                       return Optional.empty();
+               return Optional.of(iterator.next());
+       }
+
+       /**
+        * Returns the first element in an iterable.
+        *
+        * <p>
+        * This is a null-safe operation. Returns an empty Optional if the 
iterable is <jk>null</jk> or empty.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      List&lt;String&gt; <jv>list</jv> = <jsm>l</jsm>(<js>"a"</js>, 
<js>"b"</js>, <js>"c"</js>);
+        *      Optional&lt;String&gt; <jv>first</jv> = 
<jsm>first</jsm>(<jv>list</jv>);  <jc>// Optional.of("a")</jc>
+        *
+        *      Set&lt;Integer&gt; <jv>set</jv> = <jsm>s</jsm>(1, 2, 3);
+        *      Optional&lt;Integer&gt; <jv>firstInt</jv> = 
<jsm>first</jsm>(<jv>set</jv>);  <jc>// Optional.of(1) or another element</jc>
+        *
+        *      EnumSet&lt;MyEnum&gt; <jv>enumSet</jv> = 
EnumSet.allOf(MyEnum.<jk>class</jk>);
+        *      Optional&lt;MyEnum&gt; <jv>firstEnum</jv> = 
<jsm>first</jsm>(<jv>enumSet</jv>);  <jc>// Optional.of(first enum value)</jc>
+        *
+        *      Optional&lt;String&gt; <jv>empty</jv> = 
<jsm>first</jsm>(Collections.emptyList());  <jc>// Optional.empty()</jc>
+        *      Optional&lt;String&gt; <jv>nullResult</jv> = 
<jsm>first</jsm>(<jk>null</jk>);  <jc>// Optional.empty()</jc>
+        * </p>
+        *
+        * @param <E> The element type.
+        * @param iterable The iterable. Can be <jk>null</jk>.
+        * @return An Optional containing the first element, or empty if the 
iterable is <jk>null</jk> or empty.
+        */
+       public static <E> Optional<E> first(Iterable<? extends E> iterable) {
+               if (iterable == null)
+                       return Optional.empty();
+               Iterator<? extends E> iterator = iterable.iterator();
+               return next(iterator);
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index a463f0c192..f65483bfa0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -956,7 +956,7 @@ public class BeanMeta<T> {
                if (l.size() > 1)
                        throw bex(ci, "Multiple instances of '@Beanc' found.");
                if (l.size() == 1) {
-                       var con = l.get(0).accessible();
+                       var con = first(l).get().accessible();
                        var args = ap.find(Beanc.class, con).stream().map(x -> 
x.inner().properties()).filter(StringUtils::isNotBlank).map(x -> 
split(x)).findFirst().orElse(liste());
                        if (! con.hasNumParameters(args.size())) {
                                if (ne(args))
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 7de64f3665..2c9efd9337 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -1284,8 +1284,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
 
                if (ci.isAssignableTo(Surrogate.class)) {
                        List<SurrogateSwap<?,?>> l = 
SurrogateSwap.findObjectSwaps(c, beanContext);
-                       if (! l.isEmpty())
-                               return (ObjectSwap<T,?>)l.iterator().next();
+                       return first(l).map(x -> 
(ObjectSwap<T,?>)x).orElse(null);
                }
 
                throw new ClassMetaRuntimeException(c, "Invalid swap class 
''{0}'' specified.  Must extend from ObjectSwap or Surrogate.", c);
@@ -1410,7 +1409,6 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                return m.build();
        }
 
-       @SuppressWarnings("unchecked")
        private String findExample() {
 
                var example = beanMeta.get().optBeanMeta().map(x -> 
x.getBeanFilter()).map(x -> x.getExample()).orElse(null);
@@ -1429,8 +1427,8 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        } else if (cat.is(CHARSEQ)) {
                                example = "foo";
                        } else if (cat.is(ENUM)) {
-                               Iterator<? extends Enum<?>> i = 
EnumSet.allOf(asEnumClass(inner())).iterator();
-                               example = i.hasNext() ? 
(beanContext.isUseEnumNames() ? i.next().name() : i.next().toString()) : null;
+                               Optional<Enum<?>> e = 
first(EnumSet.allOf(asEnumClass(inner())));
+                               example = e.map(x -> 
beanContext.isUseEnumNames() ? x.name() : x.toString()).orElse(null);
                        } else if (isAny(float.class, Float.class, 
double.class, Double.class)) {
                                example = "1.0";
                        } else if (isAny(short.class, Short.class, int.class, 
Integer.class, long.class, Long.class)) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
index 659ed8249d..37e431a2f5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
@@ -1104,7 +1104,7 @@ public class JsonMap extends LinkedHashMap<String,Object> 
{
         *
         * @return The first key in the map, or <jk>null</jk> if the map is 
empty.
         */
-       public String getFirstKey() { return isEmpty() ? null : 
keySet().iterator().next(); }
+       public String getFirstKey() { return first(keySet()).orElse(null); }
 
        /**
         * Returns the specified entry value converted to an {@link Integer}.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
index e4830be95f..2f9c6c6bb8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
@@ -236,7 +236,7 @@ public class CsvSerializerSession extends 
WriterSerializerSession {
 
                        // TODO - Doesn't support DynaBeans.
                        if (ne(l)) {
-                               var entryType = 
getClassMetaForObject(l.iterator().next());
+                               var entryType = 
getClassMetaForObject(first(l).get());
                                if (entryType.isBean()) {
                                        var bm = entryType.getBeanMeta();
                                        var addComma = Flag.create();
@@ -264,7 +264,7 @@ public class CsvSerializerSession extends 
WriterSerializerSession {
                                        });
                                } else if (entryType.isMap()) {
                                        var addComma = Flag.create();
-                                       var first = (Map)l.iterator().next();
+                                       var first = (Map)first(l).get();
                                        first.keySet().forEach(x -> {
                                                addComma.ifSet(() -> 
w.w(',')).set();
                                                w.writeEntry(x);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
index 4d4379e5fb..4794d121ef 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
@@ -1080,7 +1080,7 @@ public class Parser extends BeanContextable {
         *
         * @return The media type.
         */
-       public final MediaType getPrimaryMediaType() { return 
consumesArray.isEmpty() ? null : consumesArray.get(0); }
+       public final MediaType getPrimaryMediaType() { return 
first(consumesArray).orElse(null); }
 
        @Override /* Overridden from Context */
        public ParserSession getSession() { return createSession().build(); }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
index 7566dce830..f49cca7425 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -1364,7 +1364,7 @@ public class Serializer extends BeanTraverseContext {
         *
         * @return The media type.  Never <jk>null</jk>.
         */
-       public final MediaType getPrimaryMediaType() { return 
acceptMediaTypes.get(0); }
+       public final MediaType getPrimaryMediaType() { return 
first(acceptMediaTypes).get(); }
 
        /**
         * Optional method that returns the response <c>Content-Type</c> for 
this serializer if it is different from
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
index 314240a6ea..8e59d8f108 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/utils/CollectionUtils_Test.java
@@ -555,15 +555,20 @@ class CollectionUtils_Test extends TestBase {
        }
 
        
//====================================================================================================
-       // first(List<E>)
+       // first(Iterable<E>)
        
//====================================================================================================
        @Test
        void a031_first() {
-               List<String> list = list("a", "b", "c");
-               assertEquals("a", first(list));
+               var list = list("a", "b", "c");
+               assertEquals(Optional.of("a"), first(list));
+
+               assertEquals(Optional.empty(), first(null));
+               assertEquals(Optional.empty(), first(list()));
 
-               assertNull(first(null));
-               assertNull(first(list()));
+               // Test with Set
+               var set = set(1, 2, 3);
+               assertTrue(first(set).isPresent());
+               assertTrue(set.contains(first(set).get()));
        }
 
        
//====================================================================================================
@@ -1297,7 +1302,6 @@ class CollectionUtils_Test extends TestBase {
                ArrayList<String> arrayList = new ArrayList<>();
                arrayList.add("a");
                arrayList.add("b");
-               @SuppressWarnings("cast")
                List<?> result1 = toList((Object)arrayList);
                assertSame(arrayList, result1);
 

Reply via email to