BATCH-1033: Created PrefixMatchingCompositeLineMapper and reorganized PrefixMatchingCompositeLineTokenizer so that its lookup functionality could be reused. Also updated the multiRecordType sample by removing PrefixMatchingCompositeFieldSetMapper in favor of the new class.
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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 java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.batch.item.file.transform.LineTokenizer;
|
||||
import org.springframework.batch.item.file.transform.PrefixMatchingCompositeLineTokenizer;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A {@link LineMapper} implementation that stores a mapping of String prefixes
|
||||
* to delegate {@link LineTokenizer}s as well as a mapping of String prefixes
|
||||
* to delegate {@link LineTokenizer}s. Each line received will be tokenized and
|
||||
* then mapped to a field set.
|
||||
*
|
||||
* <p>
|
||||
* Both the tokenizing and the mapping work in a similar way. The line will be
|
||||
* checked for its prefix. If the prefix matches a key in the map of delegates,
|
||||
* then the corresponding delegate will be used. Otherwise, the default
|
||||
* tokenizer or mapper will be used. The default can be configured in the
|
||||
* delegate map by setting its corresponding prefix to the empty string.
|
||||
*
|
||||
* @author Dan Garrette
|
||||
*/
|
||||
public class PrefixMatchingCompositeLineMapper<T> extends PrefixMatchingCompositeLineTokenizer implements LineMapper<T> {
|
||||
|
||||
private Map<String, FieldSetMapper<T>> fieldSetMappers = null;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.mapping.LineMapper#mapLine(java.lang.String,
|
||||
* int)
|
||||
*/
|
||||
public T mapLine(String line, int lineNumber) throws Exception {
|
||||
return this.matchPrefix(line, this.fieldSetMappers).mapFieldSet(this.tokenize(line));
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
super.afterPropertiesSet();
|
||||
Assert.isTrue(this.fieldSetMappers != null && this.fieldSetMappers.size() > 0,
|
||||
"The 'fieldSetMappers' property must be non-empty");
|
||||
}
|
||||
|
||||
public void setFieldSetMappers(Map<String, FieldSetMapper<T>> fieldSetMappers) {
|
||||
this.fieldSetMappers = new LinkedHashMap<String, FieldSetMapper<T>>(fieldSetMappers);
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
package org.springframework.batch.item.file.transform;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link LineTokenizer} implementation that stores a mapping of String
|
||||
@@ -30,46 +31,69 @@ import java.util.Map;
|
||||
* {@link LineTokenizer} can be configured in the delegate map by setting its
|
||||
* corresponding prefix to the empty string.
|
||||
*
|
||||
* @author Dan Garrette
|
||||
*/
|
||||
public class PrefixMatchingCompositeLineTokenizer implements LineTokenizer {
|
||||
public class PrefixMatchingCompositeLineTokenizer implements LineTokenizer, InitializingBean {
|
||||
|
||||
private Map<String, LineTokenizer> tokenizers = new HashMap<String, LineTokenizer>();
|
||||
private Map<String, LineTokenizer> tokenizers = null;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String)
|
||||
*/
|
||||
public FieldSet tokenize(String line) {
|
||||
return this.matchPrefix(line, this.tokenizers).tokenize(line);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line
|
||||
* @return the delegate whose prefix matches the given line
|
||||
*/
|
||||
protected <S> S matchPrefix(String line, Map<String, S> delegates) {
|
||||
S delegate = null;
|
||||
S defaultDelegate = null;
|
||||
|
||||
if (line != null) {
|
||||
for (String key : delegates.keySet()) {
|
||||
if ("".equals(key)) {
|
||||
defaultDelegate = delegates.get(key);
|
||||
// don't break here or the delegate may not be found
|
||||
}
|
||||
else if (line.startsWith(key)) {
|
||||
delegate = delegates.get(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (delegate == null) {
|
||||
delegate = defaultDelegate;
|
||||
}
|
||||
}
|
||||
else if (delegates.containsKey(null)) {
|
||||
delegate = delegates.get(null);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Could not handle a null line");
|
||||
}
|
||||
|
||||
if (delegate == null) {
|
||||
throw new IllegalStateException("Could not find a matching prefix for line=[" + line + "]");
|
||||
}
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
|
||||
*/
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.isTrue(this.tokenizers != null && this.tokenizers.size() > 0,
|
||||
"The 'tokenizers' property must be non-empty");
|
||||
}
|
||||
|
||||
public void setTokenizers(Map<String, LineTokenizer> tokenizers) {
|
||||
this.tokenizers = new LinkedHashMap<String, LineTokenizer>(tokenizers);
|
||||
}
|
||||
|
||||
public FieldSet tokenize(String line) {
|
||||
|
||||
if (line == null) {
|
||||
return new DefaultFieldSet(new String[0]);
|
||||
}
|
||||
|
||||
LineTokenizer tokenizer = null;
|
||||
LineTokenizer defaultTokenizer = null;
|
||||
|
||||
for (String key : tokenizers.keySet()) {
|
||||
|
||||
if ("".equals(key)) {
|
||||
defaultTokenizer = (LineTokenizer) tokenizers.get(key);
|
||||
// don't break here or the tokenizer may not be found
|
||||
continue;
|
||||
}
|
||||
if (line.startsWith(key)) {
|
||||
tokenizer = (LineTokenizer) tokenizers.get(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenizer == null) {
|
||||
tokenizer = defaultTokenizer;
|
||||
}
|
||||
|
||||
if (tokenizer == null) {
|
||||
throw new IllegalStateException("Could not match record to tokenizer for line=[" + line + "]");
|
||||
}
|
||||
|
||||
return tokenizer.tokenize(line);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user