Skip to content
This repository was archived by the owner on Jun 6, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2025 Crown Copyright
*
* Licensed 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
*
* http://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.
*/

package uk.gov.gchq.koryphe.impl.binaryoperator;

import uk.gov.gchq.koryphe.Since;
import uk.gov.gchq.koryphe.Summary;
import uk.gov.gchq.koryphe.binaryoperator.KorypheBinaryOperator;
import uk.gov.gchq.koryphe.util.IterableUtil;

import java.util.Arrays;

/**
* An <code>IterableMerge</code> is a {@link KorypheBinaryOperator} that takes two
* {@link java.lang.Iterable}s and merges them together.
*/
@Since("2.6.0")
@Summary("Merges two iterables together.")
public class IterableMerge<T> extends KorypheBinaryOperator<Iterable<T>> {

@Override
protected Iterable<T> _apply(final Iterable<T> a, final Iterable<T> b) {
return IterableUtil.concat(Arrays.asList(a, b));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Crown Copyright
* Copyright 2025 Crown Copyright
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,7 @@
import uk.gov.gchq.koryphe.util.CloseableUtil;

import java.io.Closeable;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;

Expand All @@ -31,6 +32,10 @@ public class ChainedIterator<T> implements Closeable, Iterator<T> {
private final Iterator<? extends Iterable<? extends T>> iterablesIterator;
private Iterator<? extends T> currentIterator = Collections.emptyIterator();

public ChainedIterator(final Iterable<? extends T>... iterators) {
this((iterators == null || iterators.length == 0) ? null : Arrays.asList(iterators).iterator());
}

public ChainedIterator(final Iterator<? extends Iterable<? extends T>> iterablesIterator) {
if (null == iterablesIterator) {
throw new IllegalArgumentException("iterables are required");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2025 Crown Copyright
*
* Licensed 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
*
* http://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.
*/

package uk.gov.gchq.koryphe.impl.binaryoperator;

import static org.assertj.core.api.Assertions.assertThat;

import org.junit.jupiter.api.Test;

import com.google.common.collect.Lists;

import uk.gov.gchq.koryphe.binaryoperator.BinaryOperatorTest;
import uk.gov.gchq.koryphe.iterable.ChainedIterable;
import uk.gov.gchq.koryphe.util.JsonSerialiser;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.TreeSet;

class IterableMergeTest extends BinaryOperatorTest<IterableMerge> {

@Test
public void shouldJsonSerialiseAndDeserialise() throws IOException {
// Given
final IterableMerge merger = new IterableMerge<>();

// When
final String json = JsonSerialiser.serialise(merger);

// Then
JsonSerialiser.assertEquals(
String.format("{%n" +
" \"class\" : \"uk.gov.gchq.koryphe.impl.binaryoperator.IterableMerge\"%n" +
"}"),
json);

// When
final IterableMerge deserialisedMerger = JsonSerialiser.deserialise(json, IterableMerge.class);

// Then
assertThat(deserialisedMerger).isNotNull();
}

@Test
void shouldMergeArrays() {
// Given
final IterableMerge<Integer> merger = new IterableMerge<>();
final List<Integer> itr1 = Lists.newArrayList(1, 2, 3, 4);
final List<Integer> itr2 = Lists.newArrayList(5, 6);

// When
final Iterable<Integer> result = merger.apply(itr1, itr2);

// Then
assertThat(result)
.isInstanceOf(ChainedIterable.class)
.containsExactly(1, 2, 3, 4, 5, 6);
}

@Test
void shouldMergeHashSets() {
// Given
final HashSet<Integer> hashSet1 = new HashSet<>();
hashSet1.add(1);

final HashSet<Integer> hashSet2 = new HashSet<>();
hashSet2.add(2);
hashSet2.add(3);

IterableMerge<Integer> merger = new IterableMerge<>();
final Iterable<Integer> result = merger.apply(hashSet1, hashSet2);

assertThat(result).containsExactly(1, 2, 3);
}

@Test
void shouldMergeTreeSets() {
// Given
final TreeSet<String> treeSet1 = new TreeSet<>();
treeSet1.add("string1");

final TreeSet<String> treeSet2 = new TreeSet<>();
treeSet2.add("string3");
treeSet2.add("string2");

final IterableMerge<String> merger = new IterableMerge<>();

// When
final Iterable<String> result = merger.apply(treeSet1, treeSet2);

// Then
assertThat(result).containsExactly("string1", "string2", "string3");
}

@Test
void shouldHandleNullElementsOfIterable() {
// Given
final IterableMerge<Integer> merger = new IterableMerge<>();
final List<Integer> itr1 = Lists.newArrayList(1, 2, null, 4);
final List<Integer> itr2 = Lists.newArrayList(null, 6);

// When
final Iterable<Integer> results = merger.apply(itr1, itr2);

// Then
assertThat(results).containsExactly(1, 2, null, 4, null, 6);
}

@Override
protected IterableMerge getInstance() {
return new IterableMerge<>();
}

@Override
protected Iterable<IterableMerge> getDifferentInstancesOrNull() {
return null;
}
}
Loading