TransformIterable implements CloseableIterable<O> { @Override public CloseableIterator<O> iterator() { return new CloseableIterator<O>() { @Override public void close() { CloseableUtil.close(inputItr); } private final Iterator<? extends I> inputItr = input.iterator(); private O nextElement; private Boolean hasNext; @Override public boolean hasNext() { if (null == hasNext) { while (inputItr.hasNext()) { final I possibleNext = inputItr.next(); if (validator.validate(possibleNext)) { nextElement = transform(possibleNext); hasNext = true; return Boolean.TRUE.equals(hasNext); } else if (skipInvalid) { continue; } else { handleInvalidItem(possibleNext); } } hasNext = false; nextElement = null; } final boolean hasNextResult = Boolean.TRUE.equals(hasNext); if (autoClose && !hasNextResult) { close(); } return hasNextResult; } @Override public O next() { if ((null == hasNext) && (!hasNext())) { throw new NoSuchElementException("Reached the end of the iterator"); } final O elementToReturn = nextElement; nextElement = null; hasNext = null; return elementToReturn; } @Override public void remove() { throw new UnsupportedOperationException("Cannot call remove on a " + getIterableClass().getSimpleName() + " iterator"); } }; } TransformIterable(final Iterable<? extends I> input);  TransformIterable(final Iterable<? extends I> input, final Validator<I> validator);  TransformIterable(final Iterable<? extends I> input, final Validator<I> validator, final boolean skipInvalid);  TransformIterable(final Iterable<? extends I> input, final Validator<I> validator, final boolean skipInvalid, final boolean autoClose); @Override CloseableIterator<O> iterator(); @Override void close();  }
@Test public void shouldCreateIteratorThatReturnsOnlyValidStrings() { final String item1 = "valid item 1"; final String item2 = "invalid item 2"; final String item3 = "valid item 3"; final Iterable<String> items = Arrays.asList(item1, item2, item3); final Validator<String> validator = mock(Validator.class); final TransformIterable iterable = new TransformIterableImpl(items, validator, true); final Iterator<String> itr = iterable.iterator(); given(validator.validate(item1)).willReturn(true); given(validator.validate(item2)).willReturn(false); given(validator.validate(item3)).willReturn(true); assertTrue(itr.hasNext()); assertEquals("VALID ITEM 1", itr.next()); assertTrue(itr.hasNext()); assertEquals("VALID ITEM 3", itr.next()); }
@Test public void shouldThrowIAXExceptionWhenNextItemIsInvalidString() { final String item1 = "valid item 1"; final String item2 = "invalid item 2 invalid"; final String item3 = "valid item 3"; final Iterable<String> items = Arrays.asList(item1, item2, item3); final Validator<String> validator = mock(Validator.class); final TransformIterable iterable = new TransformIterableImpl(items, validator, false); final Iterator<String> itr = iterable.iterator(); given(validator.validate(item1)).willReturn(true); given(validator.validate(item2)).willReturn(false); given(validator.validate(item3)).willReturn(true); assertTrue(itr.hasNext()); assertEquals("VALID ITEM 1", itr.next()); assertThrows(IllegalArgumentException.class, () -> itr.hasNext()); }
@Test public void shouldThrowNoElementExceptionWhenNextCalledWhenNoNextString() { final String item1 = "item 1"; final Iterable<String> items = Arrays.asList(item1); final Validator<String> validator = mock(Validator.class); final TransformIterable iterable = new TransformIterableImpl(items, validator); final Iterator<String> itr = iterable.iterator(); given(validator.validate(item1)).willReturn(true); assertEquals("ITEM 1", itr.next()); assertThrows(NoSuchElementException.class, () -> itr.next()); }
@Test public void shouldThrowExceptionIfRemoveCalled() { final String item1 = "item 1"; final String item2 = "item 2"; final Iterable<String> items = Arrays.asList(item1, item2); final Validator<String> validator = mock(Validator.class); final TransformIterable iterable = new TransformIterableImpl(items, validator); final Iterator<String> itr = iterable.iterator(); given(validator.validate(item1)).willReturn(true); given(validator.validate(item2)).willReturn(true); assertThrows(UnsupportedOperationException.class, () -> itr.remove()); }