Skip to content

Commit ea378b9

Browse files
committed
Add adapters for Java functional interfaces
Resolves #4672
1 parent 3758f86 commit ea378b9

File tree

6 files changed

+308
-0
lines changed

6 files changed

+308
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.function.Consumer;
19+
20+
import org.springframework.batch.item.Chunk;
21+
import org.springframework.batch.item.ItemWriter;
22+
import org.springframework.util.Assert;
23+
24+
/**
25+
* Adapter for a {@link Consumer} to an {@link ItemWriter}.
26+
*
27+
* @param <T> type of items to write
28+
* @author Mahmoud Ben Hassine
29+
* @since 5.2
30+
*/
31+
public class ConsumerItemWriter<T> implements ItemWriter<T> {
32+
33+
private final Consumer<T> consumer;
34+
35+
/**
36+
* Create a new {@link ConsumerItemWriter}.
37+
* @param consumer the consumer to use to write items. Must not be {@code null}.
38+
*/
39+
public ConsumerItemWriter(Consumer<T> consumer) {
40+
Assert.notNull(consumer, "A consumer is required");
41+
this.consumer = consumer;
42+
}
43+
44+
@Override
45+
public void write(Chunk<? extends T> items) throws Exception {
46+
items.forEach(this.consumer);
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.function.Predicate;
19+
20+
import org.springframework.batch.item.ItemProcessor;
21+
import org.springframework.util.Assert;
22+
23+
/**
24+
* A filtering {@link ItemProcessor} that is based on a {@link Predicate}. Items for which
25+
* the predicate returns {@code true} will be filtered.
26+
*
27+
* @param <T> type of item to process
28+
* @author Mahmoud Ben Hassine
29+
* @since 5.2
30+
*/
31+
public class PredicateFilteringItemProcessor<T> implements ItemProcessor<T, T> {
32+
33+
private final Predicate<T> predicate;
34+
35+
/**
36+
* Create a new {@link PredicateFilteringItemProcessor}.
37+
* @param predicate the predicate to use to filter items. Must not be {@code null}.
38+
*/
39+
public PredicateFilteringItemProcessor(Predicate<T> predicate) {
40+
Assert.notNull(predicate, "A predicate is required");
41+
this.predicate = predicate;
42+
}
43+
44+
@Override
45+
public T process(T item) throws Exception {
46+
return this.predicate.test(item) ? null : item;
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.function.Supplier;
19+
20+
import org.springframework.batch.item.ItemReader;
21+
import org.springframework.util.Assert;
22+
23+
/**
24+
* Adapter for a {@link Supplier} to an {@link ItemReader}.
25+
*
26+
* @param <T> type of items to read
27+
* @author Mahmoud Ben Hassine
28+
* @since 5.2
29+
*/
30+
public class SupplierItemReader<T> implements ItemReader<T> {
31+
32+
private final Supplier<T> supplier;
33+
34+
/**
35+
* Create a new {@link SupplierItemReader}.
36+
* @param supplier the supplier to use to read items. Must not be {@code null}.
37+
*/
38+
public SupplierItemReader(Supplier<T> supplier) {
39+
Assert.notNull(supplier, "A supplier is required");
40+
this.supplier = supplier;
41+
}
42+
43+
@Override
44+
public T read() throws Exception {
45+
return this.supplier.get();
46+
}
47+
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
import java.util.function.Consumer;
21+
22+
import org.junit.jupiter.api.Assertions;
23+
import org.junit.jupiter.api.Test;
24+
25+
import org.springframework.batch.item.Chunk;
26+
27+
/**
28+
* Test class for {@link ConsumerItemWriter}.
29+
*
30+
* @author Mahmoud Ben Hassine
31+
*/
32+
class ConsumerItemWriterTests {
33+
34+
private final List<String> items = new ArrayList<>();
35+
36+
private final Consumer<String> consumer = items::add;
37+
38+
@Test
39+
void testMandatoryConsumer() {
40+
Assertions.assertThrows(IllegalArgumentException.class, () -> new ConsumerItemWriter<String>(null),
41+
"A consumer is required");
42+
}
43+
44+
@Test
45+
void testWrite() throws Exception {
46+
// given
47+
Chunk<String> chunk = Chunk.of("foo", "bar");
48+
ConsumerItemWriter<String> consumerItemWriter = new ConsumerItemWriter<>(this.consumer);
49+
50+
// when
51+
consumerItemWriter.write(chunk);
52+
53+
// then
54+
Assertions.assertIterableEquals(chunk, this.items);
55+
}
56+
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.function.Predicate;
19+
20+
import org.junit.jupiter.api.Assertions;
21+
import org.junit.jupiter.api.Test;
22+
23+
/**
24+
* Test class for {@link PredicateFilteringItemProcessor}.
25+
*
26+
* @author Mahmoud Ben Hassine
27+
*/
28+
class PredicateFilteringItemProcessorTests {
29+
30+
private final Predicate<String> foos = item -> item.startsWith("foo");
31+
32+
@Test
33+
void testMandatoryPredicate() {
34+
Assertions.assertThrows(IllegalArgumentException.class, () -> new PredicateFilteringItemProcessor<String>(null),
35+
"A predicate is required");
36+
}
37+
38+
@Test
39+
void testProcess() throws Exception {
40+
// given
41+
PredicateFilteringItemProcessor<String> processor = new PredicateFilteringItemProcessor<>(this.foos);
42+
43+
// when & then
44+
Assertions.assertNull(processor.process("foo1"));
45+
Assertions.assertNull(processor.process("foo2"));
46+
Assertions.assertEquals("bar", processor.process("bar"));
47+
}
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.item.function;
17+
18+
import java.util.function.Supplier;
19+
20+
import org.junit.jupiter.api.Assertions;
21+
import org.junit.jupiter.api.Test;
22+
23+
/**
24+
* Test class for {@link SupplierItemReader}.
25+
*
26+
* @author Mahmoud Ben Hassine
27+
*/
28+
class SupplierItemReaderTests {
29+
30+
private final Supplier<String> supplier = new Supplier<>() {
31+
private int count = 1;
32+
33+
@Override
34+
public String get() {
35+
return count <= 2 ? "foo" + count++ : null;
36+
}
37+
};
38+
39+
@Test
40+
void testMandatorySupplier() {
41+
Assertions.assertThrows(IllegalArgumentException.class, () -> new SupplierItemReader<String>(null),
42+
"A supplier is required");
43+
}
44+
45+
@Test
46+
void testRead() throws Exception {
47+
// given
48+
SupplierItemReader<String> supplierItemReader = new SupplierItemReader<>(supplier);
49+
50+
// when & then
51+
Assertions.assertEquals("foo1", supplierItemReader.read());
52+
Assertions.assertEquals("foo2", supplierItemReader.read());
53+
Assertions.assertNull(supplierItemReader.read());
54+
}
55+
56+
}

0 commit comments

Comments
 (0)