BATCH-105: The functionality in "DefaultFlatFileItemProvider" (validating and mapping) should be provided by the infrastructure layer (DefaultFlatFileInputSource).
http://opensource.atlassian.com/projects/spring/browse/BATCH-105
This commit is contained in:
@@ -1,143 +0,0 @@
|
||||
package org.springframework.batch.execution.tasklet.support;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.batch.restart.GenericRestartData;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.batch.restart.Restartable;
|
||||
import org.springframework.batch.statistics.StatisticsProvider;
|
||||
|
||||
/**
|
||||
* Runs a collection of ItemProcessors in fixed-order sequence.
|
||||
*
|
||||
* @author Robert Kasanicky
|
||||
*/
|
||||
public class CompositeItemProcessor implements ItemProcessor, Restartable, StatisticsProvider {
|
||||
|
||||
private static final String SEPARATOR = "#";
|
||||
|
||||
private List itemProcessors;
|
||||
|
||||
/**
|
||||
* Calls injected ItemProcessors in order.
|
||||
*/
|
||||
public void process(Object data) throws Exception {
|
||||
for (Iterator iterator = itemProcessors.listIterator(); iterator.hasNext();) {
|
||||
((ItemProcessor) iterator.next()).process(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compound restart data of all injected (Restartable) ItemProcessors, property keys are
|
||||
* prefixed with list index of the ItemProcessor.
|
||||
*/
|
||||
public RestartData getRestartData() {
|
||||
Properties props = createCompoundProperties(new PropertiesExtractor() {
|
||||
public Properties extractProperties(Object o) {
|
||||
if (o instanceof Restartable) {
|
||||
return ((Restartable)o).getRestartData().getProperties();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
return new GenericRestartData(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data contains values of restart data, property keys are expected to be prefixed with
|
||||
* list index of the ItemProcessor.
|
||||
*/
|
||||
public void restoreFrom(RestartData data) {
|
||||
if (data == null || data.getProperties() == null) {
|
||||
// do nothing
|
||||
return;
|
||||
}
|
||||
|
||||
List restartDataList = parseProperties(data.getProperties());
|
||||
|
||||
// iterators would make the loop below less readable
|
||||
for (int i=0; i < itemProcessors.size(); i++) {
|
||||
if (itemProcessors.get(i) instanceof Restartable) {
|
||||
((Restartable) itemProcessors.get(i)).restoreFrom((RestartData) restartDataList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Properties containing statistics of all injected ItemProcessors,
|
||||
* property keys are prefixed with the list index of the ItemProcessor.
|
||||
*/
|
||||
public Properties getStatistics() {
|
||||
return createCompoundProperties(new PropertiesExtractor() {
|
||||
public Properties extractProperties(Object o) {
|
||||
if (o instanceof StatisticsProvider){
|
||||
return ((StatisticsProvider) o).getStatistics();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setItemProcessors(List itemProcessors) {
|
||||
this.itemProcessors = itemProcessors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses compound properties into a list of RestartData.
|
||||
*/
|
||||
private List parseProperties(Properties props) {
|
||||
List restartDataList = new ArrayList(itemProcessors.size());
|
||||
for (int i = 0; i<itemProcessors.size(); i++) {
|
||||
restartDataList.add(new GenericRestartData(new Properties()));
|
||||
}
|
||||
|
||||
for (Iterator iterator = props.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) iterator.next();
|
||||
String key = (String) entry.getKey();
|
||||
String value = (String) entry.getValue();
|
||||
int separatorIndex = key.indexOf(SEPARATOR);
|
||||
int i = Integer.valueOf(key.substring(0, separatorIndex)).intValue();
|
||||
((RestartData)restartDataList.get(i)).getProperties().setProperty(
|
||||
key.substring(separatorIndex + 1), value);
|
||||
}
|
||||
return restartDataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param extractor used to extract Properties from ItemProviders
|
||||
* @return compound Properties containing all the Properties from injected ItemProcessors
|
||||
* with property keys prefixed by list index.
|
||||
*/
|
||||
private Properties createCompoundProperties(PropertiesExtractor extractor) {
|
||||
Properties stats = new Properties();
|
||||
int index = 0;
|
||||
for (Iterator iterator = itemProcessors.listIterator(); iterator.hasNext();) {
|
||||
ItemProcessor processor = (ItemProcessor) iterator.next();
|
||||
Properties processorStats = extractor.extractProperties(processor);
|
||||
if (processorStats != null) {
|
||||
for (Iterator iterator2 = processorStats.entrySet().iterator(); iterator2.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) iterator2.next();
|
||||
stats.setProperty("" + index + SEPARATOR + entry.getKey(), (String) entry.getValue());
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts information from given object in the form of {@link Properties}. If the information
|
||||
* is not available (e.g. unexpected object class) return null.
|
||||
*/
|
||||
private interface PropertiesExtractor {
|
||||
Properties extractProperties(Object o);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +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.execution.tasklet.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.io.InputSource;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.provider.AbstractItemProvider;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.batch.restart.Restartable;
|
||||
import org.springframework.batch.statistics.StatisticsProvider;
|
||||
|
||||
/**
|
||||
* Simple wrapper around {@link InputSource}. The input source is expected to
|
||||
* take care of open and close operations. If necessary it should be registered
|
||||
* as a step scoped bean to ensure that the lifecycle methods are called.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class InputSourceItemProvider extends AbstractItemProvider implements Restartable, StatisticsProvider, Skippable {
|
||||
|
||||
private InputSource source;
|
||||
|
||||
/**
|
||||
* Get the next object from the input source.
|
||||
* @see org.springframework.batch.item.ItemProvider#next()
|
||||
*/
|
||||
public Object next() {
|
||||
Object value = source.read();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Restartable#getRestartData()
|
||||
* @throws IllegalStateException if the parent template is not itself
|
||||
* {@link Restartable}.
|
||||
*/
|
||||
public RestartData getRestartData() {
|
||||
if (!(source instanceof Restartable)) {
|
||||
throw new IllegalStateException("Input Template is not Restartable");
|
||||
}
|
||||
return ((Restartable) source).getRestartData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Restartable#restoreFrom(RestartData)
|
||||
* @throws IllegalStateException if the parent template is not itself
|
||||
* {@link Restartable}.
|
||||
*/
|
||||
public void restoreFrom(RestartData data) {
|
||||
if (!(source instanceof Restartable)) {
|
||||
throw new IllegalStateException("Input Template is not Restartable");
|
||||
}
|
||||
((Restartable) source).restoreFrom(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return delegates to the parent template of it is a
|
||||
* {@link StatisticsProvider}, otherwise returns an empty
|
||||
* {@link Properties} instance.
|
||||
* @see StatisticsProvider#getStatistics()
|
||||
*/
|
||||
public Properties getStatistics() {
|
||||
if (!(source instanceof StatisticsProvider)) {
|
||||
return new Properties();
|
||||
}
|
||||
return ((StatisticsProvider) source).getStatistics();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for input source.
|
||||
* @param source
|
||||
*/
|
||||
public void setInputSource(InputSource source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public void skip() {
|
||||
if (source instanceof Skippable) {
|
||||
((Skippable)source).skip();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package org.springframework.batch.execution.tasklet.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.io.OutputSource;
|
||||
import org.springframework.batch.io.Skippable;
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.batch.restart.RestartData;
|
||||
import org.springframework.batch.restart.Restartable;
|
||||
import org.springframework.batch.statistics.StatisticsProvider;
|
||||
|
||||
/**
|
||||
* Simple wrapper around {@link OutputSource} providing {@link Restartable} and
|
||||
* {@link StatisticsProvider} where the {@link OutputSource} does.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class OutputSourceItemProcessor implements ItemProcessor, Restartable, Skippable,
|
||||
StatisticsProvider {
|
||||
|
||||
private OutputSource source;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.item.ItemProcessor#process(java.lang.Object)
|
||||
*/
|
||||
public void process(Object data) throws Exception {
|
||||
source.write(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for output source.
|
||||
*
|
||||
* @param source
|
||||
*/
|
||||
public void setOutputSource(OutputSource source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Restartable#getRestartData()
|
||||
* @throws IllegalStateException if the parent template is not itself
|
||||
* {@link Restartable}.
|
||||
*/
|
||||
public RestartData getRestartData() {
|
||||
if (!(source instanceof Restartable)) {
|
||||
throw new IllegalStateException("Output Source is not Restartable");
|
||||
}
|
||||
return ((Restartable) source).getRestartData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Restartable#restoreFrom(RestartData)
|
||||
* @throws IllegalStateException if the parent template is not itself
|
||||
* {@link Restartable}.
|
||||
*/
|
||||
public void restoreFrom(RestartData data) {
|
||||
if (!(source instanceof Restartable)) {
|
||||
throw new IllegalStateException("Output Source is not Restartable");
|
||||
}
|
||||
((Restartable) source).restoreFrom(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return delegates to the parent template of it is a
|
||||
* {@link StatisticsProvider}, otherwise returns an empty
|
||||
* {@link Properties} instance.
|
||||
* @see StatisticsProvider#getStatistics()
|
||||
*/
|
||||
public Properties getStatistics() {
|
||||
if (!(source instanceof StatisticsProvider)) {
|
||||
return new Properties();
|
||||
}
|
||||
return ((StatisticsProvider) source).getStatistics();
|
||||
}
|
||||
|
||||
public void skip() {
|
||||
if (source instanceof Skippable) {
|
||||
((Skippable)source).skip();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>
|
||||
Specific implementations of support concerns.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user