OPEN - issue BATCH-371: FlatFileItemWriter no longer uses LineAggregator

http://jira.springframework.org/browse/BATCH-371

Extend ItemTransformer implementations that deal with field sets and arrays
This commit is contained in:
dsyer
2008-02-21 09:15:51 +00:00
parent 30a5b28c03
commit ee0236d657
7 changed files with 467 additions and 273 deletions

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2006-2007 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.io.file.transform;
/**
* @author Dave Syer
*
*/
public class ConversionException extends RuntimeException {
/**
* @param msg
*/
public ConversionException(String msg) {
super(msg);
}
}

View File

@@ -49,10 +49,23 @@ public class LineAggregatorItemTransformer implements ItemTransformer {
}
/**
* @param item
* @return
* Extension point for subclasses. The default implementation just attempts
* to cast the item to String[] and creates a {@link DefaultFieldSet} from
* it.
*
* @param item an object (in this implementation of type String[]).
* @return a {@link FieldSet} representing the item
*
* @throws ConversionException if the field set cannot be created
*/
protected FieldSet createFieldSet(Object item) {
return new DefaultFieldSet((String[]) item);
protected FieldSet createFieldSet(Object item) throws ConversionException {
try {
return new DefaultFieldSet((String[]) item);
}
catch (ClassCastException e) {
throw new ConversionException(
"Item must be of type String[] for conversion to FieldSet. " +
"Consider overriding this method to specify a less generic algorithm.");
}
}
}

View File

@@ -6,10 +6,12 @@ import java.util.Iterator;
import org.springframework.batch.item.writer.ItemTransformer;
/**
* An implementation of {@link ItemTransformer} that just calls toString() on
* its argument, unless it it an array or collection, in which case it loops
* though, calling itself on each member in turn, concatenating the result with
* line separators.
* An implementation of {@link ItemTransformer} that treats its argument
* specially if it is an array or collection. In this case it loops though,
* calling itself on each member in turn, until it encounters a non collection.
* At this point, if the item is a String, that is used, or else it is passed to
* the delegate {@link ItemTransformer}. The transformed single item Strings
* are all concatenated with line separators.
*
* @author Dave Syer
*
@@ -18,18 +20,42 @@ public class RecursiveCollectionItemTransformer implements ItemTransformer {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
/* (non-Javadoc)
private ItemTransformer delegate = new ItemTransformer() {
public Object transform(Object item) throws Exception {
return item;
}
};
/**
* Public setter for the {@link ItemTransformer} to use on single items,
* that are not Strings. This can be used to strategise the conversion of
* collection and array elements to a String, e.g. via a subclass of
* {@link LineAggregatorItemTransformer}.<br/>
*
* N.B. if the delegate returns an array or collection, it will not be
* treated the same way as the original item passed in for transformation.
* Rather, in this case, it will simply be converted immediately to a String
* by calling its toString().
*
* @param delegate the delegate to set. Defaults to a pass through.
*/
public void setDelegate(ItemTransformer delegate) {
this.delegate = delegate;
}
/*
* (non-Javadoc)
* @see org.springframework.batch.item.writer.ItemTransformer#transform(java.lang.Object)
*/
public Object transform(Object input) {
public Object transform(Object input) throws Exception {
TransformHolder holder = new TransformHolder();
transformRecursively(input, holder);
String result = holder.builder.toString();
return result.substring(0, result.lastIndexOf(LINE_SEPARATOR));
}
public String stringify(Object input) {
return "" + input;
public String stringify(Object item) throws Exception {
return "" + delegate.transform(item);
}
/**
@@ -38,10 +64,9 @@ public class RecursiveCollectionItemTransformer implements ItemTransformer {
* @param converted
* @throws Exception
*/
private void transformRecursively(Object data, TransformHolder converted) {
private void transformRecursively(Object data, TransformHolder converted) throws Exception {
if (data instanceof Collection) {
converted.value = false;
for (Iterator iterator = ((Collection) data).iterator(); iterator.hasNext();) {
Object value = (Object) iterator.next();
// (recursive)
@@ -50,7 +75,6 @@ public class RecursiveCollectionItemTransformer implements ItemTransformer {
return;
}
if (data.getClass().isArray()) {
converted.value = false;
Object[] array = (Object[]) data;
for (int i = 0; i < array.length; i++) {
Object value = array[i];
@@ -63,21 +87,14 @@ public class RecursiveCollectionItemTransformer implements ItemTransformer {
// This is where the output stream is actually written to
converted.builder.append(data + LINE_SEPARATOR);
}
else if (!converted.value) {
else {
// (recursive)
converted.value = true;
transformRecursively(stringify(data), converted);
return;
}
else {
// Should not happen...
throw new IllegalStateException(
"Infinite loop detected - converter did not convert to String or collection/array of objects convertible to String.");
}
}
private static class TransformHolder {
boolean value;
StringBuilder builder = new StringBuilder();