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:
dsyer
2008-08-11 08:48:41 +00:00
parent 8c12cd8b10
commit d4d35cd668
27 changed files with 394 additions and 473 deletions

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -1,7 +0,0 @@
<html>
<body>
<p>
Writer implementation concerned with item transformation before writing.
</p>
</body>
</html>

View File

@@ -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();

View File

@@ -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 {
}
}
}

View File

@@ -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
}
}
}