OPEN - issue BATCH-770: Make ItemTransformer a first class citizen and rename as ItemProcessor
Done first pass. Some tests needed.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package org.springframework.batch.item;
|
||||
|
||||
/**
|
||||
* Interface for item transformations. If the return value is null it may be
|
||||
* ignored, so this interface is also able to act as a filter.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public interface ItemProcessor<I, O> {
|
||||
|
||||
O process(I item) throws Exception;
|
||||
}
|
||||
@@ -1,30 +1,31 @@
|
||||
package org.springframework.batch.item.transform;
|
||||
package org.springframework.batch.item.support;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Composite {@link ItemTransformer} that passes the item through a sequence of
|
||||
* Composite {@link ItemProcessor} that passes the item through a sequence of
|
||||
* injected <code>ItemTransformer</code>s (return value of previous
|
||||
* transformation is the entry value of the next).
|
||||
*
|
||||
* Note the user is responsible for injecting a chain of {@link ItemTransformer}
|
||||
* Note the user is responsible for injecting a chain of {@link ItemProcessor}
|
||||
* s that conforms to declared input and output types.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class CompositeItemTransformer<I, O> implements ItemTransformer<I, O>, InitializingBean {
|
||||
public class CompositeItemProcessor<I, O> implements ItemProcessor<I, O>, InitializingBean {
|
||||
|
||||
private List<ItemTransformer> itemTransformers;
|
||||
private List<ItemProcessor> itemTransformers;
|
||||
|
||||
public O transform(I item) throws Exception {
|
||||
public O process(I item) throws Exception {
|
||||
Object result = item;
|
||||
|
||||
for(ItemTransformer transformer: itemTransformers){
|
||||
result = transformer.transform(result);
|
||||
for(ItemProcessor transformer: itemTransformers){
|
||||
result = transformer.process(result);
|
||||
}
|
||||
return (O) result;
|
||||
}
|
||||
@@ -37,7 +38,7 @@ public class CompositeItemTransformer<I, O> implements ItemTransformer<I, O>, In
|
||||
* @param itemTransformers will be chained to produce a composite
|
||||
* transformation.
|
||||
*/
|
||||
public void setItemTransformers(List<ItemTransformer> itemTransformers) {
|
||||
public void setItemTransformers(List<ItemProcessor> itemTransformers) {
|
||||
this.itemTransformers = itemTransformers;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.springframework.batch.item.support;
|
||||
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class PassthroughItemProcessor<T> implements ItemProcessor<T, T> {
|
||||
public T process(T item) throws Exception {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.springframework.batch.item.transform;
|
||||
|
||||
/**
|
||||
* Interface for item transformations during processing phase.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public interface ItemTransformer<I,O> {
|
||||
|
||||
O transform(I item) throws Exception;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.springframework.batch.item.transform;
|
||||
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.support.DelegatingItemWriter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Transforms the item using injected {@link ItemTransformer}
|
||||
* before it is written to output by {@link ItemWriter}.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class ItemTransformerItemWriter<I,O> extends DelegatingItemWriter<I,O> {
|
||||
|
||||
private ItemTransformer<? super I,? extends O> itemTransformer;
|
||||
|
||||
/**
|
||||
* Transform the item using the {@link #setItemTransformer(ItemTransformer)}.
|
||||
*/
|
||||
protected O doProcess(I item) throws Exception {
|
||||
return itemTransformer.transform(item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemTransformer will transform the item before
|
||||
* it is passed to {@link ItemWriter}.
|
||||
*/
|
||||
public void setItemTransformer(ItemTransformer<? super I,? extends O> itemTransformer) {
|
||||
this.itemTransformer = itemTransformer;
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(itemTransformer);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Writer implementation concerned with item transformation before writing.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.springframework.batch.item.transform;
|
||||
package org.springframework.batch.item.support;
|
||||
|
||||
import static org.easymock.EasyMock.createMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
@@ -11,26 +11,28 @@ import java.util.ArrayList;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.batch.item.support.CompositeItemProcessor;
|
||||
|
||||
/**
|
||||
* Tests for {@link CompositeItemTransformer}.
|
||||
* Tests for {@link CompositeItemProcessor}.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class CompositeItemTransformerTests {
|
||||
public class CompositeItemProcessorTests {
|
||||
|
||||
private CompositeItemTransformer<Object, Object> composite = new CompositeItemTransformer<Object, Object>();
|
||||
private CompositeItemProcessor<Object, Object> composite = new CompositeItemProcessor<Object, Object>();
|
||||
|
||||
private ItemTransformer<Object, Object> transformer1;
|
||||
private ItemTransformer<Object, Object> transformer2;
|
||||
private ItemProcessor<Object, Object> transformer1;
|
||||
private ItemProcessor<Object, Object> transformer2;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
transformer1 = createMock(ItemTransformer.class);
|
||||
transformer2 = createMock(ItemTransformer.class);
|
||||
transformer1 = createMock(ItemProcessor.class);
|
||||
transformer2 = createMock(ItemProcessor.class);
|
||||
|
||||
composite.setItemTransformers(new ArrayList<ItemTransformer>() {{
|
||||
composite.setItemTransformers(new ArrayList<ItemProcessor>() {{
|
||||
add(transformer1); add(transformer2);
|
||||
}});
|
||||
|
||||
@@ -47,14 +49,14 @@ public class CompositeItemTransformerTests {
|
||||
Object itemAfterFirstTransfromation = new Object();
|
||||
Object itemAfterSecondTransformation = new Object();
|
||||
|
||||
expect(transformer1.transform(item)).andReturn(itemAfterFirstTransfromation);
|
||||
expect(transformer1.process(item)).andReturn(itemAfterFirstTransfromation);
|
||||
|
||||
expect(transformer2.transform(itemAfterFirstTransfromation)).andReturn(itemAfterSecondTransformation);
|
||||
expect(transformer2.process(itemAfterFirstTransfromation)).andReturn(itemAfterSecondTransformation);
|
||||
|
||||
replay(transformer1);
|
||||
replay(transformer2);
|
||||
|
||||
assertSame(itemAfterSecondTransformation, composite.transform(item));
|
||||
assertSame(itemAfterSecondTransformation, composite.process(item));
|
||||
|
||||
verify(transformer1);
|
||||
verify(transformer2);
|
||||
@@ -62,7 +64,7 @@ public class CompositeItemTransformerTests {
|
||||
|
||||
/**
|
||||
* The list of transformers must not be null or empty and
|
||||
* can contain only instances of {@link ItemTransformer}.
|
||||
* can contain only instances of {@link ItemProcessor}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
@@ -79,7 +81,7 @@ public class CompositeItemTransformerTests {
|
||||
}
|
||||
|
||||
// empty list
|
||||
composite.setItemTransformers(new ArrayList<ItemTransformer>());
|
||||
composite.setItemTransformers(new ArrayList<ItemProcessor>());
|
||||
try {
|
||||
composite.afterPropertiesSet();
|
||||
fail();
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2006-2008 the original author or authors.
|
||||
*
|
||||
* 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 org.springframework.batch.item.transform;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.item.ClearFailedException;
|
||||
import org.springframework.batch.item.FlushFailedException;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* These functional tests were created for the Reference Documentation and show how various
|
||||
* combinations of ItemTransformer can be used with an ItemTransformerItemWriter.
|
||||
*
|
||||
* @author Lucas Ward
|
||||
*
|
||||
*/
|
||||
public class ItemTransformerItemWriterFunctionalTests extends TestCase {
|
||||
|
||||
public void testTransform() throws Exception{
|
||||
|
||||
ItemTransformerItemWriter<Foo, Bar> itemTransformerItemWriter = new ItemTransformerItemWriter<Foo, Bar>();
|
||||
itemTransformerItemWriter.setItemTransformer(new FooTransformer());
|
||||
itemTransformerItemWriter.setDelegate(new BarWriter());
|
||||
itemTransformerItemWriter.write(new Foo());
|
||||
}
|
||||
|
||||
|
||||
public void testComposite() throws Exception{
|
||||
|
||||
CompositeItemTransformer<Foo, Foobar> compositeTransformer = new CompositeItemTransformer<Foo, Foobar>();
|
||||
|
||||
@SuppressWarnings("unchecked") List<ItemTransformer> itemTransformers = new ArrayList<ItemTransformer>();
|
||||
itemTransformers.add(new FooTransformer());
|
||||
itemTransformers.add(new BarTransformer());
|
||||
compositeTransformer.setItemTransformers(itemTransformers);
|
||||
ItemTransformerItemWriter<Foo, Foobar> itemTransformerItemWriter = new ItemTransformerItemWriter<Foo, Foobar>();
|
||||
itemTransformerItemWriter.setItemTransformer(compositeTransformer);
|
||||
itemTransformerItemWriter.setDelegate(new FoobarWriter());
|
||||
itemTransformerItemWriter.write(new Foo());
|
||||
}
|
||||
|
||||
private static class Foo {
|
||||
|
||||
}
|
||||
|
||||
private static class Bar {
|
||||
public Bar(Foo foo) {
|
||||
}
|
||||
}
|
||||
|
||||
private static class Foobar{
|
||||
public Foobar(Bar bar){}
|
||||
}
|
||||
|
||||
public class FooTransformer implements ItemTransformer<Foo, Bar>{
|
||||
|
||||
//Preform simple transformation, convert a Foo to a Barr
|
||||
public Bar transform(Foo foo) throws Exception {
|
||||
return new Bar(foo);
|
||||
}
|
||||
}
|
||||
|
||||
public class BarTransformer implements ItemTransformer<Bar, Foobar>{
|
||||
|
||||
public Foobar transform(Bar bar) throws Exception {
|
||||
return new Foobar(bar);
|
||||
}
|
||||
}
|
||||
|
||||
private static class BarWriter implements ItemWriter<Bar>{
|
||||
|
||||
public void write(Bar item) throws Exception {
|
||||
assertTrue(item instanceof Bar);
|
||||
}
|
||||
|
||||
public void clear() throws ClearFailedException {
|
||||
}
|
||||
|
||||
public void flush() throws FlushFailedException {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class FoobarWriter implements ItemWriter<Foobar>{
|
||||
|
||||
public void write(Foobar item) throws Exception {
|
||||
assertTrue(item instanceof Foobar);
|
||||
}
|
||||
|
||||
public void clear() throws ClearFailedException {
|
||||
}
|
||||
|
||||
public void flush() throws FlushFailedException {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package org.springframework.batch.item.transform;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.easymock.EasyMock;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
|
||||
/**
|
||||
* Tests for {@link ItemTransformerItemWriter}.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class ItemTransformerItemWriterTests {
|
||||
|
||||
private ItemTransformerItemWriter<Object, Object> processor = new ItemTransformerItemWriter<Object, Object>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ItemTransformer<Object, Object> transformer = EasyMock.createMock(ItemTransformer.class);
|
||||
@SuppressWarnings("unchecked")
|
||||
private ItemWriter<Object> itemWriter = EasyMock.createMock(ItemWriter.class);
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
processor.setItemTransformer(transformer);
|
||||
processor.setDelegate(itemWriter);
|
||||
processor.afterPropertiesSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Regular usage scenario - item is passed to transformer
|
||||
* and the result of transformation is passed to output source.
|
||||
*/
|
||||
@Test
|
||||
public void testProcess() throws Exception {
|
||||
Object item = new Object();
|
||||
Object itemAfterTransformation = new Object();
|
||||
|
||||
EasyMock.expect(transformer.transform(item)).andReturn(itemAfterTransformation);
|
||||
|
||||
itemWriter.write(itemAfterTransformation);
|
||||
EasyMock.expectLastCall();
|
||||
|
||||
EasyMock.replay(itemWriter, transformer);
|
||||
|
||||
processor.write(item);
|
||||
|
||||
EasyMock.verify(itemWriter, transformer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Item transformer must be set.
|
||||
*/
|
||||
@Test
|
||||
public void testAfterPropertiesSet() throws Exception {
|
||||
|
||||
// value not set
|
||||
processor.setItemTransformer(null);
|
||||
try {
|
||||
processor.afterPropertiesSet();
|
||||
fail();
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user