You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by da...@apache.org on 2025/04/25 09:27:32 UTC
(jackrabbit-oak) branch OAK-11680 created (now 5a7b1ea538)
This is an automated email from the ASF dual-hosted git repository.
daim pushed a change to branch OAK-11680
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
at 5a7b1ea538 OAK-11680 : added Iterators.cycle replacement in oak-commons
This branch includes the following new commits:
new 5a7b1ea538 OAK-11680 : added Iterators.cycle replacement in oak-commons
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(jackrabbit-oak) 01/01: OAK-11680 : added Iterators.cycle replacement in oak-commons
Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
daim pushed a commit to branch OAK-11680
in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit 5a7b1ea538b3bb8ca61f88295e471cf36346889a
Author: Rishabh Kumar <di...@adobe.com>
AuthorDate: Fri Apr 25 14:57:15 2025 +0530
OAK-11680 : added Iterators.cycle replacement in oak-commons
---
.../oak/commons/collections/CollectionUtils.java | 29 ++++++
.../oak/commons/collections/IteratorUtils.java | 45 +++++++++
.../commons/collections/CollectionUtilsTest.java | 76 ++++++++++++++-
.../oak/commons/collections/IteratorUtilsTest.java | 105 +++++++++++++++++++++
4 files changed, 251 insertions(+), 4 deletions(-)
diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java
index a20affce1c..1c3bb714e2 100644
--- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java
+++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtils.java
@@ -18,6 +18,8 @@
*/
package org.apache.jackrabbit.oak.commons.collections;
+import java.util.Collection;
+
/**
* Utility methods for collections conversions.
*/
@@ -49,4 +51,31 @@ public class CollectionUtils {
return 1 + (int) (capacity / 0.75f);
}
+
+ /**
+ * Converts an Iterable to a Collection.
+ * <p>
+ * If the provided iterable is already a Collection, it is simply cast and returned.
+ * Otherwise, the elements from the iterable are copied into a new List using
+ * {@link ListUtils#toList(Iterable)}.
+ * <p>
+ * Example usage:
+ * <pre>
+ * Iterable<String> iterable = () -> Arrays.asList("a", "b", "c").iterator();
+ * Collection<String> collection = CollectionUtils.asCollection(iterable);
+ * // collection will contain "a", "b", "c"
+ * </pre>
+ *
+ * @param <E> the type of elements in the iterable
+ * @param iterable the iterable to convert, must not be null
+ * @return a Collection containing all elements of the iterable
+ * @throws NullPointerException if the iterable is null
+ */
+ @SuppressWarnings("unchecked")
+ static <E> Collection<E> toCollection(final Iterable<? extends E> iterable) {
+ if (iterable instanceof Collection) {
+ return (Collection<E>) iterable;
+ }
+ return ListUtils.toList(iterable);
+ }
}
\ No newline at end of file
diff --git a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
index 214e404b47..b6830593e4 100644
--- a/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
+++ b/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtils.java
@@ -429,5 +429,50 @@ public class IteratorUtils {
public static <F, T> Iterator<T> transform(Iterator<? extends F> itr, final Function<? super F, ? extends T> transform) {
return org.apache.commons.collections4.IteratorUtils.transformedIterator(itr, transform::apply);
}
+
+ /**
+ * Creates an iterator that cycles indefinitely over the provided elements.
+ * <p>
+ * The returned iterator will continuously loop through the given elements in the same order.
+ * If no elements are provided, the iterator will be empty.
+ * <p>
+ * Example usage:
+ * <pre>
+ * Iterator<String> cyclingIterator = IteratorUtils.cycle("a", "b", "c");
+ * // Iterates: "a", "b", "c", "a", "b", "c", ...
+ * </pre>
+ *
+ * @param <E> the type of elements in the iterator
+ * @param elements the elements to cycle through, must not be null
+ * @return an iterator that cycles indefinitely over the provided elements
+ * @throws NullPointerException if the elements array is null
+ */
+ @SafeVarargs
+ public static <E> Iterator<E> cycle(final E... elements) {
+ Objects.requireNonNull(elements, "elements must not be null");
+ return IteratorUtils.cycle(SetUtils.toLinkedSet(elements));
+ }
+
+ /**
+ * Creates an iterator that cycles indefinitely over the elements of the given iterable.
+ * <p>
+ * The returned iterator will continuously loop through the elements of the iterable in the same order.
+ * If the iterable is empty, the iterator will also be empty.
+ * <p>
+ * Example usage:
+ * <pre>
+ * List<String> list = Arrays.asList("a", "b", "c");
+ * Iterator<String> cyclingIterator = IteratorUtils.cycle(list);
+ * // Iterates: "a", "b", "c", "a", "b", "c", ...
+ * </pre>
+ *
+ * @param <E> the type of elements in the iterable
+ * @param iterable the iterable to cycle through, must not be null
+ * @return an iterator that cycles indefinitely over the elements of the iterable
+ * @throws NullPointerException if the iterable is null
+ */
+ public static <E> Iterator<E> cycle(final Iterable<E> iterable) {
+ return org.apache.commons.collections4.IteratorUtils.loopingIterator(CollectionUtils.toCollection(iterable));
+ }
}
diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java
index 65d97851be..4b798fbbe8 100644
--- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java
+++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/CollectionUtilsTest.java
@@ -21,7 +21,10 @@ package org.apache.jackrabbit.oak.commons.collections;
import org.junit.Assert;
import org.junit.Test;
-import static org.junit.Assert.fail;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
public class CollectionUtilsTest {
@@ -37,9 +40,74 @@ public class CollectionUtilsTest {
Assert.assertEquals(1073741824, capacity);
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void ensureCapacityWithNegativeValue() {
- int capacity = CollectionUtils.ensureCapacity(-8);
- fail("Should throw IllegalArgumentException");
+ Assert.assertThrows(IllegalArgumentException.class, () -> CollectionUtils.ensureCapacity(-8));
+ }
+
+ @Test
+ public void testToCollectionWithCollection() {
+ // Create a Collection
+ Collection<String> original = Arrays.asList("a", "b", "c");
+
+ // Convert to Collection
+ Collection<String> result = CollectionUtils.toCollection(original);
+
+ // Verify it's the same instance
+ Assert.assertSame(original, result);
+ Assert.assertEquals(Arrays.asList("a", "b", "c"), result);
+ }
+
+ @Test
+ public void testToCollectionWithNonCollection() {
+ // Create a non-Collection Iterable using custom implementation
+ Iterable<Integer> iterable = () -> Arrays.asList(1, 2, 3).iterator();
+
+ // Convert to Collection
+ Collection<Integer> result = CollectionUtils.toCollection(iterable);
+
+ // Verify it created a new List with the correct elements
+ Assert.assertTrue(result instanceof List);
+ Assert.assertEquals(Arrays.asList(1, 2, 3), result);
+ }
+
+ @Test
+ public void testToCollectionWithNull() {
+ Assert.assertThrows(NullPointerException.class, () -> CollectionUtils.toCollection(null));
+ }
+
+ @Test
+ public void testToCollectionWithEmptyIterable() {
+ Iterable<String> empty = Collections.emptyList();
+ Collection<String> result = CollectionUtils.toCollection(empty);
+
+ Assert.assertTrue(result.isEmpty());
+ Assert.assertEquals(0, result.size());
+ }
+
+ @Test
+ public void testToCollectionWithCustomIterable() {
+ // Create a custom Iterable
+ Iterable<Character> chars = () -> Arrays.asList('a', 'b', 'c').iterator();
+
+ Collection<Character> result = CollectionUtils.toCollection(chars);
+
+ Assert.assertEquals(3, result.size());
+ Assert.assertTrue(result.contains('a'));
+ Assert.assertTrue(result.contains('b'));
+ Assert.assertTrue(result.contains('c'));
+ }
+
+ @Test
+ public void testToCollectionMutability() {
+ // Create a non-Collection Iterable
+ Iterable<String> iterable = () -> Arrays.asList("a", "b").iterator();
+
+ // Convert to Collection
+ Collection<String> result = CollectionUtils.toCollection(iterable);
+
+ // Verify the resulting collection is mutable
+ result.add("c");
+ Assert.assertEquals(Arrays.asList("a", "b", "c"), result);
}
}
\ No newline at end of file
diff --git a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
index bb549e068c..ddcd9a8a7b 100644
--- a/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
+++ b/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/collections/IteratorUtilsTest.java
@@ -1030,4 +1030,109 @@ public class IteratorUtilsTest {
Assert.assertEquals(Arrays.asList(4, 4, 4, 4), result);
}
+
+ @Test
+ public void testCycleWithNonEmptyElements() {
+ Iterator<String> cyclingIterator = IteratorUtils.cycle("a", "b", "c");
+
+ Assert.assertTrue(cyclingIterator.hasNext());
+ Assert.assertEquals("a", cyclingIterator.next());
+ Assert.assertEquals("b", cyclingIterator.next());
+ Assert.assertEquals("c", cyclingIterator.next());
+ Assert.assertEquals("a", cyclingIterator.next()); // Cycles back
+ Assert.assertEquals("b", cyclingIterator.next()); // Cycles back
+ Assert.assertEquals("c", cyclingIterator.next()); // Cycles back
+ }
+
+ @Test
+ public void testCycleWithSingleElement() {
+ Iterator<Integer> cyclingIterator = IteratorUtils.cycle(42);
+
+ Assert.assertTrue(cyclingIterator.hasNext());
+ Assert.assertEquals(Integer.valueOf(42), cyclingIterator.next());
+ Assert.assertEquals(Integer.valueOf(42), cyclingIterator.next()); // Repeats
+ }
+
+ @Test
+ public void testCycleWithEmptyElements() {
+ Iterator<Object> cyclingIterator = IteratorUtils.cycle();
+
+ Assert.assertFalse(cyclingIterator.hasNext());
+ }
+
+ @Test
+ public void testCycleWithNullElements() {
+ Assert.assertThrows(NullPointerException.class,() -> IteratorUtils.cycle((String[]) null));
+ }
+
+ @Test
+ public void testCycleWithRemove() {
+ Iterator<String> cyclingIterator = IteratorUtils.cycle("x", "y");
+
+ Assert.assertEquals("x", cyclingIterator.next());
+ cyclingIterator.remove(); // Should remove "x"
+ Assert.assertEquals("y", cyclingIterator.next());
+ Assert.assertEquals("y", cyclingIterator.next());
+ cyclingIterator.remove(); // Should remove "y"
+ Assert.assertFalse(cyclingIterator.hasNext());
+ }
+
+ @Test
+ public void testCycleWithNonEmptyIterable() {
+ List<String> list = Arrays.asList("a", "b", "c");
+ Iterator<String> cyclingIterator = IteratorUtils.cycle(list);
+
+ Assert.assertTrue(cyclingIterator.hasNext());
+ Assert.assertEquals("a", cyclingIterator.next());
+ Assert.assertEquals("b", cyclingIterator.next());
+ Assert.assertEquals("c", cyclingIterator.next());
+ Assert.assertEquals("a", cyclingIterator.next()); // Cycles back
+ }
+
+ @Test
+ public void testCycleWithSingleElementIterable() {
+ List<Integer> list = Collections.singletonList(42);
+ Iterator<Integer> cyclingIterator = IteratorUtils.cycle(list);
+
+ Assert.assertTrue(cyclingIterator.hasNext());
+ Assert.assertEquals(Integer.valueOf(42), cyclingIterator.next());
+ Assert.assertEquals(Integer.valueOf(42), cyclingIterator.next()); // Repeats
+ }
+
+ @Test
+ public void testCycleWithEmptyIterable() {
+ List<Object> emptyList = Collections.emptyList();
+ Iterator<Object> cyclingIterator = IteratorUtils.cycle(emptyList);
+
+ Assert.assertFalse(cyclingIterator.hasNext());
+ }
+
+ @Test
+ public void testCycleWithNullIterable() {
+ Assert.assertThrows(NullPointerException.class, () -> IteratorUtils.cycle((Iterable<String>) null));
+ }
+
+ @Test
+ public void testCycleWithRemoveWhenIterableAllows() {
+ List<String> list = new ArrayList<>(Arrays.asList("x", "y"));
+ Iterator<String> cyclingIterator = IteratorUtils.cycle(list);
+
+ Assert.assertEquals("x", cyclingIterator.next());
+ cyclingIterator.remove(); // Removes "x"
+ Assert.assertEquals("y", cyclingIterator.next());
+ cyclingIterator.remove(); // Removes "y"
+ Assert.assertFalse(cyclingIterator.hasNext());
+ }
+
+ @Test
+ public void testCycleWithRemoveWhenIterableDisallows() {
+ List<String> list = Arrays.asList("x", "y");
+ Iterator<String> cyclingIterator = IteratorUtils.cycle(list);
+
+ Assert.assertEquals("x", cyclingIterator.next());
+ Assert.assertThrows(UnsupportedOperationException.class, cyclingIterator::remove); // Doesn't Removes "x"
+ Assert.assertEquals("y", cyclingIterator.next());
+ Assert.assertEquals("x", cyclingIterator.next());
+ Assert.assertTrue(cyclingIterator.hasNext());
+ }
}