RESOLVED - issue BATCH-1106: SqlPagingQueryProviderFactoryBean ascending should default to true
Plus change PatternMatcher to match patterns instead of prefixes.
This commit is contained in:
@@ -58,9 +58,11 @@ public class SqlPagingQueryProviderFactoryBean implements FactoryBean {
|
||||
|
||||
private String sortKey;
|
||||
|
||||
private boolean ascending = true;
|
||||
|
||||
private Map<DatabaseType, AbstractSqlPagingQueryProvider> providers = new HashMap<DatabaseType, AbstractSqlPagingQueryProvider>();
|
||||
|
||||
private boolean ascending;
|
||||
|
||||
{
|
||||
providers.put(DB2, new Db2PagingQueryProvider());
|
||||
providers.put(DB2ZOS, new Db2PagingQueryProvider());
|
||||
|
||||
@@ -39,7 +39,7 @@ import org.springframework.util.Assert;
|
||||
* with the most specific, and the first match always succeeds.
|
||||
*
|
||||
* @see PrefixMatchingCompositeLineTokenizer
|
||||
* @see PatternMatcher#matchPrefix(String, Map)
|
||||
* @see PatternMatcher#match(String, Map)
|
||||
*
|
||||
* @author Dan Garrette
|
||||
* @since 2.0
|
||||
@@ -56,7 +56,7 @@ public class PrefixMatchingCompositeLineMapper<T> implements LineMapper<T>, Init
|
||||
* int)
|
||||
*/
|
||||
public T mapLine(String line, int lineNumber) throws Exception {
|
||||
return PatternMatcher.matchPrefix(line, this.fieldSetMappers).mapFieldSet(this.tokenizer.tokenize(line));
|
||||
return PatternMatcher.match(line, this.fieldSetMappers).mapFieldSet(this.tokenizer.tokenize(line));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -75,6 +75,13 @@ public class PrefixMatchingCompositeLineMapper<T> implements LineMapper<T>, Init
|
||||
}
|
||||
|
||||
public void setFieldSetMappers(Map<String, FieldSetMapper<T>> fieldSetMappers) {
|
||||
this.fieldSetMappers = new LinkedHashMap<String, FieldSetMapper<T>>(fieldSetMappers);
|
||||
this.fieldSetMappers = new LinkedHashMap<String, FieldSetMapper<T>>();
|
||||
for (String key : fieldSetMappers.keySet()) {
|
||||
FieldSetMapper<T> value = fieldSetMappers.get(key);
|
||||
if (!key.endsWith("*")) {
|
||||
key = key + "*";
|
||||
}
|
||||
this.fieldSetMappers.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,11 @@ import org.springframework.util.Assert;
|
||||
* are sorted starting with the most specific, and the first match always
|
||||
* succeeds.
|
||||
*
|
||||
* @see PatternMatcher#matchPrefix(String, Map)
|
||||
* @see PatternMatcher#match(String, Map)
|
||||
*
|
||||
* @author Ben Hale
|
||||
* @author Dan Garrette
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class PrefixMatchingCompositeLineTokenizer implements LineTokenizer, InitializingBean {
|
||||
|
||||
@@ -46,7 +47,7 @@ public class PrefixMatchingCompositeLineTokenizer implements LineTokenizer, Init
|
||||
* @see org.springframework.batch.item.file.transform.LineTokenizer#tokenize(java.lang.String)
|
||||
*/
|
||||
public FieldSet tokenize(String line) {
|
||||
return PatternMatcher.matchPrefix(line, this.tokenizers).tokenize(line);
|
||||
return PatternMatcher.match(line, this.tokenizers).tokenize(line);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -60,6 +61,13 @@ public class PrefixMatchingCompositeLineTokenizer implements LineTokenizer, Init
|
||||
}
|
||||
|
||||
public void setTokenizers(Map<String, LineTokenizer> tokenizers) {
|
||||
this.tokenizers = new LinkedHashMap<String, LineTokenizer>(tokenizers);
|
||||
this.tokenizers = new LinkedHashMap<String, LineTokenizer>();
|
||||
for (String key : tokenizers.keySet()) {
|
||||
LineTokenizer value = tokenizers.get(key);
|
||||
if (!key.endsWith("*")) {
|
||||
key = key + "*";
|
||||
}
|
||||
this.tokenizers.put(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,21 +21,14 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
* @author Dan Garrette
|
||||
*/
|
||||
public class PatternMatcher {
|
||||
|
||||
/**
|
||||
* Used for reverse-sorting strings
|
||||
*/
|
||||
private static Comparator<String> STRING_REVERSE_COMPARATOR = new Comparator<String>() {
|
||||
public int compare(String o1, String o2) {
|
||||
return o2.compareTo(o1);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Lifted from AntPathMatcher in Spring Core. Tests whether or not a string
|
||||
* matches against a pattern. The pattern may contain two special
|
||||
@@ -43,13 +36,11 @@ public class PatternMatcher {
|
||||
* '*' means zero or more characters<br>
|
||||
* '?' means one and only one character
|
||||
*
|
||||
* @param pattern
|
||||
* pattern to match against. Must not be <code>null</code>.
|
||||
* @param str
|
||||
* string which must be matched against the pattern. Must not be
|
||||
* <code>null</code>.
|
||||
* @param pattern pattern to match against. Must not be <code>null</code>.
|
||||
* @param str string which must be matched against the pattern. Must not be
|
||||
* <code>null</code>.
|
||||
* @return <code>true</code> if the string matches against the pattern, or
|
||||
* <code>false</code> otherwise.
|
||||
* <code>false</code> otherwise.
|
||||
*/
|
||||
public static boolean match(String pattern, String str) {
|
||||
char[] patArr = pattern.toCharArray();
|
||||
@@ -179,12 +170,12 @@ public class PatternMatcher {
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This method takes a String line and a map from String prefixes to values
|
||||
* of any type. During processing, the method will identify the most
|
||||
* specific prefix in the map that matches the beginning of the line. Once
|
||||
* the correct is identified, its value is returned. Note that if the map
|
||||
* contains the empty string as a prefix, then it will serve as the
|
||||
* "default" case, matching every non-null line given.
|
||||
* This method takes a String key and a map from Strings to values of any
|
||||
* type. During processing, the method will identify the most specific key
|
||||
* in the map that matches the line. Once the correct is identified, its
|
||||
* value is returned. Note that if the map contains the wildcard string "*"
|
||||
* as a key, then it will serve as the "default" case, matching every
|
||||
* line that does not match anything else.
|
||||
*
|
||||
* <p>
|
||||
* If no matching prefix is found, a {@link IllegalStateException} will be
|
||||
@@ -193,32 +184,34 @@ public class PatternMatcher {
|
||||
* <p>
|
||||
* Null keys are not allowed in the map.
|
||||
*
|
||||
* @param line
|
||||
* An input string
|
||||
* @param map
|
||||
* A map with String prefixes as keys.
|
||||
* @param line An input string
|
||||
* @param map A map with String prefixes as keys.
|
||||
* @return the value whose prefix matches the given line
|
||||
*/
|
||||
public static <S> S matchPrefix(String line, Map<String, S> map) {
|
||||
public static <S> S match(String line, Map<String, S> map) {
|
||||
S value = null;
|
||||
|
||||
if (line == null) {
|
||||
throw new IllegalStateException("Could not handle a null line");
|
||||
}
|
||||
Assert.notNull(line, "A non-null key must be provided.");
|
||||
|
||||
// Sort keys to start with the most specific
|
||||
List<String> sorted = new ArrayList<String>(map.keySet());
|
||||
Collections.sort(sorted, STRING_REVERSE_COMPARATOR);
|
||||
Collections.sort(sorted, new Comparator<String>() {
|
||||
public int compare(String o1, String o2) {
|
||||
String s1 = o1; // .replace('?', '{');
|
||||
String s2 = o2; // .replace('*', '}');
|
||||
return s2.compareTo(s1);
|
||||
}
|
||||
});
|
||||
for (String key : sorted) {
|
||||
if (line.startsWith(key)) {
|
||||
if (PatternMatcher.match(key, line)) {
|
||||
value = map.get(key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new IllegalStateException("Could not find a matching prefix for line=[" + line + "]");
|
||||
throw new IllegalStateException("Could not find a matching pattern for key=[" + line + "]");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -83,6 +83,13 @@ public class SqlPagingQueryProviderFactoryBeanTests {
|
||||
assertTrue("Wrong query: "+query, query.contains("x=y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAscending() throws Exception {
|
||||
PagingQueryProvider provider = (PagingQueryProvider) factory.getObject();
|
||||
String query = provider.generateFirstPageQuery(100);
|
||||
assertTrue("Wrong query: "+query, query.contains("ASC"));
|
||||
}
|
||||
|
||||
@Test(expected=IllegalArgumentException.class)
|
||||
public void testWrongDatabaseType() throws Exception {
|
||||
factory.setDatabaseType("NoSuchDb");
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.batch.item.file.transform.Name;
|
||||
|
||||
/**
|
||||
* @author Dan Garrette
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class PrefixMatchingCompositeLineMapperTests {
|
||||
|
||||
@@ -32,81 +32,87 @@ public class PatternMatcherTests {
|
||||
|
||||
private static Map<String, Integer> map = new HashMap<String, Integer>();
|
||||
static {
|
||||
map.put("an", 3);
|
||||
map.put("a", 2);
|
||||
map.put("big", 4);
|
||||
map.put("an*", 3);
|
||||
map.put("a*", 2);
|
||||
map.put("big*", 4);
|
||||
}
|
||||
|
||||
private static Map<String, Integer> defaultMap = new HashMap<String, Integer>();
|
||||
static {
|
||||
defaultMap.put("an", 3);
|
||||
defaultMap.put("a", 2);
|
||||
defaultMap.put("big", 4);
|
||||
defaultMap.put("", 1);
|
||||
defaultMap.put("big*", 4);
|
||||
defaultMap.put("big?*", 5);
|
||||
defaultMap.put("*", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_noWildcard_yes() {
|
||||
public void testMatchNoWildcardYes() {
|
||||
assertTrue(PatternMatcher.match("abc", "abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_noWildcard_no() {
|
||||
public void testMatchNoWildcardNo() {
|
||||
assertFalse(PatternMatcher.match("abc", "ab"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_qMark_yes() {
|
||||
public void testMatchSingleYes() {
|
||||
assertTrue(PatternMatcher.match("a?c", "abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_qMark_no() {
|
||||
public void testMatchSingleNo() {
|
||||
assertFalse(PatternMatcher.match("a?c", "ab"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_star_yes() {
|
||||
public void testMatchSingleWildcardNo() {
|
||||
assertTrue(PatternMatcher.match("a?*", "abc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchStarYes() {
|
||||
assertTrue(PatternMatcher.match("a*c", "abdegc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatch_star_no() {
|
||||
public void testMatchStarNo() {
|
||||
assertFalse(PatternMatcher.match("a*c", "abdeg"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_subsumed() {
|
||||
assertEquals(2, PatternMatcher.matchPrefix("apple", map).intValue());
|
||||
public void testMatchPrefixSubsumed() {
|
||||
assertEquals(2, PatternMatcher.match("apple", map).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_subsuming() {
|
||||
assertEquals(3, PatternMatcher.matchPrefix("animal", map).intValue());
|
||||
public void testMatchPrefixSubsuming() {
|
||||
assertEquals(3, PatternMatcher.match("animal", map).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_unrelated() {
|
||||
assertEquals(4, PatternMatcher.matchPrefix("biggest", map).intValue());
|
||||
public void testMatchPrefixUnrelated() {
|
||||
assertEquals(4, PatternMatcher.match("biggest", map).intValue());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testMatchPrefix_noMatch() {
|
||||
PatternMatcher.matchPrefix("bat", map);
|
||||
PatternMatcher.match("bat", map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_defaultValue_unrelated() {
|
||||
assertEquals(4, PatternMatcher.matchPrefix("biggest", defaultMap).intValue());
|
||||
public void testMatchPrefixDefaultValueUnrelated() {
|
||||
assertEquals(5, PatternMatcher.match("biggest", defaultMap).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_defaultValue_emptyString() {
|
||||
assertEquals(1, PatternMatcher.matchPrefix("", defaultMap).intValue());
|
||||
public void testMatchPrefixDefaultValueEmptyString() {
|
||||
assertEquals(1, PatternMatcher.match("", defaultMap).intValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMatchPrefix_defaultValue_noMatch() {
|
||||
assertEquals(1, PatternMatcher.matchPrefix("bat", defaultMap).intValue());
|
||||
public void testMatchPrefixDefaultValueNoMatch() {
|
||||
assertEquals(1, PatternMatcher.match("bat", defaultMap).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user