-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
* gh-266 ChainedIterable made public * gh-266 ChainedIterable made public - typo * gh-266: Moved out all Iterable classes into iterable module * gh-266: Spotless apply * gh-256: Moved over constructors and tests from Gaffer * gh-266: Added more iterable tests * gh-266: Cleanup and add more constructors * gh-266: Tidy up null check on list Co-authored-by: GCHQDev404 <[email protected]> Co-authored-by: t92549 <[email protected]>
- Loading branch information
1 parent
ec18795
commit 02865ed
Showing
13 changed files
with
1,046 additions
and
350 deletions.
There are no files selected for viewing
61 changes: 61 additions & 0 deletions
61
core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Copyright 2022 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.iterable; | ||
|
||
import org.apache.commons.lang3.ArrayUtils; | ||
|
||
import uk.gov.gchq.koryphe.util.CloseableUtil; | ||
|
||
import java.io.Closeable; | ||
import java.util.Arrays; | ||
import java.util.Iterator; | ||
|
||
/** | ||
* A {@code ChainedIterable} is a {@link java.io.Closeable} | ||
* {@link java.lang.Iterable} composed of other {@link java.lang.Iterable}s. | ||
* | ||
* As a client iterates through this iterable, the child iterables are consumed | ||
* sequentially. | ||
* | ||
* @param <T> the type of items in the iterable. | ||
*/ | ||
public class ChainedIterable<T> implements Closeable, Iterable<T> { | ||
private final Iterable<? extends Iterable<? extends T>> iterables; | ||
|
||
public ChainedIterable(final Iterable<? extends T>... iterables) { | ||
this(ArrayUtils.isEmpty(iterables) ? null : Arrays.asList(iterables)); | ||
} | ||
|
||
public ChainedIterable(final Iterable<? extends Iterable<? extends T>> iterables) { | ||
if (null == iterables) { | ||
throw new IllegalArgumentException("iterables are required"); | ||
} | ||
this.iterables = iterables; | ||
} | ||
|
||
@Override | ||
public Iterator<T> iterator() { | ||
return new ChainedIterator<>(iterables.iterator()); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
for (final Iterable<? extends T> iterable : iterables) { | ||
CloseableUtil.close(iterable); | ||
} | ||
} | ||
} |
74 changes: 74 additions & 0 deletions
74
core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright 2022 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.iterable; | ||
|
||
import uk.gov.gchq.koryphe.util.CloseableUtil; | ||
|
||
import java.io.Closeable; | ||
import java.util.Collections; | ||
import java.util.Iterator; | ||
|
||
/** | ||
* @param <T> the type of items in the iterator | ||
*/ | ||
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 Iterator<? extends Iterable<? extends T>> iterablesIterator) { | ||
if (null == iterablesIterator) { | ||
throw new IllegalArgumentException("iterables are required"); | ||
} | ||
this.iterablesIterator = iterablesIterator; | ||
} | ||
|
||
@Override | ||
public boolean hasNext() { | ||
return getIterator().hasNext(); | ||
} | ||
|
||
@Override | ||
public T next() { | ||
return getIterator().next(); | ||
} | ||
|
||
@Override | ||
public void remove() { | ||
currentIterator.remove(); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
CloseableUtil.close(currentIterator); | ||
while (iterablesIterator.hasNext()) { | ||
CloseableUtil.close(iterablesIterator.next()); | ||
} | ||
} | ||
|
||
private Iterator<? extends T> getIterator() { | ||
while (!currentIterator.hasNext()) { | ||
CloseableUtil.close(currentIterator); | ||
if (iterablesIterator.hasNext()) { | ||
currentIterator = iterablesIterator.next().iterator(); | ||
} else { | ||
break; | ||
} | ||
} | ||
|
||
return currentIterator; | ||
} | ||
} |
68 changes: 68 additions & 0 deletions
68
core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright 2022 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.iterable; | ||
|
||
import com.google.common.collect.Lists; | ||
|
||
import uk.gov.gchq.koryphe.util.CloseableUtil; | ||
|
||
import java.io.Closeable; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import java.util.function.Predicate; | ||
|
||
/** | ||
* A {@code FilteredIterable} is a {@link java.io.Closeable} | ||
* {@link java.lang.Iterable} which can filter out elements | ||
* based on a {@link java.util.List} of {@link java.util.function.Predicate}s. | ||
* | ||
* @param <T> the type of items in the iterable. | ||
*/ | ||
public class FilteredIterable<T> implements Closeable, Iterable<T> { | ||
private final Iterable<T> iterable; | ||
private final List<Predicate> predicates; | ||
|
||
public FilteredIterable(final Iterable<T> iterable, final Predicate... predicates) { | ||
this(iterable, Lists.newArrayList(predicates)); | ||
} | ||
|
||
public FilteredIterable(final Iterable<T> iterable, final List<Predicate> predicates) { | ||
if (null == iterable) { | ||
throw new IllegalArgumentException("iterable is required"); | ||
} | ||
if (null == predicates) { | ||
throw new IllegalArgumentException("List of predicates cannot be null"); | ||
} | ||
if (predicates.stream().anyMatch(Objects::isNull)) { | ||
throw new IllegalArgumentException("Predicates list cannot contain a null predicate"); | ||
} | ||
|
||
this.iterable = iterable; | ||
this.predicates = predicates; | ||
} | ||
|
||
@Override | ||
public Iterator<T> iterator() { | ||
return new FilteredIterator<>(iterable.iterator(), predicates); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
CloseableUtil.close(iterable); | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
* Copyright 2022 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.iterable; | ||
|
||
import uk.gov.gchq.koryphe.impl.predicate.And; | ||
import uk.gov.gchq.koryphe.util.CloseableUtil; | ||
|
||
import java.io.Closeable; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
import java.util.NoSuchElementException; | ||
import java.util.Objects; | ||
import java.util.function.Predicate; | ||
|
||
/** | ||
* @param <T> the type of items in the iterator | ||
*/ | ||
public class FilteredIterator<T> implements Closeable, Iterator<T> { | ||
private final Iterator<? extends T> iterator; | ||
private final And<T> andPredicate; | ||
|
||
public FilteredIterator(final Iterator<T> iterator, final List<Predicate> predicates) { | ||
if (null == iterator) { | ||
throw new IllegalArgumentException("iterator is required"); | ||
} | ||
if (null == predicates) { | ||
throw new IllegalArgumentException("List of predicates cannot be null"); | ||
} | ||
if (predicates.stream().anyMatch(Objects::isNull)) { | ||
throw new IllegalArgumentException("Predicates list cannot contain a null predicate"); | ||
} | ||
|
||
this.iterator = iterator; | ||
this.andPredicate = new And<>(predicates); | ||
} | ||
|
||
private T nextElement; | ||
private Boolean hasNext; | ||
|
||
@Override | ||
public boolean hasNext() { | ||
if (null == hasNext) { | ||
while (iterator.hasNext()) { | ||
final T possibleNext = iterator.next(); | ||
if (andPredicate.test(possibleNext)) { | ||
nextElement = possibleNext; | ||
hasNext = true; | ||
return true; | ||
} | ||
} | ||
hasNext = false; | ||
nextElement = null; | ||
} | ||
|
||
final boolean hasNextResult = Boolean.TRUE.equals(hasNext); | ||
if (!hasNextResult) { | ||
close(); | ||
} | ||
|
||
return hasNextResult; | ||
} | ||
|
||
@Override | ||
public T next() { | ||
if ((null == hasNext) && (!hasNext())) { | ||
throw new NoSuchElementException("Reached the end of the iterator"); | ||
} | ||
|
||
final T elementToReturn = nextElement; | ||
nextElement = null; | ||
hasNext = null; | ||
|
||
return elementToReturn; | ||
} | ||
|
||
@Override | ||
public void remove() { | ||
throw new UnsupportedOperationException("Cannot call remove on a " + getClass().getSimpleName()); | ||
} | ||
|
||
@Override | ||
public void close() { | ||
CloseableUtil.close(iterator); | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright 2022 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.iterable; | ||
|
||
import com.fasterxml.jackson.annotation.JsonIgnore; | ||
|
||
import uk.gov.gchq.koryphe.util.CloseableUtil; | ||
|
||
import java.io.Closeable; | ||
import java.util.Collections; | ||
import java.util.Iterator; | ||
|
||
import static uk.gov.gchq.koryphe.util.JavaUtils.requireNonNullElse; | ||
|
||
/** | ||
* A {@code LimitedIterable} is a {@link java.io.Closeable} | ||
* {@link java.lang.Iterable} which is limited to a maximum size. | ||
* | ||
* @param <T> the type of items in the iterable. | ||
*/ | ||
public final class LimitedIterable<T> implements Closeable, Iterable<T> { | ||
private final Iterable<T> iterable; | ||
private final int start; | ||
private final Integer end; | ||
private final Boolean truncate; | ||
|
||
public LimitedIterable(final Iterable<T> iterable, final int start, final Integer end) { | ||
this(iterable, start, end, true); | ||
} | ||
|
||
public LimitedIterable(final Iterable<T> iterable, final int start, final Integer end, final boolean truncate) { | ||
if (null != end && start > end) { | ||
throw new IllegalArgumentException("The start pointer must be less than the end pointer."); | ||
} | ||
|
||
this.iterable = requireNonNullElse(iterable, Collections.emptyList()); | ||
|
||
this.start = start; | ||
this.end = end; | ||
this.truncate = truncate; | ||
} | ||
|
||
@JsonIgnore | ||
public int getStart() { | ||
return start; | ||
} | ||
|
||
@JsonIgnore | ||
public Integer getEnd() { | ||
return end; | ||
} | ||
|
||
@Override | ||
public void close() { | ||
CloseableUtil.close(iterable); | ||
} | ||
|
||
@Override | ||
public Iterator<T> iterator() { | ||
return new LimitedIterator<>(iterable.iterator(), start, end, truncate); | ||
} | ||
} |
Oops, something went wrong.