DATACMNS-15 - Added support to discover Distinct keyword.
Query method names now support Distinct in method name prefixes. Beyond that I laxed the prefix constraints a little so that it can potentially contain anything before a 'By' separator: - findByLastname -> simply query - findUsersByLastname -> simple query - findUsersDistinctByFirstname -> distinct query - findDistinctUsersByFirstname -> distinct query - findDistinctByLastname -> distinct query
This commit is contained in:
@@ -21,6 +21,7 @@ import static java.util.regex.Pattern.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -40,11 +41,13 @@ import org.springframework.util.Assert;
|
||||
public class PartTree implements Iterable<OrPart> {
|
||||
|
||||
private static final String ORDER_BY = "OrderBy";
|
||||
private static final String[] PREFIXES = new String[] { "findBy", "find",
|
||||
"readBy", "read", "getBy", "get" };
|
||||
private static final String PREFIX_TEMPLATE = "^%s(?=[A-Z]).*";
|
||||
private static final String KEYWORD_TEMPLATE = "(%s)(?=[A-Z])";
|
||||
private static final String DISTINCT = "Distinct";
|
||||
|
||||
private static final Pattern PREFIX_TEMPLATE = Pattern
|
||||
.compile("^(find|read|get)(\\p{Upper}.*?)??By");
|
||||
|
||||
private final boolean distinct;
|
||||
private final OrderBySource orderBySource;
|
||||
private final List<OrPart> nodes = new ArrayList<PartTree.OrPart>();
|
||||
|
||||
@@ -61,6 +64,7 @@ public class PartTree implements Iterable<OrPart> {
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(domainClass);
|
||||
|
||||
this.distinct = detectDistinct(source);
|
||||
String foo = strip(source);
|
||||
String[] parts = split(foo, ORDER_BY);
|
||||
|
||||
@@ -109,6 +113,17 @@ public class PartTree implements Iterable<OrPart> {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether we indicate distinct lookup of entities.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isDistinct() {
|
||||
|
||||
return distinct;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Splits the given text at the given keywords. Expects camelcase style to
|
||||
* only match concrete keywords and not derivatives of it.
|
||||
@@ -135,15 +150,33 @@ public class PartTree implements Iterable<OrPart> {
|
||||
*/
|
||||
private String strip(String methodName) {
|
||||
|
||||
for (String prefix : PREFIXES) {
|
||||
Matcher matcher = PREFIX_TEMPLATE.matcher(methodName);
|
||||
|
||||
String regex = format(PREFIX_TEMPLATE, prefix);
|
||||
if (methodName.matches(regex)) {
|
||||
return methodName.substring(prefix.length());
|
||||
}
|
||||
if (matcher.find()) {
|
||||
return methodName.substring(matcher.group().length());
|
||||
} else {
|
||||
return methodName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether the given source string contains the {@link #DISTINCT}
|
||||
* keyword in it's prefix.
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private boolean detectDistinct(String source) {
|
||||
|
||||
Matcher matcher = PREFIX_TEMPLATE.matcher(source);
|
||||
|
||||
if (!matcher.find()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return methodName;
|
||||
String group = matcher.group(2);
|
||||
return group != null && group.contains(DISTINCT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,6 +91,32 @@ public class PartTreeUnitTests {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectsDistinctCorrectly() throws Exception {
|
||||
|
||||
PartTree tree = new PartTree("findDistinctByLastname", User.class);
|
||||
assertThat(tree.isDistinct(), is(true));
|
||||
|
||||
tree = new PartTree("findUsersDistinctByLastname", User.class);
|
||||
assertThat(tree.isDistinct(), is(true));
|
||||
|
||||
tree = new PartTree("findDistinctUsersByLastname", User.class);
|
||||
assertThat(tree.isDistinct(), is(true));
|
||||
|
||||
tree = new PartTree("findUsersByLastname", User.class);
|
||||
assertThat(tree.isDistinct(), is(false));
|
||||
|
||||
tree = new PartTree("findByLastname", User.class);
|
||||
assertThat(tree.isDistinct(), is(false));
|
||||
|
||||
// Check it's non-greedy (would strip everything until Order*By*
|
||||
// otherwise)
|
||||
tree = new PartTree("findByLastnameOrderByFirstnameDesc", User.class);
|
||||
assertThat(tree.isDistinct(), is(false));
|
||||
assertThat(tree.getSort(), is(new Sort(Direction.DESC, "firstname")));
|
||||
}
|
||||
|
||||
|
||||
private void assertPart(PartTree tree, Part[]... parts) {
|
||||
|
||||
Iterator<OrPart> iterator = tree.iterator();
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
Spring Data Commons Changelog
|
||||
=============================================
|
||||
|
||||
Changes in version 1.0.0.M4
|
||||
----------------------------------------
|
||||
|
||||
Repository
|
||||
* Improved ParameterAccessor infrastructure
|
||||
* Added support for 'Distinct' keyword in finder method names
|
||||
|
||||
Changes in version 1.0.0.M3 (2011-02-09)
|
||||
----------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user