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);
+ }
+}