[ 
https://issues.apache.org/jira/browse/COLLECTIONS-890?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18090189#comment-18090189
 ] 

Gary D. Gregory commented on COLLECTIONS-890:
---------------------------------------------

[~rickydong] 

Please see my comments in the PR.

TY.

> TransformIterator documents null transformers as pass-through, but next() 
> throws NullPointerException
> -----------------------------------------------------------------------------------------------------
>
>                 Key: COLLECTIONS-890
>                 URL: https://issues.apache.org/jira/browse/COLLECTIONS-890
>             Project: Commons Collections
>          Issue Type: Bug
>          Components: Iterator
>            Reporter: Ruiqi Dong
>            Priority: Minor
>
> *Summary*
> `TransformIterator` documents the same contract in three places:
> - constructor: null transformer means elements will not be transformed
> - `next()`: null transformer means the original element is returned directly
> - `setTransformer(...)`: null transformer is a no-op transformer
> The implementation does not honor that contract. `next()` always calls 
> `transformer.apply(...)`, so a null transformer causes an immediate 
> `NullPointerException`.
>  
> *Affected code*
> File: 
> `src/main/java/org/apache/commons/collections4/iterators/TransformIterator.java`
> {code:java}
> public TransformIterator(final Iterator<? extends I> iterator,
>                          final Transformer<? super I, ? extends O> 
> transformer) {
>     this.iterator = iterator;
>     this.transformer = transformer;
> }
> @Override
> public O next() {
>     return transform(iterator.next());
> }
> protected O transform(final I source) {
>     return transformer.apply(source);
> } {code}
> The same class also states:
> {code:java}
> // constructor Javadoc
> // If the given transformer is null, then objects will not be transformed.
> // next() Javadoc
> // If the transformer is null, no transformation occurs and the object
> // from the iterator is returned directly.
> // setTransformer(...) Javadoc
> // A null transformer is a no-op transformer. {code}
> *Reproducer*
> Add the following test to 
> `src/test/java/org/apache/commons/collections4/iterators/TransformIteratorTest.java`:
> {code:java}
> @Test
> void testNullTransformerActsAsPassThrough() {
>     final TransformIterator<Integer, Integer> iterator =
>             new TransformIterator<>(Arrays.asList(1, 2).iterator(), null);
>     assertEquals(Integer.valueOf(1), iterator.next());
>     assertEquals(Integer.valueOf(2), iterator.next());
> } {code}
> Run:
> {code:java}
> mvn -q 
> -Dtest=org.apache.commons.collections4.iterators.TransformIteratorTest#testNullTransformerActsAsPassThrough
>  test {code}
> *Observed behavior*
> {code:java}
> java.lang.NullPointerException:
> Cannot invoke "org.apache.commons.collections4.Transformer.apply(Object)"
> because "this.transformer" is null {code}
> *Expected behavior*
> When the transformer is null, the iterator should behave as an identity 
> transform and return the original elements unchanged.
> This is not just an undocumented corner case. The public Javadoc explicitly 
> promises null-as-pass-through behavior, but the implementation 
> unconditionally dereferences the transformer. Callers following the 
> documented contract get a runtime failure instead of the advertised semantics.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to