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:
Oliver Gierke
2011-02-21 18:08:16 +01:00
parent 5f89ccf966
commit aeee6935f5
3 changed files with 75 additions and 9 deletions

View File

@@ -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);
}
/**

View File

@@ -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();

View File

@@ -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)
----------------------------------------