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

afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new e87507e1de Fixed infinite loop in Iter.dropWhile, removed itemClass 
argument from ImmutableUniqueList builders.
e87507e1de is described below

commit e87507e1ded80b1d6cb24bf084a04b340d917482
Author: Claus Stadler <[email protected]>
AuthorDate: Wed Jul 22 16:35:01 2026 +0200

    Fixed infinite loop in Iter.dropWhile, removed itemClass argument from 
ImmutableUniqueList builders.
---
 .../jena/sparql/algebra/table/TableBuilder.java    |  2 +-
 .../sparql/engine/join/ImmutableUniqueList.java    | 59 +++++++++++--------
 .../apache/jena/sparql/engine/join/JoinKey.java    |  8 +--
 .../java/org/apache/jena/atlas/iterator/Iter.java  | 10 +---
 .../jena/atlas/iterator/IteratorDropWhile.java     | 68 ++++++++++++++++++++++
 5 files changed, 109 insertions(+), 38 deletions(-)

diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/TableBuilder.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/TableBuilder.java
index 2b88502d94..154c7306e8 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/TableBuilder.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/table/TableBuilder.java
@@ -39,7 +39,7 @@ import org.apache.jena.sparql.engine.join.ImmutableUniqueList;
  * This builder is not thread safe.
  */
 public class TableBuilder {
-    private ImmutableUniqueList.Builder<Var> varsBuilder = 
ImmutableUniqueList.newUniqueListBuilder(Var.class);
+    private ImmutableUniqueList.Builder<Var> varsBuilder = 
ImmutableUniqueList.newUniqueListBuilder();
 
     private List<Binding> rows = new ArrayList<>();
     private boolean copyRowsOnNextMutation = false;
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/ImmutableUniqueList.java
 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/ImmutableUniqueList.java
index 0c3790a464..f9ede5dc19 100644
--- 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/ImmutableUniqueList.java
+++ 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/ImmutableUniqueList.java
@@ -20,7 +20,6 @@
  */
 package org.apache.jena.sparql.engine.join;
 
-import java.lang.reflect.Array;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -46,17 +45,14 @@ public class ImmutableUniqueList<T> extends AbstractList<T> 
{
      * and it can be continued to be used.
      */
     public static final class Builder<T> {
-        private Class<T> itemClass;
-
         /**
          * The keys collection upgrades itself from ArrayList to
          * LinkedHashSet upon adding a sufficient number of items.
          */
         private Collection<T> items;
 
-        Builder(Class<T> itemClass) {
+        Builder() {
             super();
-            this.itemClass = itemClass;
         }
 
         private void alloc(int n) {
@@ -69,13 +65,13 @@ public class ImmutableUniqueList<T> extends AbstractList<T> 
{
         }
 
         public Builder<T> add(T item) {
-            if (!(items instanceof Set)) {
-                if ( items == null || ! items.contains(item) ) {
+            if (items instanceof Set) {
+                items.add(item);
+            } else {
+                if (items == null || !items.contains(item)) {
                     alloc(1);
                     items.add(item) ;
                 }
-            } else {
-                items.add(item);
             }
             return this ;
         }
@@ -116,43 +112,57 @@ public class ImmutableUniqueList<T> extends 
AbstractList<T> {
             return items == null || items.isEmpty();
         }
 
-        @SuppressWarnings("unchecked")
         public ImmutableUniqueList<T> build() {
-            T[] finalItems;
+            Object[] finalItems;
             if (items == null) {
-                finalItems = (T[])Array.newInstance(itemClass, 0);
+                finalItems = new Object[0];
             } else {
-                finalItems = (T[])Array.newInstance(itemClass, items.size());
+                finalItems = new Object[items.size()];
                 items.toArray(finalItems);
             }
             return new ImmutableUniqueList<>(INDEX_THRESHOLD, finalItems);
         }
     }
 
-    public static <T> Builder<T> newUniqueListBuilder(Class<T> itemClass) {
-        return new Builder<>(itemClass);
+    public static <T> Builder<T> newUniqueListBuilder() {
+        return new Builder<>();
+    }
+
+    @Deprecated(forRemoval = true)
+    public static <T> Builder<T> newUniqueListBuilder(Class<T> itemType) {
+        return newUniqueListBuilder();
+    }
+
+    public static <T> ImmutableUniqueList<T> createUniqueList(Collection<T> 
items) {
+        return 
ImmutableUniqueList.<T>newUniqueListBuilder().addAll(items).build();
+    }
+
+    public static <T> ImmutableUniqueList<T> createUniqueList(T[] items) {
+        return 
ImmutableUniqueList.<T>newUniqueListBuilder().addAll(items).build();
     }
 
+    @Deprecated(forRemoval = true)
     public static <T> ImmutableUniqueList<T> createUniqueList(Class<T> 
itemClass, Collection<T> items) {
-        return 
ImmutableUniqueList.<T>newUniqueListBuilder(itemClass).addAll(items).build();
+        return createUniqueList(items);
     }
 
+    @Deprecated(forRemoval = true)
     public static <T> ImmutableUniqueList<T> createUniqueList(Class<T> 
itemClass, T[] items) {
-        return 
ImmutableUniqueList.<T>newUniqueListBuilder(itemClass).addAll(items).build();
+        return createUniqueList(items);
     }
 
     /** Subclasses may access the keys array but must never modify it! */
-    protected final T[] elementData;
+    protected final Object[] elementData;
     protected final int indexThreshold;
 
     /** keyToIdx mapping is initialized lazily in {@link #indexOf(Object)} */
-    private transient Map<T, Integer> elementToIndex;
+    private transient Map<Object, Integer> elementToIndex;
 
-    protected ImmutableUniqueList(T[] elementData) {
+    protected ImmutableUniqueList(Object[] elementData) {
         this(INDEX_THRESHOLD, elementData);
     }
 
-    protected ImmutableUniqueList(int indexThreshold, T[] elementData) {
+    protected ImmutableUniqueList(int indexThreshold, Object[] elementData) {
         super();
         this.indexThreshold = indexThreshold;
         this.elementData = elementData ;
@@ -163,8 +173,9 @@ public class ImmutableUniqueList<T> extends AbstractList<T> 
{
 
     public int length()               { return size(); }
 
+    @SuppressWarnings("unchecked")
     @Override
-    public T get(int i)               { return elementData[i]; }
+    public T get(int i)               { return (T)elementData[i]; }
 
     @Override
     public boolean contains(Object o) { return indexOf(o) != -1; }
@@ -179,9 +190,9 @@ public class ImmutableUniqueList<T> extends AbstractList<T> 
{
                 result = elementToIndex.getOrDefault(o, -1);
             } else {
                 // Compute the map from element to its index
-                Map<T, Integer> map = new HashMap<>();
+                Map<Object, Integer> map = new HashMap<>();
                 for (int i = 0; i < elementData.length; ++i) {
-                    T key = elementData[i];
+                    Object key = elementData[i];
                     map.put(key, i);
                 }
                 result = map.getOrDefault(o, -1);
diff --git 
a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinKey.java 
b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinKey.java
index 29346712ae..628cd3e689 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinKey.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/join/JoinKey.java
@@ -62,7 +62,7 @@ public final class JoinKey extends ImmutableUniqueList<Var>
         private ImmutableUniqueList.Builder<Var> delegate;
 
         Builder() {
-            this.delegate = newUniqueListBuilder(Var.class);
+            this.delegate = newUniqueListBuilder();
         }
 
         public Builder add(Var var) {
@@ -139,15 +139,15 @@ public final class JoinKey extends 
ImmutableUniqueList<Var>
         return keys.length == 0 ? empty() : new JoinKey(keys);
     }
 
-    private JoinKey(Var[] keys) {
+    private JoinKey(Object[] keys) {
         super(keys);
     }
 
     /** Get a single variable for this key.
      *  For any one key, it always returns the same var */
     public Var getVarKey() {
-        if ( elementData.length == 0 )
+        if ( length() == 0 )
             return null ;
-        return elementData[0] ;
+        return get(0);
     }
 }
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java 
b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
index 2d859b3900..36d1c98524 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Iter.java
@@ -607,15 +607,7 @@ public class Iter<T> implements IteratorCloseable<T> {
      *  returned iterator.
      */
     public static <T> Iterator<T> dropWhile(Iterator<T> iter, Predicate<T> 
predicate) {
-        PeekIterator<T> iter2 = new PeekIterator<>(iter);
-        for(;;) {
-            T elt = iter2.peek();
-            if ( elt == null )
-                return Iter.nullIterator();
-            if ( ! predicate.test(elt) )
-                break;
-        }
-        return iter2;
+        return new IteratorDropWhile<T>(iter, predicate);
     }
 
     /** Create an iterator such that elements from the front until
diff --git 
a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDropWhile.java 
b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDropWhile.java
new file mode 100644
index 0000000000..0c7020c7cf
--- /dev/null
+++ 
b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDropWhile.java
@@ -0,0 +1,68 @@
+/*
+ * 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
+ *
+ *   https://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.
+ *
+ *   SPDX-License-Identifier: Apache-2.0
+ */
+
+package org.apache.jena.atlas.iterator;
+
+import java.util.Iterator;
+import java.util.function.Predicate;
+
+/** Iterate drop while a condition is true, then emit the remaining items. */
+final
+public class IteratorDropWhile<T> extends IteratorSlotted<T> {
+    private final Predicate<T> predicate;
+    private Iterator<T> iter;
+    private boolean isInitialized = false;
+
+    public IteratorDropWhile(Iterator<T> iter, Predicate<T> predicate) {
+        this.iter = iter;
+        this.predicate = predicate;
+    }
+
+    @Override
+    protected boolean hasMore() {
+        return true;
+    }
+
+    @Override
+    protected T moveToNext() {
+        // During initialize we drop items as long as the predicate evaluates 
to true.
+        if (!isInitialized) {
+            isInitialized = true;
+            while (iter.hasNext()) {
+                T item = iter.next();
+                if (!predicate.test(item)) {
+                    return item;
+                }
+            }
+            return null;
+        }
+
+        if (!iter.hasNext())
+            return null;
+        T item = iter.next();
+        return item;
+    }
+
+    @Override
+    protected void closeIterator() {
+        Iter.close(iter);
+    }
+}

Reply via email to