diff --git a/src/main/java/org/apache/commons/collections4/IterableUtils.java b/src/main/java/org/apache/commons/collections4/IterableUtils.java index 38a1c11a51..e6c52fcb16 100644 --- a/src/main/java/org/apache/commons/collections4/IterableUtils.java +++ b/src/main/java/org/apache/commons/collections4/IterableUtils.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.Supplier; import org.apache.commons.collections4.functors.EqualPredicate; import org.apache.commons.collections4.iterators.LazyIteratorChain; @@ -140,6 +141,39 @@ protected Iterator nextIterator(final int count) { }; } + /** + * Combines the provided iterables into a single iterable. + *

+ * The returned iterable has an iterator that traverses the elements in the order + * of the arguments, i.e. iterables[0], iterables[1], .... The source iterators + * are not polled until necessary. + *

+ * The returned iterable's iterator supports {@code remove()} when the corresponding + * input iterator supports it. + * + * @param the element type + * @param iterableSuppliers the iterables to combine, may not be null + * @return a new iterable, combining the provided iterables + * @throws NullPointerException if either of the provided iterables is null + */ + public static Iterable chainedIterable(final Supplier>... iterableSuppliers) { + checkNotNull(iterableSuppliers); + return new FluentIterable() { + @Override + public Iterator iterator() { + return new LazyIteratorChain() { + @Override + protected Iterator nextIterator(final int count) { + if (count > iterableSuppliers.length) { + return null; + } + return iterableSuppliers[count - 1].get().iterator(); + } + }; + } + }; + } + /** * Combines two iterables into a single iterable. *

@@ -231,6 +265,19 @@ static void checkNotNull(final Iterable... iterables) { } } + /** + * Fail-fast check for null arguments. + * + * @param suppliers the suppliers to check + * @throws NullPointerException if the argument or any of its contents is null + */ + static void checkNotNull(final Supplier... suppliers) { + Objects.requireNonNull(suppliers, "suppliers"); + for (final Supplier supplier : suppliers) { + Objects.requireNonNull(supplier, "supplier"); + } + } + /** * Combines the two provided iterables into an ordered iterable using the * provided comparator. If the comparator is null, natural ordering will be @@ -384,7 +431,7 @@ public static Set duplicateSet(final Iterable iterable) { } /** - * Worker method for {@link #duplicateSet(Collection)} and friends. + * Worker method for {@link #duplicateSet(Iterable)} and friends. * * @param the type of Collection. * @param the type of elements in the Collection. diff --git a/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java b/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java index ab8995b91f..a48b05205f 100644 --- a/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java +++ b/src/test/java/org/apache/commons/collections4/IterableUtilsTest.java @@ -33,14 +33,21 @@ import java.util.Collections; import java.util.Deque; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; import org.apache.commons.collections4.bag.HashBag; import org.apache.commons.collections4.functors.EqualPredicate; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -653,4 +660,105 @@ public void testToStringWithNullArguments() { }, StringUtils.EMPTY, "(", null), "expecting NullPointerException")); } + static final class MockMongoAlertQueryService { + + public Iterable> query(String table) { + switch (table) { + case "alerts_tenant_1": { + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("uuId", "alert-23132158"); + map1.put("property1", "xxxxxx"); + map1.put("property2", "xxxxxx"); + map1.put("property3", "xxxxxx"); + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("uuId", "alert-23132159"); + map2.put("property1", "xxxxxx"); + map2.put("property2", "xxxxxx"); + map2.put("property3", "xxxxxx"); + return Arrays.asList( + map1, + map2 + ); + } + case "alerts_tenant_2": { + return new HashSet<>(); + } + case "alerts_tenant_3": { + LinkedHashMap map1 = new LinkedHashMap<>(); + map1.put("uuId", "alert-23154789"); + map1.put("property1", "xxxxxx"); + map1.put("property2", "xxxxxx"); + map1.put("property3", "xxxxxx"); + LinkedHashMap map2 = new LinkedHashMap<>(); + map2.put("uuId", "alert-32651147"); + map2.put("property1", "xxxxxx"); + map2.put("property2", "xxxxxx"); + map2.put("property3", "xxxxxx"); + LinkedHashMap map3 = new LinkedHashMap<>(); + map3.put("uuId", "alert-34321523"); + map3.put("property1", "xxxxxx"); + map3.put("property2", "xxxxxx"); + map3.put("property3", "xxxxxx"); + return Arrays.asList( + map1, + map2, + map3 + ); + } + default: + return new ArrayList<>(); + } + + } + + } + + @Test + public void testChainedIterable() { + MockMongoAlertQueryService mockMongoAlertQueryService = new MockMongoAlertQueryService(); + List>>> suppliers = + Arrays.asList( + "alerts_tenant_1", + "alerts_tenant_2", + "alerts_tenant_3", + "alerts_tenant_4", + "alerts_tenant_5" + ).stream().map( + new Function>>>() { + @Override + public Supplier>> apply(String tableName) { + return () -> mockMongoAlertQueryService.query( + tableName + ); + } + } + ).collect( + Collectors.toList() + ); + Iterable> totalAlertsIterable + = IterableUtils.chainedIterable( + suppliers.toArray(new Supplier[0]) + ); + ArrayList resultUuids = new ArrayList<>(0); + totalAlertsIterable.forEach( + new Consumer>() { + @Override + public void accept(Map stringObjectMap) { + resultUuids.add(stringObjectMap.get("uuId")); + } + } + ); + Assertions.assertArrayEquals( + new Object[]{ + "alert-23132158", + "alert-23132159", + "alert-23154789", + "alert-32651147", + "alert-34321523" + }, + resultUuids.toArray(new Object[0]) + ); + + } + }