From 8d47243ea5f86d16e41892441d308b88eee35674 Mon Sep 17 00:00:00 2001 From: t92549 <80890692+t92549@users.noreply.github.com> Date: Fri, 6 May 2022 15:15:06 +0100 Subject: [PATCH] gh-266: Moved out all Iterable classes into iterable module --- .../iterable/ChainedIterable.java | 2 +- .../iterable/ChainedIterator.java | 2 +- .../koryphe/iterable/FilteredIterable.java | 47 ++++ .../koryphe/iterable/FilteredIterator.java | 87 ++++++ .../koryphe/iterable/LimitedIterable.java | 69 +++++ .../koryphe/iterable/LimitedIterator.java | 81 ++++++ .../gchq/koryphe/iterable/MappedIterable.java | 48 ++++ .../gchq/koryphe/iterable/MappedIterator.java | 59 ++++ .../gov/gchq/koryphe/util/IterableUtil.java | 255 +----------------- 9 files changed, 397 insertions(+), 253 deletions(-) rename core/src/main/java/uk/gov/gchq/koryphe/{commonutil => }/iterable/ChainedIterable.java (96%) rename core/src/main/java/uk/gov/gchq/koryphe/{commonutil => }/iterable/ChainedIterator.java (97%) create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterable.java create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterator.java create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterable.java create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterator.java create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterable.java create mode 100644 core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterator.java diff --git a/core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterable.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterable.java similarity index 96% rename from core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterable.java rename to core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterable.java index f70ec803..93eea41f 100644 --- a/core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterable.java +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterable.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package uk.gov.gchq.koryphe.commonutil.iterable; +package uk.gov.gchq.koryphe.iterable; import uk.gov.gchq.koryphe.util.CloseableUtil; diff --git a/core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterator.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterator.java similarity index 97% rename from core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterator.java rename to core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterator.java index 23a14770..2685e422 100644 --- a/core/src/main/java/uk/gov/gchq/koryphe/commonutil/iterable/ChainedIterator.java +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/ChainedIterator.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package uk.gov.gchq.koryphe.commonutil.iterable; +package uk.gov.gchq.koryphe.iterable; import uk.gov.gchq.koryphe.util.CloseableUtil; diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterable.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterable.java new file mode 100644 index 00000000..6841364c --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterable.java @@ -0,0 +1,47 @@ +/* + * 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.Iterator; +import java.util.List; +import java.util.function.Predicate; + +/** + * @param the type of items in the iterator + */ +public class FilteredIterable implements Closeable, Iterable { + private final Iterable iterable; + private final List predicates; + + public FilteredIterable(final Iterable iterable, final List predicates) { + this.iterable = iterable; + this.predicates = predicates; + } + + @Override + public Iterator iterator() { + return new FilteredIterator<>(iterable.iterator(), predicates); + } + + @Override + public void close() { + CloseableUtil.close(iterable); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterator.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterator.java new file mode 100644 index 00000000..eb255212 --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/FilteredIterator.java @@ -0,0 +1,87 @@ +/* + * 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.function.Predicate; + +/** + * @param the type of items in the iterator + */ +public class FilteredIterator implements Closeable, Iterator { + private final Iterator iterator; + private final And andPredicate; + + public FilteredIterator(final Iterator iterator, final List predicates) { + 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); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterable.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterable.java new file mode 100644 index 00000000..124b1865 --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterable.java @@ -0,0 +1,69 @@ +/* + * 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; + +/** + * @param the type of items in the iterator + */ +public final class LimitedIterable implements Closeable, Iterable { + private final Iterable iterable; + private final int start; + private final Integer end; + private final Boolean truncate; + + public LimitedIterable(final Iterable 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 iterator() { + return new LimitedIterator<>(iterable.iterator(), start, end, truncate); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterator.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterator.java new file mode 100644 index 00000000..b8329501 --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/LimitedIterator.java @@ -0,0 +1,81 @@ +/* + * 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; +import java.util.NoSuchElementException; + +import static uk.gov.gchq.koryphe.util.JavaUtils.requireNonNullElse; + +/** + * @param the type of items in the iterator + */ +public final class LimitedIterator implements Closeable, Iterator { + private final Iterator iterator; + private final Integer end; + private int index = 0; + private Boolean truncate = true; + + public LimitedIterator(final Iterator iterator, final int start, final Integer end, final boolean truncate) { + if (null != end && start > end) { + throw new IllegalArgumentException("start should be less than end"); + } + + this.iterator = requireNonNullElse(iterator, Collections.emptyIterator()); + this.end = end; + this.truncate = truncate; + + while (index < start && hasNext()) { + next(); + } + } + + @Override + public void close() { + CloseableUtil.close(iterator); + } + + @Override + public boolean hasNext() { + final boolean withinLimit = (null == end || index < end); + + if (!withinLimit && !truncate && iterator.hasNext()) { + // Throw an exception if we are - not within the limit, we don't want to truncate and there are items remaining. + throw new NoSuchElementException("Limit of " + end + " exceeded."); + } + + final boolean hasNext = withinLimit && iterator.hasNext(); + if (!hasNext) { + close(); + } + + return hasNext; + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + index++; + return iterator.next(); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterable.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterable.java new file mode 100644 index 00000000..75984b8b --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterable.java @@ -0,0 +1,48 @@ +/* + * 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.Iterator; +import java.util.List; +import java.util.function.Function; + +/** + * @param input type of items in the input iterator + * @param output type of items in the output iterator + */ +public class MappedIterable implements Closeable, Iterable { + private final Iterable iterable; + private final List functions; + + public MappedIterable(final Iterable iterable, final List functions) { + this.iterable = iterable; + this.functions = functions; + } + + @Override + public Iterator iterator() { + return new MappedIterator<>(iterable.iterator(), functions); + } + + @Override + public void close() { + CloseableUtil.close(iterable); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterator.java b/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterator.java new file mode 100644 index 00000000..0e6d722c --- /dev/null +++ b/core/src/main/java/uk/gov/gchq/koryphe/iterable/MappedIterator.java @@ -0,0 +1,59 @@ +/* + * 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.Iterator; +import java.util.List; +import java.util.function.Function; + +/** + * @param the type of items in the iterator + */ +public class MappedIterator implements Closeable, Iterator { + private final Iterator iterator; + private final List functions; + + public MappedIterator(final Iterator iterator, final List functions) { + this.iterator = iterator; + this.functions = functions; + } + + @Override + public boolean hasNext() { + return iterator.hasNext(); + } + + @Override + public O_ITEM next() { + Object item = iterator.next(); + try { + for (final Function function : functions) { + item = function.apply(item); + } + return (O_ITEM) item; + } catch (final ClassCastException c) { + throw new IllegalArgumentException("The input/output types of the functions were incompatible", c); + } + } + + @Override + public void close() { + CloseableUtil.close(iterator); + } +} diff --git a/core/src/main/java/uk/gov/gchq/koryphe/util/IterableUtil.java b/core/src/main/java/uk/gov/gchq/koryphe/util/IterableUtil.java index c9f5cbe6..4d5f6069 100644 --- a/core/src/main/java/uk/gov/gchq/koryphe/util/IterableUtil.java +++ b/core/src/main/java/uk/gov/gchq/koryphe/util/IterableUtil.java @@ -16,21 +16,16 @@ package uk.gov.gchq.koryphe.util; -import com.fasterxml.jackson.annotation.JsonIgnore; +import uk.gov.gchq.koryphe.iterable.ChainedIterable; +import uk.gov.gchq.koryphe.iterable.FilteredIterable; +import uk.gov.gchq.koryphe.iterable.LimitedIterable; +import uk.gov.gchq.koryphe.iterable.MappedIterable; -import uk.gov.gchq.koryphe.commonutil.iterable.ChainedIterable; -import uk.gov.gchq.koryphe.impl.predicate.And; - -import java.io.Closeable; import java.util.Collections; -import java.util.Iterator; import java.util.List; -import java.util.NoSuchElementException; import java.util.function.Function; import java.util.function.Predicate; -import static uk.gov.gchq.koryphe.util.JavaUtils.requireNonNullElse; - /** * An {@code IterableUtil} is a utility class providing capabilities for: *
    @@ -118,246 +113,4 @@ public static Iterable limit(final Iterable iterable, final int start, return new LimitedIterable<>(iterable, start, end, truncate); } - /** - * @param input type of items in the input iterator - * @param output type of items in the output iterator - */ - private static class MappedIterable implements Closeable, Iterable { - private final Iterable iterable; - private final List functions; - - MappedIterable(final Iterable iterable, final List functions) { - this.iterable = iterable; - this.functions = functions; - } - - @Override - public Iterator iterator() { - return new MappedIterator<>(iterable.iterator(), functions); - } - - @Override - public void close() { - CloseableUtil.close(iterable); - } - } - - /** - * @param the type of items in the iterator - */ - private static class MappedIterator implements Closeable, Iterator { - private final Iterator iterator; - private final List functions; - - MappedIterator(final Iterator iterator, final List functions) { - this.iterator = iterator; - this.functions = functions; - } - - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - - @Override - public O_ITEM next() { - Object item = iterator.next(); - try { - for (final Function function : functions) { - item = function.apply(item); - } - return (O_ITEM) item; - } catch (final ClassCastException c) { - throw new IllegalArgumentException("The input/output types of the functions were incompatible", c); - } - } - - @Override - public void close() { - CloseableUtil.close(iterator); - } - } - - /** - * @param the type of items in the iterator - */ - private static class FilteredIterable implements Closeable, Iterable { - private final Iterable iterable; - private final List predicates; - - FilteredIterable(final Iterable iterable, final List predicates) { - this.iterable = iterable; - this.predicates = predicates; - } - - @Override - public Iterator iterator() { - return new FilteredIterator<>(iterable.iterator(), predicates); - } - - @Override - public void close() { - CloseableUtil.close(iterable); - } - } - - /** - * @param the type of items in the iterator - */ - private static class FilteredIterator implements Closeable, Iterator { - private final Iterator iterator; - private final And andPredicate; - - FilteredIterator(final Iterator iterator, final List predicates) { - 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); - } - } - - /** - * @param the type of items in the iterator - */ - private static final class LimitedIterable implements Closeable, Iterable { - private final Iterable iterable; - private final int start; - private final Integer end; - private final Boolean truncate; - - private LimitedIterable(final Iterable 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 iterator() { - return new LimitedIterator<>(iterable.iterator(), start, end, truncate); - } - } - - /** - * @param the type of items in the iterator - */ - private static final class LimitedIterator implements Closeable, Iterator { - private final Iterator iterator; - private final Integer end; - private int index = 0; - private Boolean truncate = true; - - private LimitedIterator(final Iterator iterator, final int start, final Integer end, final boolean truncate) { - if (null != end && start > end) { - throw new IllegalArgumentException("start should be less than end"); - } - - this.iterator = requireNonNullElse(iterator, Collections.emptyIterator()); - this.end = end; - this.truncate = truncate; - - while (index < start && hasNext()) { - next(); - } - } - - @Override - public void close() { - CloseableUtil.close(iterator); - } - - @Override - public boolean hasNext() { - final boolean withinLimit = (null == end || index < end); - - if (!withinLimit && !truncate && iterator.hasNext()) { - // Throw an exception if we are - not within the limit, we don't want to truncate and there are items remaining. - throw new NoSuchElementException("Limit of " + end + " exceeded."); - } - - final boolean hasNext = withinLimit && iterator.hasNext(); - if (!hasNext) { - close(); - } - - return hasNext; - } - - @Override - public T next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - - index++; - return iterator.next(); - } - } }