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

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

Introduce FieldSetUnmapper for symmetry with input
This commit is contained in:
dsyer
2008-02-25 14:42:16 +00:00
parent 4b0edc1799
commit 4f4b63b6c1
12 changed files with 332 additions and 163 deletions

View File

@@ -28,14 +28,16 @@ import java.util.Properties;
import org.springframework.batch.io.exception.BatchCriticalException;
import org.springframework.batch.io.exception.BatchEnvironmentException;
import org.springframework.batch.io.file.transform.RecursiveCollectionItemTransformer;
import org.springframework.batch.io.file.mapping.FieldSet;
import org.springframework.batch.io.file.mapping.FieldSetUnmapper;
import org.springframework.batch.io.file.transform.DelimitedLineAggregator;
import org.springframework.batch.io.file.transform.LineAggregator;
import org.springframework.batch.io.support.AbstractTransactionalIoSource;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.exception.ResetFailedException;
import org.springframework.batch.item.exception.StreamException;
import org.springframework.batch.item.writer.ItemTransformer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessResourceFailureException;
@@ -52,9 +54,11 @@ import org.springframework.util.Assert;
*
* Use {@link #write(String)} method to output a line to an item writer.
*
* <p>This class will be updated in the future to use a buffering approach
* to handling transactions, rather than outputting directly to the file and
* truncating on rollback</p>
* <p>
* This class will be updated in the future to use a buffering approach to
* handling transactions, rather than outputting directly to the file and
* truncating on rollback
* </p>
*
* @author Waseem Malik
* @author Tomas Slanina
@@ -78,26 +82,40 @@ public class FlatFileItemWriter extends AbstractTransactionalIoSource implements
private OutputState state = null;
private ItemTransformer transformer = new RecursiveCollectionItemTransformer();
private LineAggregator lineAggregator = new DelimitedLineAggregator();
private FieldSetUnmapper fieldSetUnmapper;
/**
* Assert that mandatory properties (resource) are set.
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource);
Assert.notNull(resource, "The resource must be set");
Assert.notNull(fieldSetUnmapper, "A FieldSetUnmapper must be provided.");
File file = resource.getFile();
Assert.state(!file.exists() || file.canWrite(), "Resource is not writable: [" + resource + "]");
}
/**
* Public setter for the converter. If not-null this will be used to convert
* the input data before it is output.
* Public setter for the {@link LineAggregator}. This will be used to
* translate a {@link FieldSet} into a line for output.
*
* @param transformer the converter to set
* @param lineAggregator the {@link LineAggregator} to set
*/
public void setTransformer(ItemTransformer transformer) {
this.transformer = transformer;
public void setLineAggregator(LineAggregator lineAggregator) {
this.lineAggregator = lineAggregator;
}
/**
* Public setter for the {@link FieldSetUnmapper}. This will be used to
* transform the item into a {@link FieldSet} before it is aggregated by the
* {@link LineAggregator}.
*
* @param fieldSetUnmapper the {@link FieldSetUnmapper} to set
*/
public void setFieldSetUnmapper(FieldSetUnmapper fieldSetUnmapper) {
this.fieldSetUnmapper = fieldSetUnmapper;
}
/**
@@ -123,7 +141,8 @@ public class FlatFileItemWriter extends AbstractTransactionalIoSource implements
* @throws Exception if the transformer or file output fail
*/
public void write(Object data) throws Exception {
getOutputState().write(transformer.transform(data) + LINE_SEPARATOR);
FieldSet fieldSet = fieldSetUnmapper.unmapItem(data);
getOutputState().write(lineAggregator.aggregate(fieldSet ) + LINE_SEPARATOR);
}
/**
@@ -228,6 +247,13 @@ public class FlatFileItemWriter extends AbstractTransactionalIoSource implements
long restartCount = 0;
boolean shouldDeleteIfExists = true;
/**
*
*/
public OutputState() {
initializeBufferedWriter();
}
/**
* Return the byte offset position of the cursor in the output file as a
@@ -469,16 +495,16 @@ public class FlatFileItemWriter extends AbstractTransactionalIoSource implements
return true;
}
/* To be deleted once interface changes are complete
* (non-Javadoc)
/*
* To be deleted once interface changes are complete (non-Javadoc)
* @see org.springframework.batch.io.support.AbstractTransactionalIoSource#mark(org.springframework.batch.item.ExecutionContext)
*/
public void mark() {
}
/* To be deleted once interface changes are complete
* (non-Javadoc)
/*
* To be deleted once interface changes are complete (non-Javadoc)
* @see org.springframework.batch.io.support.AbstractTransactionalIoSource#reset(org.springframework.batch.item.ExecutionContext)
*/
public void reset() throws ResetFailedException {
@@ -488,7 +514,8 @@ public class FlatFileItemWriter extends AbstractTransactionalIoSource implements
public void clear() throws Exception {
try {
getOutputState().reset();
} catch (BatchCriticalException e) {
}
catch (BatchCriticalException e) {
throw new ResetFailedException(e);
}
}

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.mapping;
/**
* @author Dave Syer
*
*/
public interface FieldSetUnmapper {
/**
* @param data an Object to convert.
* @return a {@link FieldSet} created from the input.
*/
FieldSet unmapItem(Object data);
}

View File

@@ -17,20 +17,37 @@ package org.springframework.batch.io.file.mapping;
/**
* Pass through {@link FieldSetMapper} useful for
* passing a fieldset back from a FlatFileInputsource rather
* than a mapped object.
*
* Pass through {@link FieldSetMapper} useful for passing a {@link FieldSet}
* back directly rather than a mapped object.
*
* @author Lucas Ward
*
*
*/
public class PassThroughFieldSetMapper implements FieldSetMapper {
public class PassThroughFieldSetMapper implements FieldSetMapper, FieldSetUnmapper {
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.batch.io.file.FieldSetMapper#mapLine(org.springframework.batch.io.file.FieldSet)
*/
public Object mapLine(FieldSet fs) {
return fs;
}
/**
* 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.io.file.mapping.FieldSetUnmapper#unmapItem(java.lang.Object)
*/
public FieldSet unmapItem(Object data) {
if (data instanceof FieldSet) {
return (FieldSet) data;
}
if (!(data instanceof String)) {
data = "" + data;
}
return new DefaultFieldSet(new String[] { (String) data });
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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;
import org.springframework.batch.io.file.mapping.FieldSet;
import org.springframework.batch.io.file.mapping.FieldSetUnmapper;
import org.springframework.batch.item.writer.ItemTransformer;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
/**
* An {@link ItemTransformer} that delegates to a {@link FieldSetUnmapper}, so
* the result of the transformation is a {@link FieldSet}.
*
* @author Dave Syer
*
*/
public class FieldSetUnmapperItemTransformer implements ItemTransformer, InitializingBean {
private FieldSetUnmapper fieldSetUnmapper;
/**
* Assert that mandatory properties are set.
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
Assert.notNull(fieldSetUnmapper, "A FieldSetUnmapper must be provided.");
}
/* (non-Javadoc)
* @see org.springframework.batch.item.writer.ItemTransformer#transform(java.lang.Object)
*/
public Object transform(Object item) throws Exception {
return fieldSetUnmapper.unmapItem(item);
}
}

View File

@@ -1,6 +1,10 @@
package org.springframework.batch.item.writer;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.exception.StreamException;
import org.springframework.batch.item.stream.ItemStreamAdapter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
@@ -10,9 +14,11 @@ import org.springframework.util.Assert;
* @author Dave Syer
* @author Robert Kasanicky
*/
public class DelegatingItemWriter implements ItemWriter, InitializingBean {
public class DelegatingItemWriter implements ItemWriter, ItemStream, InitializingBean {
private ItemWriter writer;
private ItemStream stream;
/**
* Calls {@link #doProcess(Object)} and then writes the result to the
@@ -40,6 +46,11 @@ public class DelegatingItemWriter implements ItemWriter, InitializingBean {
*/
public void setDelegate(ItemWriter writer) {
this.writer = writer;
if (writer instanceof ItemStream) {
this.stream = (ItemStream) writer;
} else {
this.stream = new ItemStreamAdapter();
}
}
public void afterPropertiesSet() throws Exception {
@@ -60,4 +71,38 @@ public class DelegatingItemWriter implements ItemWriter, InitializingBean {
writer.flush();
}
/**
* @throws StreamException
* @see org.springframework.batch.item.ItemStream#close()
*/
public void close() throws StreamException {
stream.close();
}
/**
* @return
* @see org.springframework.batch.item.ExecutionContextProvider#getExecutionContext()
*/
public ExecutionContext getExecutionContext() {
return stream.getExecutionContext();
}
/**
* @throws StreamException
* @see org.springframework.batch.item.ItemStream#open()
*/
public void open() throws StreamException {
stream.open();
}
/**
* @param context
* @see org.springframework.batch.item.ItemStream#restoreFrom(org.springframework.batch.item.ExecutionContext)
*/
public void restoreFrom(ExecutionContext context) {
stream.restoreFrom(context);
}
}