diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java index 93be62415..f28a3f9d6 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/FlatFileItemWriter.java @@ -37,8 +37,6 @@ import org.springframework.batch.item.MarkFailedException; import org.springframework.batch.item.ResetFailedException; import org.springframework.batch.item.WriterNotOpenException; import org.springframework.batch.item.file.mapping.FieldSet; -import org.springframework.batch.item.file.mapping.FieldSetCreator; -import org.springframework.batch.item.file.transform.DelimitedLineAggregator; import org.springframework.batch.item.file.transform.LineAggregator; import org.springframework.batch.item.util.ExecutionContextUserSupport; import org.springframework.batch.item.util.FileUtils; @@ -78,9 +76,7 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement private OutputState state = null; - private LineAggregator lineAggregator = new DelimitedLineAggregator(); - - private FieldSetCreator fieldSetCreator; + private LineAggregator lineAggregator; private boolean saveState = true; @@ -101,12 +97,12 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement } /** - * Assert that mandatory properties (resource) are set. + * Assert that mandatory properties (lineAggregator) are set. * * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() */ public void afterPropertiesSet() throws Exception { - Assert.notNull(fieldSetCreator, "A FieldSetCreator must be provided."); + Assert.notNull(lineAggregator, "A LineAggregator must be provided."); } /** @@ -124,21 +120,10 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement * * @param lineAggregator the {@link LineAggregator} to set */ - public void setLineAggregator(LineAggregator lineAggregator) { + public void setLineAggregator(LineAggregator lineAggregator) { this.lineAggregator = lineAggregator; } - /** - * Public setter for the {@link FieldSetCreator}. This will be used to - * transform the item into a {@link FieldSet} before it is aggregated by the - * {@link LineAggregator}. - * - * @param fieldSetCreator the {@link FieldSetCreator} to set - */ - public void setFieldSetCreator(FieldSetCreator fieldSetCreator) { - this.fieldSetCreator = fieldSetCreator; - } - /** * Setter for resource. Represents a file that can be written. * @@ -208,8 +193,7 @@ public class FlatFileItemWriter extends ExecutionContextUserSupport implement */ public void write(T item) throws Exception { if (getOutputState().isInitialized()) { - FieldSet fieldSet = fieldSetCreator.mapItem(item); - lineBuffer.add(lineAggregator.aggregate(fieldSet) + lineSeparator); + lineBuffer.add(lineAggregator.aggregate(item) + lineSeparator); } else { throw new WriterNotOpenException("Writer must be open before it can be written to"); diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetCreator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetCreator.java deleted file mode 100644 index 5e926f674..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/FieldSetCreator.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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.item.file.mapping; - -import org.springframework.batch.item.file.transform.LineTokenizer; - -/** - * Strategy interface for mapping between arbitrary objects and {@link FieldSet}. - * Similar to a {@link LineTokenizer}, but the input is generally a domain - * object, not a String. - * - * @author Dave Syer - * - */ -public interface FieldSetCreator { - - /** - * @param data an Object to convert. - * @return a {@link FieldSet} created from the input. - */ - FieldSet mapItem(T data); - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreator.java deleted file mode 100644 index 949476646..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreator.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.springframework.batch.item.file.mapping; - -public class PassThroughFieldSetCreator implements FieldSetCreator { - - /** - * If the input is a {@link FieldSet} pass it to the caller. Otherwise - * convert to a String with toString() and convert it to a single field - * {@link FieldSet}. - * - * @see org.springframework.batch.item.file.mapping.FieldSetCreator#mapItem(java.lang.Object) - */ - public FieldSet mapItem(T item) { - if (item instanceof FieldSet) { - return (FieldSet) item; - } - - String stringItem = item.toString(); - - return new DefaultFieldSet(new String[] { stringItem }); - } - -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java deleted file mode 100644 index 8ac8b7bb6..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/DelimitedLineAggregator.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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.item.file.transform; - -import org.springframework.batch.item.file.mapping.FieldSet; - - -/** - * Class used to create string representing object. Values are separated by - * defined delimiter. - * - * @author tomas.slanina - * - */ -public class DelimitedLineAggregator implements LineAggregator { - private String delimiter = ","; - - /** - * Method used to create string representing object. - * - * @param fieldSet arrays of strings representing data to be stored - */ - public String aggregate(FieldSet fieldSet) { - StringBuffer buffer = new StringBuffer(); - String[] args = fieldSet.getValues(); - for (int i = 0; i < args.length; i++) { - buffer.append(args[i]); - - if (i != (args.length - 1)) { - buffer.append(delimiter); - } - } - - return buffer.toString(); - } - - /** - * Sets the character to be used as a delimiter. - */ - public void setDelimiter(String delimiter) { - this.delimiter = delimiter; - } -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/StubLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java similarity index 59% rename from spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/StubLineAggregator.java rename to spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java index 9d351ca2e..53ed8a3b9 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/StubLineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FieldExtractor.java @@ -13,29 +13,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.batch.item.file.transform; -import org.springframework.batch.item.file.mapping.FieldSet; - - /** - * Stub implementation of {@link LineAggregator} interface for testing purposes. - * - * @author robert.kasanicky + * @author Dave Syer + * */ -public class StubLineAggregator implements LineAggregator { +public interface FieldExtractor { + + Object[] extract(T item); - /** - * Concatenates arguments. - */ - public String aggregate(FieldSet fieldSet) { - String result = ""; - - for (int i = 1; i < fieldSet.getFieldCount(); i++) { - result = result + fieldSet.readString(i); - } - - return result; - } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregator.java deleted file mode 100644 index 4a4c56580..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregator.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * 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.item.file.transform; - -import java.util.Arrays; - -import org.springframework.batch.item.file.mapping.FieldSet; -import org.springframework.util.Assert; - -/** - * {@link LineAggregator} implementation which produces line by aggregating provided - * strings into columns with fixed length. Columns are specified by array of - * ranges ({@link #setColumns(Range[])}.
- * - * @author tomas.slanina - * @author peter.zozom - * @author Dave Syer - */ -public class FixedLengthLineAggregator implements LineAggregator { - - private Range[] ranges; - - private int lastColumn; - - private Alignment align = Alignment.LEFT; - - private char padding = ' '; - - /** - * Set column ranges. Used in conjunction with the - * {@link RangeArrayPropertyEditor} this property can be set in the form of - * a String describing the range boundaries, e.g. "1,4,7" or "1-3,4-6,7" or - * "1-2,4-5,7-10". - * - * @param columns array of Range objects which specify column start and end - * position - */ - public void setColumns(Range[] columns) { - Assert.notNull(columns); - lastColumn = findLastColumn(columns); - this.ranges = columns; - } - - /** - * Aggregate provided strings into single line using specified column - * ranges. - * - * @param fieldSet arrays of strings representing data to be aggregated - * @return aggregated strings - */ - public String aggregate(FieldSet fieldSet) { - - Assert.notNull(fieldSet); - Assert.notNull(ranges); - - String[] args = fieldSet.getValues(); - Assert.isTrue(args.length <= ranges.length, "Number of arguments must match number of fields in a record"); - - // calculate line length - int lineLength = ranges[lastColumn].hasMaxValue() ? ranges[lastColumn].getMax() : ranges[lastColumn].getMin() - + args[lastColumn].length() - 1; - - // create stringBuffer with length of line filled with padding - // characters - char[] emptyLine = new char[lineLength]; - Arrays.fill(emptyLine, padding); - - StringBuffer stringBuffer = new StringBuffer(lineLength); - stringBuffer.append(emptyLine); - - // aggregate all strings - for (int i = 0; i < args.length; i++) { - - // offset where text will be inserted - int start = ranges[i].getMin() - 1; - - // calculate column length - int columnLength; - if ((i == lastColumn) && (!ranges[lastColumn].hasMaxValue())) { - columnLength = args[lastColumn].length(); - } - else { - columnLength = ranges[i].getMax() - ranges[i].getMin() + 1; - } - - String textToInsert = (args[i] == null) ? "" : args[i]; - - Assert.isTrue(columnLength >= textToInsert.length(), "Supplied text: " + textToInsert - + " is longer than defined length: " + columnLength); - - if (align == Alignment.RIGHT) { - start += (columnLength - textToInsert.length()); - } - else if (align == Alignment.CENTER) { - start += ((columnLength - textToInsert.length()) / 2); - } - - stringBuffer.replace(start, start + textToInsert.length(), textToInsert); - } - - return stringBuffer.toString(); - } - - /** - * Recognized alignments are CENTER, RIGHT, LEFT. An - * IllegalArgumentException is thrown in case the argument does not match - * any of the recognized values. - * - * @param alignment the alignment to be used - */ - public void setAlignment(Alignment alignment) { - this.align = alignment; - } - - /** - * Setter for padding (default is space). - * - * @param padding the padding character - */ - public void setPadding(char padding) { - this.padding = padding; - } - - /* - * Find last column. Columns are not sorted. Returns index of last column - * (column with highest offset). - */ - private int findLastColumn(Range[] columns) { - - int lastOffset = 1; - int lastIndex = 0; - - for (int i = 0; i < columns.length; i++) { - if (columns[i].getMin() > lastOffset) { - lastOffset = columns[i].getMin(); - lastIndex = i; - } - } - - return lastIndex; - } -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java new file mode 100644 index 000000000..8e9a7657e --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/FormatterLineAggregator.java @@ -0,0 +1,118 @@ +/* + * 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.item.file.transform; + +import java.util.Formatter; +import java.util.Locale; + +import org.springframework.util.Assert; + +/** + * A {@link LineAggregator} implementation which produces a String by + * aggregating the provided item via the {@link Formatter} syntax.
+ * + * @see Formatter + * + * @author Dave Syer + */ +public class FormatterLineAggregator implements LineAggregator { + + private String format; + + private FieldExtractor fieldExtractor = new PassThroughFieldExtractor(); + + private Locale locale = Locale.getDefault(); + + private int maximumLength = 0; + + private int minimumLength = 0; + + /** + * Public setter for the minimum length of the formatted string. If this is + * not set the default is to allow any length. + * + * @param minimumLength the minimum length to set + */ + public void setMinimumLength(int minimumLength) { + this.minimumLength = minimumLength; + } + + /** + * Public setter for the maximum length of the formatted string. If this is + * not set the default is to allow any length. + * @param maximumLength the maximum length to set + */ + public void setMaximumLength(int maximumLength) { + this.maximumLength = maximumLength; + } + + /** + * Set the format string used to aggregate items. + * + * @see Formatter + */ + public void setFormat(String format) { + this.format = format; + } + + /** + * Public setter for the field extractor responsible for splitting an input + * object up into an array of objects. Defaults to + * {@link PassThroughFieldExtractor}. + * + * @param fieldExtractor the field extractor to set + */ + public void setFieldExtractor(FieldExtractor fieldExtractor) { + this.fieldExtractor = fieldExtractor; + } + + /** + * Public setter for the locale. + * @param locale the locale to set + */ + public void setLocale(Locale locale) { + this.locale = locale; + } + + /** + * Aggregate provided item into single line using specified format. + * + * @param item data to be aggregated + * @return aggregated string + */ + public String aggregate(T item) { + + Assert.notNull(item); + Assert.notNull(format); + + Object[] args = fieldExtractor.extract(item); + + String value = String.format(locale, format, args); + + if (maximumLength > 0) { + Assert.state(value.length() <= maximumLength, String.format("String overflowed in formatter -" + + " longer than %d characters: [%s", maximumLength, value)); + } + + if (minimumLength > 0) { + Assert.state(value.length() >= minimumLength, String.format("String underflowed in formatter -" + + " shorter than %d characters: [%s", minimumLength, value)); + } + + return value; + } +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java index 6fc828a5a..45f06a788 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregator.java @@ -16,20 +16,19 @@ package org.springframework.batch.item.file.transform; -import org.springframework.batch.item.file.mapping.FieldSet; /** - * Interface used to create string used to create string representing object. + * Interface used to create string representing object. * - * @author tomas.slanina + * @author Dave Syer */ -public interface LineAggregator { +public interface LineAggregator { /** - * Method used to create a string to be stored from the array of values. + * Create a string from the value provided. * - * @param fieldSet values to be converted + * @param item values to be converted * @return string */ - public String aggregate(FieldSet fieldSet); + public String aggregate(T item); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregatorItemTransformer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregatorItemTransformer.java deleted file mode 100644 index e31fef391..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/LineAggregatorItemTransformer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.item.file.transform; - -import org.springframework.batch.item.file.mapping.DefaultFieldSet; -import org.springframework.batch.item.file.mapping.FieldSet; -import org.springframework.batch.item.transform.ItemTransformer; - -/** - * An {@link ItemTransformer} that expects a String[] as input and delegates to - * a {@link LineAggregator}. - * - * @author Dave Syer - * - */ -public class LineAggregatorItemTransformer implements ItemTransformer { - - private LineAggregator aggregator = new DelimitedLineAggregator(); - - /** - * Public setter for the {@link LineAggregator}. - * @param aggregator the aggregator to set - */ - public void setAggregator(LineAggregator aggregator) { - this.aggregator = aggregator; - } - - /** - * Assume the item is an array of String (no check is made) and delegate to - * the aggregator. - * - * @see org.springframework.batch.item.transform.ItemTransformer#transform(java.lang.Object) - */ - public String transform(T item) throws Exception { - return aggregator.aggregate(createFieldSet(item)); - } - - /** - * 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(T 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."); - } - } -} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java new file mode 100644 index 000000000..d20dcc6de --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughFieldExtractor.java @@ -0,0 +1,66 @@ +/* + * 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.item.file.transform; + +import java.util.Collection; + +/** + * {@link FieldExtractor} that just returns the original item. If the item is an + * array or collection it will be returned as is, otherwise it is wrapped in a + * single element array. + * + * @author Dave Syer + * + */ +public class PassThroughFieldExtractor implements FieldExtractor { + + /** + * @param item the object to convert + * @return an array of objects as close as possible to the original item + */ + public Object[] extract(T item) { + + if (item.getClass().isArray()) { + Object[] items = (Object[]) item; + Object[] args = new Object[items.length]; + for (int i = 0; i < items.length; i++) { + if (items[i] == null) + args[i] = ""; + else + args[i] = items[i]; + } + return args; + } + + if (item instanceof Collection) { + Collection items = (Collection) item; + Object[] args = new Object[items.size()]; + int i = 0; + for (Object object : items) { + if (object == null) + args[i] = ""; + else + args[i] = object; + i++; + } + return args; + } + + return new Object[] { item }; + + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java new file mode 100644 index 000000000..dffb2fb62 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/PassThroughLineAggregator.java @@ -0,0 +1,15 @@ +package org.springframework.batch.item.file.transform; + + +public class PassThroughLineAggregator implements LineAggregator { + + /** + * Simply convert to a String with toString(). + * + * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) + */ + public String aggregate(T item) { + return item.toString(); + } + +} diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformer.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformer.java deleted file mode 100644 index 9eb71ef7f..000000000 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformer.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.springframework.batch.item.file.transform; - -import java.util.Collection; - -import org.springframework.batch.item.transform.ItemTransformer; - -/** - * 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 - * - */ -@SuppressWarnings("unchecked") -public class RecursiveCollectionItemTransformer implements ItemTransformer { - - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - 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}.
- * - * 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) 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 item) throws Exception { - return "" + delegate.transform(item); - } - - /** - * Convert the date to a format that can be output and then write it out. - * @param data - * @param converted - * @throws Exception - */ - private void transformRecursively(Object data, TransformHolder converted) throws Exception { - - if (data instanceof Collection) { - - for (Object value : (Collection) data) { - // (recursive) - transformRecursively(value, new TransformHolder(converted.builder)); - } - return; - } - if (data.getClass().isArray()) { - Object[] array = (Object[]) data; - for (int i = 0; i < array.length; i++) { - Object value = array[i]; - // (recursive) - transformRecursively(value, new TransformHolder(converted.builder)); - } - return; - } - if (data instanceof String) { - // This is where the output stream is actually written to - converted.builder.append(data + LINE_SEPARATOR); - } - else { - // (recursive) - transformRecursively(stringify(data), converted); - return; - } - } - - private static class TransformHolder { - - StringBuffer builder = new StringBuffer(); - - TransformHolder() { - } - - TransformHolder(StringBuffer builder) { - this.builder = builder; - } - } -} \ No newline at end of file diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java new file mode 100644 index 000000000..1d5cef1c7 --- /dev/null +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/file/transform/RecursiveCollectionLineAggregator.java @@ -0,0 +1,42 @@ +package org.springframework.batch.item.file.transform; + +import java.util.Collection; + + +/** + * An implementation of {@link LineAggregator} that concatenates a collection of + * items of a common type with the system line separator. + * + * @author Dave Syer + * + */ +public class RecursiveCollectionLineAggregator implements LineAggregator> { + + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + + private LineAggregator delegate = new PassThroughLineAggregator(); + + /** + * Public setter for the {@link LineAggregator} 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.
+ * + * @param delegate the line aggregator to set. Defaults to a pass through. + */ + public void setDelegate(LineAggregator delegate) { + this.delegate = delegate; + } + + /* + * (non-Javadoc) + * @see org.springframework.batch.item.file.transform.LineAggregator#aggregate(java.lang.Object) + */ + public String aggregate(Collection items) { + StringBuilder builder = new StringBuilder(); + for (T value : items) { + builder.append(delegate.aggregate(value) + LINE_SEPARATOR); + } + return builder.delete(builder.length()-LINE_SEPARATOR.length(),builder.length()).toString(); + } + +} \ No newline at end of file diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java index 54cb35ebd..0a4b98a76 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/FlatFileItemWriterTests.java @@ -26,10 +26,8 @@ import junit.framework.TestCase; import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; -import org.springframework.batch.item.file.mapping.DefaultFieldSet; -import org.springframework.batch.item.file.mapping.FieldSet; -import org.springframework.batch.item.file.mapping.FieldSetCreator; -import org.springframework.batch.item.file.mapping.PassThroughFieldSetCreator; +import org.springframework.batch.item.file.transform.LineAggregator; +import org.springframework.batch.item.file.transform.PassThroughLineAggregator; import org.springframework.core.io.FileSystemResource; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; @@ -74,7 +72,7 @@ public class FlatFileItemWriterTests extends TestCase { outputFile = File.createTempFile("flatfile-test-output-", ".tmp"); writer.setResource(new FileSystemResource(outputFile)); - writer.setFieldSetCreator(new PassThroughFieldSetCreator()); + writer.setLineAggregator(new PassThroughLineAggregator()); writer.afterPropertiesSet(); writer.setSaveState(true); executionContext = new ExecutionContext(); @@ -144,9 +142,9 @@ public class FlatFileItemWriterTests extends TestCase { * @throws Exception */ public void testWriteWithConverter() throws Exception { - writer.setFieldSetCreator(new FieldSetCreator() { - public FieldSet mapItem(String data) { - return new DefaultFieldSet(new String[] { "FOO:" + data }); + writer.setLineAggregator(new LineAggregator() { + public String aggregate(String item) { + return "FOO:" + item; } }); String data = "string"; @@ -164,9 +162,9 @@ public class FlatFileItemWriterTests extends TestCase { * @throws Exception */ public void testWriteWithConverterAndString() throws Exception { - writer.setFieldSetCreator(new FieldSetCreator() { - public FieldSet mapItem(String data) { - return new DefaultFieldSet(new String[] { "FOO:" + data }); + writer.setLineAggregator(new LineAggregator() { + public String aggregate(String item) { + return "FOO:" + item; } }); writer.open(executionContext); @@ -278,7 +276,7 @@ public class FlatFileItemWriterTests extends TestCase { public void testOpenWithNonWritableFile() throws Exception { writer = new FlatFileItemWriter(); - writer.setFieldSetCreator(new PassThroughFieldSetCreator()); + writer.setLineAggregator(new PassThroughLineAggregator()); FileSystemResource file = new FileSystemResource("target/no-such-file.foo"); writer.setResource(file); new File(file.getFile().getParent()).mkdirs(); @@ -310,7 +308,7 @@ public class FlatFileItemWriterTests extends TestCase { public void testDefaultStreamContext() throws Exception { writer = new FlatFileItemWriter(); writer.setResource(new FileSystemResource(outputFile)); - writer.setFieldSetCreator(new PassThroughFieldSetCreator()); + writer.setLineAggregator(new PassThroughLineAggregator()); writer.afterPropertiesSet(); writer.setSaveState(true); writer.open(executionContext); diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreatorTests.java deleted file mode 100644 index 863bceb69..000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/mapping/PassThroughFieldSetCreatorTests.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.springframework.batch.item.file.mapping; - -import junit.framework.TestCase; - -public class PassThroughFieldSetCreatorTests extends TestCase { - - private PassThroughFieldSetCreator mapper = new PassThroughFieldSetCreator(); - - /** - * Test method for - * {@link org.springframework.batch.item.file.mapping.PassThroughFieldSetCreator#mapItem(Object)}. - */ - public void testUnmapItemAsFieldSet() { - FieldSet fieldSet = new DefaultFieldSet(new String[] { "foo", "bar" }); - assertEquals(fieldSet, mapper.mapItem(fieldSet)); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.mapping.PassThroughFieldSetCreator#mapItem(java.lang.Object)}. - */ - public void testUnmapItemAsString() { - assertEquals(new DefaultFieldSet(new String[] { "foo" }), mapper.mapItem("foo")); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.mapping.PassThroughFieldSetCreator#mapItem(java.lang.Object)}. - */ - public void testUnmapItemAsNonString() { - Object object = new Object(); - assertEquals(new DefaultFieldSet(new String[] { "" + object }), mapper.mapItem(object)); - } -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java deleted file mode 100644 index ef061a4c1..000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/DelimitedLineAggregatorTests.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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.item.file.transform; - -import junit.framework.TestCase; - -import org.springframework.batch.item.file.mapping.DefaultFieldSet; - -/** - * Unit tests for {@link DelimitedLineAggregator} - * - * @author robert.kasanicky - */ -public class DelimitedLineAggregatorTests extends TestCase { - private DelimitedLineAggregator aggregator; - - public void testAggregate() { - aggregator = new DelimitedLineAggregator(); - aggregator.setDelimiter(":"); - - String[] args = { "a", "bc", "def" }; - String expectedResult = "a:bc:def"; - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, expectedResult); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregatorTests.java deleted file mode 100644 index 5078ade85..000000000 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FixedLengthLineAggregatorTests.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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.item.file.transform; - -import junit.framework.TestCase; - -import org.springframework.batch.item.file.mapping.DefaultFieldSet; - -/** - * Unit tests for {@link FixedLengthLineAggregator} - * - * @author robert.kasanicky - * @author peter.zozom - */ -public class FixedLengthLineAggregatorTests extends TestCase { - - // object under test - private FixedLengthLineAggregator aggregator = new FixedLengthLineAggregator(); - - /** - * If no ranges are specified, IllegalArgumentException is thrown - */ - public void testAggregateNullRecordDescriptor() { - String[] args = { "does not matter what is here" }; - - try { - aggregator.aggregate(new DefaultFieldSet(args)); - fail("should not work with no ranges specified"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Count of aggregated strings does not match the number of columns - */ - public void testAggregateWrongArgumentCount() { - String[] string = { "only one test string" }; - aggregator.setColumns(new Range[0]); - - try { - aggregator.aggregate(new DefaultFieldSet(string)); - fail("Exception expected: count of aggregated strings" - + " does not match the number of columns"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Text length exceeds the length of the column. - */ - public void testAggregateInvalidInputLength() { - String[] args = { "Oversize" }; - aggregator.setColumns(new Range[] {new Range(1,args[0].length()-1)}); - try { - aggregator.aggregate(new DefaultFieldSet(args)); - fail("Invalid text length, exception should have been thrown"); - } - catch (IllegalArgumentException expected) { - // expected - } - } - - /** - * Test aggregation - */ - public void testAggregate() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setColumns(new Range[] {new Range(1,9), new Range(10,18)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals("MatchsizeSmallsize", result); - } - - /** - * Test aggregation with last range unbound - */ - public void testAggregateWithLastRangeUnbound() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setColumns(new Range[] {new Range(1,12), new Range(13)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals("Matchsize Smallsize", result); - } - - - /** - * Test aggregation with right alignment - */ - public void testAggregateFormattedRight() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment(Alignment.RIGHT); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,23)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(23,result.length()); - assertEquals(result, " Matchsize Smallsize"); - } - - /** - * Test aggregation with center alignment - */ - public void testAggregateFormattedCenter() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment(Alignment.CENTER); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,25)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, " Matchsize Smallsize "); - } - - /** - * Test aggregation with left alignment - */ - public void testAggregateWithCustomPadding() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setPadding('.'); - aggregator.setAlignment(Alignment.LEFT); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, "Matchsize....Smallsize.."); - } - - /** - * Test aggregation with left alignment - */ - public void testAggregateFormattedLeft() { - String[] args = { "Matchsize", "Smallsize" }; - aggregator.setAlignment(Alignment.LEFT); - aggregator.setColumns(new Range[] {new Range(1,13), new Range(14,24)}); - String result = aggregator.aggregate(new DefaultFieldSet(args)); - assertEquals(result, "Matchsize Smallsize "); - } - - /** - * If one of the passed arguments is null, string filled with spaces should - * be returned - */ - public void testAggregateNullArgument() { - String[] args = { null }; - aggregator.setColumns(new Range[] {new Range(1,3)}); - assertEquals(" ", aggregator.aggregate(new DefaultFieldSet(args))); - } -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java new file mode 100644 index 000000000..a5f0928c1 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/FormatterLineAggregatorTests.java @@ -0,0 +1,188 @@ +/* + * 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.item.file.transform; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.junit.Test; + +/** + * Unit tests for {@link FormatterLineAggregator} + * + * @author Dave Syer + */ +public class FormatterLineAggregatorTests { + + // object under test + private FormatterLineAggregator aggregator = new FormatterLineAggregator(); + + /** + * If no ranges are specified, IllegalArgumentException is thrown + */ + @Test + public void testAggregateNullRecordDescriptor() { + String[] args = { "does not matter what is here" }; + + try { + aggregator.aggregate(args); + fail("should not work with no format specified"); + } + catch (IllegalArgumentException expected) { + // expected + } + } + + /** + * Text length exceeds the length of the column. + */ + @Test + public void testAggregateInvalidInputLength() { + String[] args = { "Oversize" }; + aggregator.setMaximumLength(3); + aggregator.setFormat("%3s"); + try { + aggregator.aggregate(args); + fail("Invalid text length, exception should have been thrown"); + } + catch (IllegalStateException expected) { + // expected + } + } + + /** + * Test aggregation + */ + @Test + public void testAggregate() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setFormat("%9s%9s"); + String result = aggregator.aggregate(args); + assertEquals("MatchsizeSmallsize", result); + } + + /** + * Test aggregation with last range unbound + */ + @Test + public void testAggregateWithLastRangeUnbound() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setFormat("%-12s%s"); + String result = aggregator.aggregate(args); + assertEquals("Matchsize Smallsize", result); + } + + /** + * Test aggregation with right alignment + */ + @Test + public void testAggregateFormattedRight() { + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setFormat("%13s%10s"); + String result = aggregator.aggregate(args); + assertEquals(23, result.length()); + assertEquals(" Matchsize Smallsize", result); + } + + /** + * Test aggregation with center alignment + */ + @Test + public void testAggregateFormattedCenter() { + + String[] args = { "Matchsize", "Smallsize" }; + aggregator.setFormat("%13s%12s"); + aggregator.setMinimumLength(25); + aggregator.setMaximumLength(25); + + aggregator.setFieldExtractor(new FieldExtractor() { + private int[] widths = new int[] {13,12}; + public Object[] extract(String[] item) { + String[] strings = new String[item.length]; + for (int i = 0; i < strings.length; i++) { + strings[i] = item[i]; + if (item[i].length()() { + private int[] widths = new int[] {13,11}; + public Object[] extract(String[] item) { + String[] strings = new String[item.length]; + for (int i = 0; i < strings.length; i++) { + strings[i] = item[i]; + if (item[i].length() transformer = new LineAggregatorItemTransformer(); - - /** - * Test method for {@link org.springframework.batch.item.file.transform.LineAggregatorItemTransformer#setAggregator(org.springframework.batch.item.file.transform.LineAggregator)}. - * @throws Exception - */ - public void testSetAggregator() throws Exception { - transformer.setAggregator(new LineAggregator() { - public String aggregate(FieldSet fieldSet) { - return "foo"; - } - }); - String value = (String) transformer.transform(new String[] {"a", "b"}); - assertEquals("foo", value); - } - - /** - * Test method for {@link org.springframework.batch.item.file.transform.LineAggregatorItemTransformer#transform(java.lang.Object)}. - * @throws Exception - */ - public void testTransform() throws Exception { - String value = (String) transformer.transform(new String[] {"a", "b"}); - assertTrue("Wrong value: "+value, value.startsWith("a,b")); - } - -} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java new file mode 100644 index 000000000..5407405a2 --- /dev/null +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/PassThroughLineAggregatorTests.java @@ -0,0 +1,21 @@ +package org.springframework.batch.item.file.transform; + +import junit.framework.TestCase; + +import org.springframework.batch.item.file.transform.LineAggregator; +import org.springframework.batch.item.file.transform.PassThroughLineAggregator; + +public class PassThroughLineAggregatorTests extends TestCase { + + private LineAggregator mapper = new PassThroughLineAggregator(); + + public void testUnmapItemAsFieldSet() { + Object item = new Object(); + assertEquals(item.toString(), mapper.aggregate(item)); + } + + public void testUnmapItemAsString() { + assertEquals("foo", mapper.aggregate("foo")); + } + +} diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java index 9cb7d778a..0b933b82f 100644 --- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java +++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/item/file/transform/RecursiveCollectionItemTransformerTests.java @@ -16,12 +16,10 @@ package org.springframework.batch.item.file.transform; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import junit.framework.TestCase; -import org.springframework.batch.item.transform.ItemTransformer; import org.springframework.util.StringUtils; /** @@ -32,97 +30,22 @@ public class RecursiveCollectionItemTransformerTests extends TestCase { private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - private RecursiveCollectionItemTransformer transformer = new RecursiveCollectionItemTransformer(); + private RecursiveCollectionLineAggregator aggregator = new RecursiveCollectionLineAggregator(); - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#setDelegate(org.springframework.batch.item.transform.ItemTransformer)}. - * @throws Exception - */ - public void testSetDelegate() throws Exception { - transformer.setDelegate(new ItemTransformer() { - public String transform(Object item) throws Exception { - return "bar"; - } - }); - assertEquals("bar", transformer.transform(new Object())); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#setDelegate(org.springframework.batch.item.transform.ItemTransformer)}. - * @throws Exception - */ public void testSetDelegateAndPassInString() throws Exception { - transformer.setDelegate(new ItemTransformer() { - public String transform(Object item) throws Exception { + aggregator.setDelegate(new LineAggregator() { + public String aggregate(String item) { return "bar"; } }); - assertEquals("foo", transformer.transform("foo")); + assertEquals("bar", aggregator.aggregate(Collections.singleton("foo"))); } - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#setDelegate(org.springframework.batch.item.transform.ItemTransformer)}. - * @throws Exception - */ - public void testSetDelegateReturnsList() throws Exception { - transformer.setDelegate(new ItemTransformer>() { - public Collection transform(Object item) throws Exception { - return Collections.singletonList("bar"); - } - }); - // The result of the delegate is a list, which will simply be - // converted to a string by concatenating with "": - assertEquals("[bar]", transformer.transform(new Object())); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#transform(java.lang.Object)}. - * @throws Exception - */ - public void testTransformString() throws Exception { - assertEquals("foo", transformer.transform("foo")); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#transform(java.lang.Object)}. - * @throws Exception - */ - public void testTransformArray() throws Exception { - String result = (String) transformer.transform(StringUtils.commaDelimitedListToStringArray("foo,bar")); - String[] array = StringUtils.delimitedListToStringArray(result, LINE_SEPARATOR); - assertEquals("foo", array[0]); - assertEquals("bar", array[1]); - } - - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#transform(java.lang.Object)}. - * @throws Exception - */ public void testTransformList() throws Exception { - String result = (String) transformer.transform(Arrays.asList(StringUtils.commaDelimitedListToStringArray("foo,bar"))); + String result = aggregator.aggregate(Arrays.asList(StringUtils.commaDelimitedListToStringArray("foo,bar"))); String[] array = StringUtils.delimitedListToStringArray(result, LINE_SEPARATOR); assertEquals("foo", array[0]); assertEquals("bar", array[1]); } - /** - * Test method for - * {@link org.springframework.batch.item.file.transform.RecursiveCollectionItemTransformer#transform(java.lang.Object)}. - * @throws Exception - */ - public void testTransformArrayOfArrays() throws Exception { - String[][] input = new String[][] { StringUtils.commaDelimitedListToStringArray("foo,bar"), - StringUtils.commaDelimitedListToStringArray("spam,bucket") }; - String result = (String) transformer.transform(input); - String[] array = StringUtils.delimitedListToStringArray(result, LINE_SEPARATOR); - assertEquals(4,array.length); - assertEquals("foo", array[0]); - assertEquals("spam", array[2]); - } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderTransformer.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderTransformer.java index 2923159ff..6fa8989c3 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderTransformer.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/order/internal/OrderTransformer.java @@ -21,8 +21,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.springframework.batch.item.file.mapping.DefaultFieldSet; -import org.springframework.batch.item.file.mapping.FieldSet; import org.springframework.batch.item.file.transform.LineAggregator; import org.springframework.batch.item.transform.ItemTransformer; import org.springframework.batch.sample.domain.order.Address; @@ -40,7 +38,7 @@ public class OrderTransformer implements ItemTransformer> { /** * Aggregators for all types of lines in the output file */ - private Map aggregators; + private Map> aggregators; /** * Converts information from an Order object to a collection of Strings for @@ -66,11 +64,11 @@ public class OrderTransformer implements ItemTransformer> { return result; } - public void setAggregators(Map aggregators) { + public void setAggregators(Map> aggregators) { this.aggregators = aggregators; } - private LineAggregator getAggregator(String name) { + private LineAggregator getAggregator(String name) { return aggregators.get(name); } @@ -82,39 +80,36 @@ public class OrderTransformer implements ItemTransformer> { private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); - static FieldSet headerArgs(Order order) { - return new DefaultFieldSet(new String[] { "BEGIN_ORDER:", String.valueOf(order.getOrderId()), - dateFormat.format(order.getOrderDate()) }); + static String[] headerArgs(Order order) { + return new String[] { "BEGIN_ORDER:", String.valueOf(order.getOrderId()), + dateFormat.format(order.getOrderDate()) }; } - static FieldSet footerArgs(Order order) { - return new DefaultFieldSet(new String[] { "END_ORDER:", order.getTotalPrice().toString() }); + static String[] footerArgs(Order order) { + return new String[] { "END_ORDER:", order.getTotalPrice().toString() }; } - static FieldSet customerArgs(Order order) { + static String[] customerArgs(Order order) { Customer customer = order.getCustomer(); - return new DefaultFieldSet(new String[] { "CUSTOMER:", String.valueOf(customer.getRegistrationId()), - customer.getFirstName(), customer.getMiddleName(), customer.getLastName() }); + return new String[] { "CUSTOMER:", String.valueOf(customer.getRegistrationId()), customer.getFirstName(), + customer.getMiddleName(), customer.getLastName() }; } - static FieldSet lineItemArgs(LineItem item) { - return new DefaultFieldSet(new String[] { "ITEM:", String.valueOf(item.getItemId()), - item.getPrice().toString() }); + static String[] lineItemArgs(LineItem item) { + return new String[] { "ITEM:", String.valueOf(item.getItemId()), item.getPrice().toString() }; } - static FieldSet billingAddressArgs(Order order) { + static String[] billingAddressArgs(Order order) { Address address = order.getBillingAddress(); - return new DefaultFieldSet(new String[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), - address.getZipCode() }); + return new String[] { "ADDRESS:", address.getAddrLine1(), address.getCity(), address.getZipCode() }; } - static FieldSet billingInfoArgs(Order order) { + static String[] billingInfoArgs(Order order) { BillingInfo billingInfo = order.getBilling(); - return new DefaultFieldSet(new String[] { "BILLING:", billingInfo.getPaymentId(), - billingInfo.getPaymentDesc() }); + return new String[] { "BILLING:", billingInfo.getPaymentId(), billingInfo.getPaymentDesc() }; } } diff --git a/spring-batch-samples/src/main/resources/jobs/compositeItemWriterSampleJob.xml b/spring-batch-samples/src/main/resources/jobs/compositeItemWriterSampleJob.xml index a3f3f0d55..cc626773c 100644 --- a/spring-batch-samples/src/main/resources/jobs/compositeItemWriterSampleJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/compositeItemWriterSampleJob.xml @@ -91,9 +91,9 @@ id="fileItemWriter"> - + + class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" /> diff --git a/spring-batch-samples/src/main/resources/jobs/multilineJob.xml b/spring-batch-samples/src/main/resources/jobs/multilineJob.xml index 674557c6b..406455b75 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineJob.xml @@ -23,8 +23,8 @@ class="org.springframework.batch.item.file.FlatFileItemWriter"> - - + + diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderIo.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderIo.xml index 3b5ef045a..55d6e9184 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderIo.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderIo.xml @@ -1,45 +1,28 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml index 05184f441..f5d1c8a55 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderJob.xml @@ -16,7 +16,7 @@ - + @@ -52,7 +52,7 @@ - + diff --git a/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputAggregators.xml b/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputAggregators.xml index f8cfc876f..cc38e734f 100644 --- a/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputAggregators.xml +++ b/spring-batch-samples/src/main/resources/jobs/multilineOrderOutputAggregators.xml @@ -14,26 +14,26 @@ - + + class="org.springframework.batch.item.file.transform.FormatterLineAggregator" + p:format="%-10s%20s"/> - + + class="org.springframework.batch.item.file.transform.FormatterLineAggregator" + p:format="%-8s%-20s%-10s%-10s" /> + class="org.springframework.batch.item.file.transform.FormatterLineAggregator" + p:format="%-8s%-10s%-20s"/> + class="org.springframework.batch.item.file.transform.FormatterLineAggregator" + p:format="%-5s%-10s%-10s" /> \ No newline at end of file diff --git a/spring-batch-samples/src/main/resources/jobs/tradeJobIo.xml b/spring-batch-samples/src/main/resources/jobs/tradeJobIo.xml index 738c00974..04455ec3f 100644 --- a/spring-batch-samples/src/main/resources/jobs/tradeJobIo.xml +++ b/spring-batch-samples/src/main/resources/jobs/tradeJobIo.xml @@ -30,9 +30,9 @@ class="org.springframework.batch.item.file.FlatFileItemWriter" id="customerFlatFileOutputSource"> - + + class="org.springframework.batch.item.file.transform.PassThroughLineAggregator" /> diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/StubLineAggregator.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/StubLineAggregator.java deleted file mode 100644 index a64bd0653..000000000 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/StubLineAggregator.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.sample; - -import org.springframework.batch.item.file.mapping.FieldSet; -import org.springframework.batch.item.file.transform.LineAggregator; - - -/** - * Stub implementation of {@link LineAggregator} interface for testing purposes. - * - * @author robert.kasanicky - */ -public class StubLineAggregator implements LineAggregator { - - /** - * Concatenates arguments. Ignores the LineDescriptor. - */ - public String aggregate(FieldSet fieldSet) { - String result = ""; - - for (int i = 1; i < fieldSet.getFieldCount(); i++) { - result = result + fieldSet.readString(i); - } - - return result; - } -} diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderWriterTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderAggregatorTests.java similarity index 60% rename from spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderWriterTests.java rename to spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderAggregatorTests.java index d5f156dc8..4db61e862 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderWriterTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/FlatFileOrderAggregatorTests.java @@ -16,7 +16,6 @@ package org.springframework.batch.sample.domain.order; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import java.math.BigDecimal; import java.util.ArrayList; @@ -25,40 +24,19 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.junit.Before; import org.junit.Test; -import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.file.transform.DelimitedLineAggregator; import org.springframework.batch.item.file.transform.LineAggregator; -import org.springframework.batch.item.support.AbstractItemWriter; -import org.springframework.batch.item.transform.ItemTransformerItemWriter; -import org.springframework.batch.sample.StubLineAggregator; import org.springframework.batch.sample.domain.order.internal.OrderTransformer; -public class FlatFileOrderWriterTests { - - List list = new ArrayList(); - - private ItemWriter output = new AbstractItemWriter() { - public void write(Object output) { - list.add(output); - } - }; - - private ItemTransformerItemWriter writer; - - @Before - public void setUp() throws Exception { - //create new writer - writer = new ItemTransformerItemWriter(); - writer.setDelegate(output); - } +public class FlatFileOrderAggregatorTests { @Test public void testWrite() throws Exception { - - //Create and set-up Order + + // Create and set-up Order Order order = new Order(); - + order.setOrderDate(new GregorianCalendar(2007, GregorianCalendar.JUNE, 1).getTime()); order.setCustomer(new Customer()); order.setBilling(new BillingInfo()); @@ -70,13 +48,13 @@ public class FlatFileOrderWriterTests { lineItems.add(item); order.setLineItems(lineItems); order.setTotalPrice(BigDecimal.valueOf(0)); - - //create aggregator stub - LineAggregator aggregator = new StubLineAggregator(); - - //create map of aggregators and set it to writer - Map aggregators = new HashMap(); - + + // create aggregator stub + LineAggregator aggregator = new DelimitedLineAggregator(); + + // create map of aggregators and set it to writer + Map> aggregators = new HashMap>(); + OrderTransformer converter = new OrderTransformer(); aggregators.put("header", aggregator); aggregators.put("customer", aggregator); @@ -85,16 +63,14 @@ public class FlatFileOrderWriterTests { aggregators.put("item", aggregator); aggregators.put("footer", aggregator); converter.setAggregators(aggregators); - writer.setItemTransformer(converter); - - //call tested method - writer.write(order); - - //verify method calls - assertEquals(1, list.size()); - assertTrue(list.get(0) instanceof List); - assertEquals("02007/06/01", ((List) list.get(0)).get(0)); - + + // call tested method + List list = converter.transform(order); + + // verify method calls + assertEquals(7, list.size()); + assertEquals("BEGIN_ORDER:,0,2007/06/01", list.get(0)); + } } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderTransformerTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderTransformerTests.java index ea61be8f5..a074b8953 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderTransformerTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/domain/order/OrderTransformerTests.java @@ -24,8 +24,8 @@ import java.util.Date; import java.util.HashMap; import org.junit.Test; -import org.springframework.batch.item.file.transform.DelimitedLineAggregator; import org.springframework.batch.item.file.transform.LineAggregator; +import org.springframework.batch.item.file.transform.PassThroughLineAggregator; import org.springframework.batch.sample.domain.order.internal.OrderTransformer; /** @@ -38,14 +38,14 @@ public class OrderTransformerTests { @Test public void testConvert() throws Exception { - converter.setAggregators(new HashMap() { + converter.setAggregators(new HashMap>() { { - put("header", new DelimitedLineAggregator()); - put("customer", new DelimitedLineAggregator()); - put("address", new DelimitedLineAggregator()); - put("billing", new DelimitedLineAggregator()); - put("item", new DelimitedLineAggregator()); - put("footer", new DelimitedLineAggregator()); + put("header", new PassThroughLineAggregator()); + put("customer", new PassThroughLineAggregator()); + put("address", new PassThroughLineAggregator()); + put("billing", new PassThroughLineAggregator()); + put("item", new PassThroughLineAggregator()); + put("footer", new PassThroughLineAggregator()); } }); Order order = new Order();