diff --git a/build.gradle b/build.gradle
index f1411c85..1f6e4392 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,27 +3,15 @@ buildscript {
maven { url 'https://repo.spring.io/plugins-release' }
}
dependencies {
+ classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0'
+ classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE'
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.0'
classpath 'org.asciidoctor:asciidoctorj:1.5.0'
classpath 'org.springframework.build.gradle:bundlor-plugin:0.1.2'
classpath 'org.springframework.build.gradle:propdeps-plugin:0.0.6'
- classpath 'io.spring.gradle:docbook-reference-plugin:0.3.0'
- classpath 'io.spring.gradle:spring-io-plugin:0.0.4.RELEASE'
}
}
-configurations {
- sharedResources
-}
-
-description = 'Spring Data GemFire'
-group = 'org.springframework.data'
-
-repositories {
- maven { url "https://repo.spring.io/libs-snapshot" }
- maven { url "https://repo.spring.io/plugins-release"}
-}
-
apply plugin: "java"
apply plugin: 'eclipse'
apply plugin: 'idea'
@@ -33,7 +21,28 @@ apply plugin: 'propdeps'
apply plugin: 'docbook-reference'
apply plugin: 'org.asciidoctor.gradle.asciidoctor'
-//project.bundlor.bundleSymbolicName = "${bundleSymbolicName}"
+configurations {
+ sharedResources
+}
+
+description = 'Spring Data GemFire'
+group = 'org.springframework.data'
+
+sourceCompatibility = 1.6
+targetCompatibility = 1.6
+
+sourceSets {
+ main {
+ output.resourcesDir = 'build/classes/main'
+ output.classesDir = 'build/classes/main'
+ }
+ test {
+ output.resourcesDir = 'build/classes/test'
+ output.classesDir = 'build/classes/test'
+ }
+}
+
+[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial"]
if (project.hasProperty('platformVersion')) {
apply plugin: 'spring-io'
@@ -51,7 +60,13 @@ if (project.hasProperty('platformVersion')) {
}
}
-[compileJava, compileTestJava]*.options*.compilerArgs = ["-Xlint:-serial"]
+if (JavaVersion.current().isJava8Compatible()) {
+ allprojects {
+ tasks.withType(Javadoc) {
+ options.addStringOption('Xdoclint:none', '-quiet')
+ }
+ }
+}
tasks.withType(Test).all {
forkEvery = 1
@@ -60,7 +75,11 @@ tasks.withType(Test).all {
systemProperties['org.springframework.data.gemfire.test.GemfireTestRunner.nomock'] = System.getProperty('org.springframework.data.gemfire.test.GemfireTestRunner.nomock')
}
-// Common dependencies
+repositories {
+ maven { url "https://repo.spring.io/libs-snapshot" }
+ maven { url "https://repo.spring.io/plugins-release"}
+}
+
dependencies {
// Spring Framework
compile("org.springframework:spring-context-support:$springVersion") {
@@ -77,11 +96,10 @@ dependencies {
// GemFire
compile("com.gemstone.gemfire:gemfire:$gemfireVersion")
- optional("com.google.code.findbugs:annotations:2.0.2")
+ optional("com.google.code.findbugs:annotations:$googleCodeFindbugsVersion")
runtime("antlr:antlr:$antlrVersion")
compile "org.aspectj:aspectjweaver:$aspectjVersion"
- compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion"
@@ -89,6 +107,7 @@ dependencies {
testCompile("org.springframework:spring-test:$springVersion") {
exclude group: "commons-logging", module: "commons-logging"
}
+ testCompile "org.assertj:assertj-core:$assertjVersion"
testCompile "junit:junit:$junitVersion"
testCompile "org.hamcrest:hamcrest-core:$hamcrestVersion"
testCompile "org.hamcrest:hamcrest-library:$hamcrestVersion"
@@ -103,58 +122,18 @@ dependencies {
sharedResources "org.springframework.data.build:spring-data-build-resources:$springDataBuildVersion@zip"
}
-sourceCompatibility = 1.6
-targetCompatibility = 1.6
-
-if (JavaVersion.current().isJava8Compatible()) {
- allprojects {
- tasks.withType(Javadoc) {
- options.addStringOption('Xdoclint:none', '-quiet')
- }
- }
- }
-
-javadoc {
- dependsOn = [ 'extractSharedResources' ]
-
- ext.srcDir = file("${projectDir}/docs/src/api")
- destinationDir = file("${buildDir}/api")
- ext.tmpDir = file("${buildDir}/api-work")
-
- configure(options) {
- stylesheetFile = file("$buildDir/shared-resources/javadoc/spring-javadoc.css")
- overview = "${srcDir}/overview.html"
- docFilesSubDirs = true
- outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
- breakIterator = true
- showFromProtected()
- groups = [
- 'Spring GemFire' : ['org.springframework.data.gemfire*'],
- ]
-
- links = [
- "http://static.springframework.org/spring/docs/3.1.x/javadoc-api",
- "http://download.oracle.com/javase/6/docs/api",
- "http://www.gemstone.com/docs/6.5.1/product/docs/japi/",
- "http://asm.objectweb.org/asm223/javadoc/user",
- "http://logging.apache.org/log4j/docs/api/",
- "http://atinject.googlecode.com/svn/trunk/javadoc/"
- ]
-
- exclude "org/springframework/data/gemfire/config/**"
- }
-
- title = "${rootProject.description} ${version} API"
+bundlor {
+ manifestTemplate = file("template.mf").text
}
jar {
-
dependsOn = [ 'bundlor' ]
manifest.attributes['Implementation-Title'] = 'spring-data-gemfire'
manifest.attributes['Implementation-Version'] = project.version
- from("$rootDir/docs/src/info") {
+ from("$rootDir/src/main/resources") {
+ include "changelog.txt"
include "license.txt"
include "notice.txt"
into "META-INF"
@@ -162,23 +141,49 @@ jar {
}
}
-bundlor {
- manifestTemplate = file("template.mf").text
+task extractSharedResources(type: Copy) {
+
+ from { // use of closure defers evaluation until execution time
+ configurations.sharedResources.collect { zipTree(it) }
+ }
+
+ into "$buildDir/shared-resources"
}
-// Reference documentation
+javadoc {
+ dependsOn = [ 'extractSharedResources' ]
-reference {
- // Avoid copy with expansions
- expandPlaceholders = '';
-}
+ destinationDir = file("${buildDir}/api")
+ ext.tmpDir = file("${buildDir}/api-work")
-referencePdf {
- dependsOn = [ 'asciidoctor' ]
- sourceDir = asciidoctor.outputDir
+ configure(options) {
+ stylesheetFile = file("$buildDir/shared-resources/javadoc/spring-javadoc.css")
+ docFilesSubDirs = true
+ outputLevel = org.gradle.external.javadoc.JavadocOutputLevel.QUIET
+ breakIterator = true
+ showFromProtected()
+
+ groups = [
+ 'Spring GemFire' : ['org.springframework.data.gemfire*'],
+ ]
+
+ links = [
+ "http://static.springframework.org/spring/docs/3.1.x/javadoc-api",
+ "http://download.oracle.com/javase/6/docs/api",
+ "http://www.gemstone.com/docs/6.5.1/product/docs/japi/",
+ "http://asm.objectweb.org/asm223/javadoc/user",
+ "http://logging.apache.org/log4j/docs/api/",
+ "http://atinject.googlecode.com/svn/trunk/javadoc/"
+ ]
+
+ exclude "org/springframework/data/gemfire/config/**"
+ }
+
+ title = "${rootProject.description} ${version} API"
}
asciidoctor {
+ sourceDir = file("${projectDir}/src/main/asciidoc")
dependsOn = [ 'extractSharedResources' ]
backends = [ 'html5', 'docbook' ]
options = [
@@ -199,6 +204,15 @@ asciidoctor {
]
}
+reference {
+ expandPlaceholders = ''; // Avoid copy with expansions
+}
+
+referencePdf {
+ dependsOn = [ 'asciidoctor' ]
+ sourceDir = asciidoctor.outputDir
+}
+
task sourcesJar(type: Jar, dependsOn:classes) {
classifier = 'sources'
from sourceSets.main.allJava
@@ -215,7 +229,7 @@ task docsZip(type: Zip) {
description = "Builds -${classifier} archive containing api and reference for deployment"
dependsOn = [ 'javadoc', 'asciidoctor', 'referencePdf' ]
- from('docs/src/info') {
+ from('src/main/resources') {
include 'changelog.txt'
}
@@ -248,10 +262,13 @@ task schemaZip(type: Zip) {
for (def key : schemas.keySet()) {
def shortName = key.replaceAll(/http.*schema.(.*).spring-.*/, '$1')
def alias = key.replaceAll(/http.*schema.(.*).(spring-.*)/, '$2')
+
assert shortName != key
+
File xsdFile = sourceSets.main.resources.find {
it.path.replace('\\', '/').endsWith(schemas.get(key))
}
+
assert xsdFile != null
into (shortName) {
@@ -270,10 +287,11 @@ task distZip(type: Zip, dependsOn: [jar, docsZip, schemaZip, sourcesJar, javadoc
ext.zipRootDir = "${project.name}-${project.version}"
into (zipRootDir) {
- from('docs/src/info') {
- include 'readme.txt'
+ from('src/main/resources') {
+ include 'changelog.txt'
include 'license.txt'
include 'notice.txt'
+ include 'readme.txt'
expand(copyright: new Date().format('yyyy'), version: project.version)
}
@@ -302,7 +320,6 @@ task distZip(type: Zip, dependsOn: [jar, docsZip, schemaZip, sourcesJar, javadoc
artifacts {
archives sourcesJar
archives javadocJar
-
archives docsZip
archives schemaZip
archives distZip
@@ -316,22 +333,15 @@ task wrapper(type: Wrapper) {
def gradleOpts = "-XX:MaxPermSize=1024m -Xms256m -Xmx1024m"
def gradleBatOpts = "$gradleOpts -XX:MaxHeapSize=1024m"
File wrapperFile = file("gradlew")
+
wrapperFile.text = wrapperFile.text.replace("DEFAULT_JVM_OPTS=",
"GRADLE_OPTS=\"$gradleOpts \$GRADLE_OPTS\"\nDEFAULT_JVM_OPTS=")
File wrapperBatFile = file("gradlew.bat")
+
wrapperBatFile.text = wrapperBatFile.text.replace("set DEFAULT_JVM_OPTS=",
"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
}
}
-task extractSharedResources(type: Copy) {
-
- from { // use of closure defers evaluation until execution time
- configurations.sharedResources.collect { zipTree(it) }
- }
-
- into "$buildDir/shared-resources"
-}
-
assemble.dependsOn = ['jar', 'sourcesJar']
defaultTasks 'build'
diff --git a/gradle.properties b/gradle.properties
index a20bf38c..1b5c2041 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,6 +1,8 @@
antlrVersion=2.7.7
aspectjVersion=1.8.5
+assertjVersion=3.5.2
gemfireVersion=8.1.0
+googleCodeFindbugsVersion=2.0.2
hamcrestVersion=1.3
jacksonVersion=2.6.4
junitVersion=4.12
@@ -10,6 +12,6 @@ multiThreadedtcVersion=1.01
slf4jVersion=1.7.12
spring.range="[4.0.0, 5.0.0)"
springVersion=4.1.9.RELEASE
-springDataBuildVersion=1.7.5.BUILD-SNAPSHOT
-springDataCommonsVersion=1.11.5.BUILD-SNAPSHOT
+springDataBuildVersion=1.7.6.BUILD-SNAPSHOT
+springDataCommonsVersion=1.11.6.BUILD-SNAPSHOT
version=1.7.5.BUILD-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index af048cd6..f82c6ad3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -3,27 +3,43 @@
4.0.0
+
+ org.springframework.data.build
+ spring-data-parent
+ 1.7.6.BUILD-SNAPSHOT
+
+
org.springframework.data
spring-data-gemfire
1.7.6.BUILD-SNAPSHOT
Spring Data Gemfire
-
- org.springframework.data.build
- spring-data-parent
- 1.7.5.RELEASE
-
-
SGF
2.7.7
+ 3.5.2
8.1.0
+ 2.0.2
1.01
- 1.11.5.RELEASE
+ 1.11.6.BUILD-SNAPSHOT
1.0.0.RELEASE
+
+
+ spring-libs-release
+ https://repo.spring.io/libs-snapshot
+
+
+
+
+
+ spring-plugins-release
+ https://repo.spring.io/plugins-release
+
+
+
@@ -58,7 +74,7 @@
com.google.code.findbugs
annotations
- 2.0.2
+ ${google-code-findbugs.version}
true
@@ -91,6 +107,13 @@
+
+ org.assertj
+ assertj-core
+ ${assertj.version}
+ test
+
+
org.apache.derby
derbyLocale_zh_TW
@@ -172,18 +195,4 @@
-
-
- spring-libs-release
- https://repo.spring.io/libs-release
-
-
-
-
-
- spring-plugins-release
- https://repo.spring.io/plugins-release
-
-
-
diff --git a/src/main/java/org/springframework/data/gemfire/repository/query/QueryBuilder.java b/src/main/java/org/springframework/data/gemfire/repository/query/QueryBuilder.java
index dead037d..df8a0d1a 100644
--- a/src/main/java/org/springframework/data/gemfire/repository/query/QueryBuilder.java
+++ b/src/main/java/org/springframework/data/gemfire/repository/query/QueryBuilder.java
@@ -13,14 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.springframework.data.gemfire.repository.query;
import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
+import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.Assert;
/**
- * The QueryBuilder class is used to build a QueryString.
+ * The QueryBuilder class is used to build a {@link QueryString}.
*
* @author Oliver Gierke
* @author David Turanski
@@ -30,22 +32,73 @@ import org.springframework.util.Assert;
class QueryBuilder {
static final String DEFAULT_ALIAS = "x";
+ static final String SELECT_OQL_TEMPLATE = "SELECT %1$s * FROM /%2$s %3$s";
+ static final String WHERE_CLAUSE_TEMPLATE = "%1$s WHERE %2$s";
private final String query;
- public QueryBuilder(String source) {
- Assert.hasText(source, "The OQL Query must be specified");
- this.query = source;
+ /* (non-Javadoc) */
+ static String asQuery(GemfirePersistentEntity> entity, PartTree tree) {
+ return String.format(SELECT_OQL_TEMPLATE, (tree.isDistinct() ? OqlKeyword.DISTINCT : ""),
+ entity.getRegionName(), DEFAULT_ALIAS).replaceAll("\\s{2,}", " ");
}
+ /* (non-Javadoc) */
+ static String validateQuery(String query) {
+ Assert.hasText(query, "An OQL Query must be specified");
+ return query;
+ }
+
+ /**
+ * Constructs an instance of {@link QueryBuilder} initialized with the given query {@link String}.
+ *
+ * @param query {@link String} containing the base OQL query.
+ * @see #validateQuery(String)
+ */
+ public QueryBuilder(String query) {
+ this.query = validateQuery(query);
+ }
+
+ /**
+ * Constructs an instance of {@link QueryBuilder} with the given {@link GemfirePersistentEntity}
+ * and {@link PartTree} that determines the GemFire {@link com.gemstone.gemfire.cache.Region}
+ * to query and whether the query should capture unique results.
+ *
+ * @param entity {@link GemfirePersistentEntity} used to determine the GemFire
+ * {@link com.gemstone.gemfire.cache.Region} to query.
+ * @param tree {@link PartTree} containing parts of the OQL Query for determining things
+ * like uniqueness.
+ * @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
+ * @see org.springframework.data.repository.query.parser.PartTree
+ */
public QueryBuilder(GemfirePersistentEntity> entity, PartTree tree) {
- this(String.format("SELECT%1$s * FROM /%2$s %3$s", (tree.isDistinct() ? " DISTINCT" : ""),
- entity.getRegionName(), DEFAULT_ALIAS));
+ this(asQuery(entity, tree));
}
+ /**
+ * Constructs a {@link QueryString} with the given {@link Predicate}.
+ *
+ * @param predicate {@link Predicate} to append to the query.
+ * @return a {@link QueryString} with the base OQL query and {@link Predicate}.
+ * @see org.springframework.data.gemfire.repository.query.Predicate
+ * @see #withPredicate(String, Predicate)
+ */
public QueryString create(Predicate predicate) {
- return new QueryString(predicate != null ? String.format("%1$s WHERE %2$s", query,
- predicate.toString(DEFAULT_ALIAS)) : query);
+ return new QueryString(withPredicate(this.query, predicate));
+ }
+
+ /**
+ * Appends the given {@link Predicate} to the given {@code query} {@link String}.
+ *
+ * @param query {@link String} containing the query.
+ * @param predicate {@link Predicate} to append to the query.
+ * @return a {@link String} containing the query with the {@link Predicate} appended,
+ * or just a {@link String} containing the query if the {@link Predicate} is {@literal null}.
+ * @see org.springframework.data.gemfire.repository.query.Predicate
+ */
+ protected String withPredicate(String query, Predicate predicate) {
+ return (predicate == null ? query
+ : String.format(WHERE_CLAUSE_TEMPLATE, query, predicate.toString(DEFAULT_ALIAS)));
}
/*
@@ -54,6 +107,6 @@ class QueryBuilder {
*/
@Override
public String toString() {
- return query;
+ return this.query;
}
}
diff --git a/src/main/java/org/springframework/data/gemfire/repository/query/QueryString.java b/src/main/java/org/springframework/data/gemfire/repository/query/QueryString.java
index 9a6a9f86..628bfdf2 100644
--- a/src/main/java/org/springframework/data/gemfire/repository/query/QueryString.java
+++ b/src/main/java/org/springframework/data/gemfire/repository/query/QueryString.java
@@ -21,15 +21,16 @@ import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import com.gemstone.gemfire.cache.Region;
+
import org.springframework.data.domain.Sort;
+import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
-import com.gemstone.gemfire.cache.Region;
-
/**
- * Value object to work with OQL query strings.
+ * The QueryString class is a utility class for working with GemFire OQL query statement syntax.
*
* @author Oliver Gierke
* @author David Turanski
@@ -43,52 +44,74 @@ public class QueryString {
protected static final Pattern TRACE_PATTERN = Pattern.compile("");
// OQL Query Templates
- private static final String HINTS_QUERY_TEMPLATE = " %2$s";
- private static final String IMPORT_QUERY_TEMPLATE = "IMPORT %1$s; %2$s";
- private static final String LIMIT_QUERY_TEMPLATE = "%1$s LIMIT %2$d";
- private static final String SELECT_QUERY_TEMPLATE = "SELECT %1$s FROM /%2$s";
- private static final String TRACE_QUERY_TEMPLATE = " %1$s";
+ private static final String HINTS_OQL_TEMPLATE = " %2$s";
+ private static final String IMPORT_OQL_TEMPLATE = "IMPORT %1$s; %2$s";
+ private static final String LIMIT_OQL_TEMPLATE = "%1$s LIMIT %2$d";
+ private static final String SELECT_OQL_TEMPLATE = "SELECT %1$s FROM /%2$s";
+ private static final String TRACE_OQL_TEMPLATE = " %1$s";
- // Query Regular Expression Patterns
+ // OQL Query Regular Expression Patterns
private static final String IN_PATTERN = "(?<=IN (SET|LIST) )\\$\\d";
private static final String IN_PARAMETER_PATTERN = "(?<=IN (SET|LIST) \\$)\\d";
private static final String REGION_PATTERN = "\\/(\\/?\\w)+";
private final String query;
- /**
- * Creates a {@link QueryString} from the given {@link String} query.
- *
- * @param source a String containing the OQL Query.
- */
- public QueryString(String source) {
- Assert.hasText(source, "The OQL statement (Query) to execute must be specified!");
- this.query = source;
+ /* (non-Javadoc) */
+ static String asQuery(Class> domainType, boolean isCountQuery) {
+ return String.format(SELECT_OQL_TEMPLATE, (isCountQuery ? "count(*)" : "*"),
+ validateDomainType(domainType).getSimpleName());
+ }
+
+ /* (non-Javadoc) */
+ static Class validateDomainType(Class domainType) {
+ Assert.notNull(domainType, "domainType must not be null");
+ return domainType;
+ }
+
+ /* (non-Javadoc) */
+ static String validateQuery(String query) {
+ Assert.hasText(query, "An OQL Query must be specified");
+ return query;
}
/**
- * Creates a {@literal SELECT} query for the given domain class.
+ * Constructs an instance of {@link QueryString} initialized with the given GemFire OQL Query {@link String}.
*
- * @param domainClass must not be {@literal null}.
+ * @param query {@link String} specifying the GemFire OQL Query.
+ * @throws IllegalArgumentException if the query string is unspecified (null or empty).
+ */
+ public QueryString(String query) {
+ this.query = validateQuery(query);
+ }
+
+ /**
+ * Constructs a GemFire OQL {@literal SELECT} Query for the given domain class.
+ *
+ * @param domainType application domain object type to query; must not be {@literal null}.
+ * @see #QueryString(Class, boolean)
*/
@SuppressWarnings("unused")
- public QueryString(Class> domainClass) {
- this(domainClass, false);
+ public QueryString(Class> domainType) {
+ this(domainType, false);
}
/**
- * Creates a {@literal SELECT} query for the given domain class.
+ * Constructs a GemFire OQL {@literal SELECT} Query for the given domain class. {@code isCountQuery} indicates
+ * whether to select a count or select the contents of the objects of the given domain object type.
*
- * @param domainClass must not be {@literal null}.
- * @param isCountQuery indicates if this is a count query
+ * @param domainType application domain object type to query; must not be {@literal null}.
+ * @param isCountQuery boolean value to indicate if this is a count query.
+ * @throws IllegalArgumentException if {@code domainType} is null.
+ * @see #QueryString(String)
*/
- public QueryString(Class> domainClass, boolean isCountQuery) {
- this(String.format(SELECT_QUERY_TEMPLATE, (isCountQuery ? "count(*)" : "*"), domainClass.getSimpleName()));
+ public QueryString(Class> domainType, boolean isCountQuery) {
+ this(asQuery(domainType, isCountQuery));
}
/**
- * Binds the given values to the {@literal IN} parameter keyword by expanding the given values into a comma-separated
- * {@link String}.
+ * Binds the given {@link Collection} of values into the {@literal IN} parameters of the OQL Query by expanding
+ * the given values into a comma-separated {@link String}.
*
* @param values the values to bind, returns the {@link QueryString} as is if {@literal null} is given.
* @return a Query String having "in" parameters bound with values.
@@ -96,7 +119,7 @@ public class QueryString {
public QueryString bindIn(Collection> values) {
if (values != null) {
String valueString = StringUtils.collectionToDelimitedString(values, ", ", "'", "'");
- return new QueryString(query.replaceFirst(IN_PATTERN, String.format("(%s)", valueString)));
+ return new QueryString(this.query.replaceFirst(IN_PATTERN, String.format("(%s)", valueString)));
}
return this;
@@ -113,7 +136,7 @@ public class QueryString {
*/
@SuppressWarnings("unused")
public QueryString forRegion(Class> domainClass, Region, ?> region) {
- return new QueryString(query.replaceAll(REGION_PATTERN, region.getFullPath()));
+ return new QueryString(this.query.replaceAll(REGION_PATTERN, region.getFullPath()));
}
/**
@@ -135,11 +158,11 @@ public class QueryString {
}
/**
- * Appends the Sort order to this GemFire OQL Query string.
+ * Appends the {@link Sort} order to this GemFire OQL Query string.
*
- * @param sort the Sort object indicating the order by criteria.
- * @return this QueryString with an ORDER BY clause if the Sort object is not null, or this QueryString as-is
- * if the Sort object is null.
+ * @param sort {@link Sort} indicating the order of the query results.
+ * @return a new {@link QueryString} with an ORDER BY clause if {@link Sort} is not {@literal null},
+ * or this {@link QueryString} as-is if {@link Sort} is {@literal null}.
* @see org.springframework.data.domain.Sort
* @see org.springframework.data.gemfire.repository.query.QueryString
*/
@@ -153,12 +176,30 @@ public class QueryString {
orderClause.append(String.format("%1$s %2$s", order.getProperty(), order.getDirection()));
}
- return new QueryString(String.format("%1$s %2$s", this.query, orderClause.toString()));
+ return new QueryString(String.format("%1$s %2$s", makeDistinct(this.query), orderClause.toString()));
}
return this;
}
+ /**
+ * Replaces the SELECT query with a SELECT DISTINCT query if the query does not contain the DISTINCT OQL keyword.
+ *
+ * @param query {@link String} containing the query to evaluate.
+ * @return a SELECT DISTINCT query if {@code query} does not contain the DISTINCT OQL keyword.
+ */
+ String makeDistinct(String query) {
+ return (query.contains(OqlKeyword.DISTINCT.getKeyword()) ? query
+ : query.replaceFirst(OqlKeyword.SELECT.getKeyword(),
+ String.format("%1$s %2$s", OqlKeyword.SELECT.getKeyword(), OqlKeyword.DISTINCT.getKeyword())));
+ }
+
+ /**
+ * Applies HINTS to the OQL Query.
+ *
+ * @param hints array of {@link String Strings} containing query hints.
+ * @return a new {@link QueryString} if hints are not null or empty, or return this {@link QueryString}.
+ */
public QueryString withHints(String... hints) {
if (!ObjectUtils.isEmpty(hints)) {
StringBuilder builder = new StringBuilder();
@@ -168,23 +209,40 @@ public class QueryString {
builder.append(String.format("'%1$s'", hint));
}
- return new QueryString(String.format(HINTS_QUERY_TEMPLATE, builder.toString(), query));
+ return new QueryString(String.format(HINTS_OQL_TEMPLATE, builder.toString(), query));
}
return this;
}
+ /**
+ * Applies an IMPORT to the OQL Query.
+ *
+ * @param importExpression {@link String} containing the import clause.
+ * @return a new {@link QueryString} if an import was declared, or return this {@link QueryString}.
+ */
public QueryString withImport(String importExpression) {
- return (StringUtils.hasText(importExpression) ? new QueryString(
- String.format(IMPORT_QUERY_TEMPLATE, importExpression, query)) : this);
+ return (StringUtils.hasText(importExpression) ?
+ new QueryString(String.format(IMPORT_OQL_TEMPLATE, importExpression, query)) : this);
}
+ /**
+ * Applies a LIMIT to the OQL Query.
+ *
+ * @param limit {@link Integer} indicating the number of results to return from the query.
+ * @return a new {@link QueryString} if a limit was specified, or return this {@link QueryString}.
+ */
public QueryString withLimit(Integer limit) {
- return (limit != null ? new QueryString(String.format(LIMIT_QUERY_TEMPLATE, query, limit)) : this);
+ return (limit != null ? new QueryString(String.format(LIMIT_OQL_TEMPLATE, query, limit)) : this);
}
+ /**
+ * Applies TRACE logging to the OQL Query.
+ *
+ * @return a new {@link QueryString} with tracing enabled.
+ */
public QueryString withTrace() {
- return new QueryString(String.format(TRACE_QUERY_TEMPLATE, query));
+ return new QueryString(String.format(TRACE_OQL_TEMPLATE, query));
}
/*
diff --git a/src/main/java/org/springframework/data/gemfire/repository/query/support/OqlKeyword.java b/src/main/java/org/springframework/data/gemfire/repository/query/support/OqlKeyword.java
new file mode 100644
index 00000000..b824832c
--- /dev/null
+++ b/src/main/java/org/springframework/data/gemfire/repository/query/support/OqlKeyword.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2012 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.data.gemfire.repository.query.support;
+
+import org.springframework.util.StringUtils;
+
+/**
+ * The OqlKeyword enum represents the range of keywords (Reserved Words)
+ * in GemFire's Object Query Language (OQL).
+ *
+ * @author John Blum
+ * @see Supported Keywords
+ * @since 1.0.0
+ */
+public enum OqlKeyword {
+ AND,
+ AS,
+ COUNT,
+ DISTINCT,
+ ELEMENT,
+ FROM,
+ HINT,
+ IMPORT,
+ IN,
+ IS_DEFINED,
+ IS_UNDEFINED,
+ LIMIT,
+ LIKE,
+ NOT,
+ NVL,
+ OR,
+ ORDER_BY("ORDER BY"),
+ SELECT,
+ SET,
+ TRACE,
+ TO_DATE,
+ TYPE,
+ WHERE;
+
+ private final String keyword;
+
+ /**
+ * Constructs an instance of the GemFire {@link OqlKeyword} enumerate value with an unspecified keyword.
+ * When the keyword is unspecified, it defaults to the {@link #name()} of the {@link OqlKeyword}.
+ *
+ * @see #OqlKeyword(String)
+ */
+ OqlKeyword() {
+ this(null);
+ }
+
+ /**
+ * Constructs an {@link OqlKeyword} enumerated value with the given GemFire OQL Keyword.
+ *
+ * @param keyword {@link String} specifying the GemFire OQL Keyword;
+ * can be {@literal null}.
+ */
+ OqlKeyword(String keyword) {
+ this.keyword = keyword;
+ }
+
+ /**
+ * Looks up an {@link OqlKeyword} for the given {@code keyword} {@link String}.
+ *
+ * @param keyword name of the GemFire OQL Keyword to lookup.
+ * @return an {@link OqlKeyword} enumerated value for the given {@code keyword} {@link String}.
+ * @throws IllegalArgumentException if {@code keyword} is not a valid GemFire OQL Keyword.
+ */
+ public static OqlKeyword valueOfIgnoreCase(String keyword) {
+ for (OqlKeyword oqlKeyword : values()) {
+ if (oqlKeyword.getKeyword().equalsIgnoreCase(StringUtils.trimWhitespace(keyword))) {
+ return oqlKeyword;
+ }
+ }
+
+ throw new IllegalArgumentException(String.format("[%s] is not a valid GemFire OQL Keyword", keyword));
+ }
+
+ /**
+ * Returns name of this GemFire OQL Keyword enumerated value. The keyword may have been
+ * explicitly defined when the {@link OqlKeyword} enumerated value was constructed, in which case
+ * this value is returned, otherwise this method returns {@link OqlKeyword#name()}.
+ *
+ * @return a {@link String} name for this GemFire OQL Keyword enumerated value.
+ * @see #name()
+ */
+ public String getKeyword() {
+ return (StringUtils.hasText(this.keyword) ? this.keyword : name());
+ }
+
+ /* (non-Javadoc) */
+ @Override
+ public String toString() {
+ return getKeyword();
+ }
+}
diff --git a/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java b/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java
index 2bc50a49..3764baff 100644
--- a/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java
+++ b/src/main/java/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.java
@@ -39,7 +39,7 @@ import com.gemstone.gemfire.cache.query.SelectResults;
/**
* Basic Repository implementation for GemFire.
- *
+ *
* @author Oliver Gierke
* @author David Turanski
* @author John Blum
@@ -56,12 +56,12 @@ public class SimpleGemfireRepository implements Gemf
/**
* Creates a new {@link SimpleGemfireRepository}.
- *
+ *
* @param template must not be {@literal null}.
* @param entityInformation must not be {@literal null}.
*/
public SimpleGemfireRepository(GemfireTemplate template, EntityInformation entityInformation) {
-
+
Assert.notNull(template);
Assert.notNull(entityInformation);
@@ -71,7 +71,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.data.repository.CrudRepository#save(S)
*/
@Override
@@ -82,7 +82,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
*/
@Override
@@ -123,7 +123,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable)
*/
@Override
@@ -144,7 +144,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.data.repository.CrudRepository#findAll()
*/
@Override
@@ -158,7 +158,7 @@ public class SimpleGemfireRepository implements Gemf
* @see org.springframework.data.gemfire.repository.GemfireRepository.sort(:org.springframework.data.domain.Sort)
*/
@Override
- public Iterable findAll(final Sort sort) {
+ public Iterable findAll(Sort sort) {
QueryString query = new QueryString("SELECT * FROM /RegionPlaceholder")
.forRegion(entityInformation.getJavaType(), template.getRegion())
.orderBy(sort);
@@ -197,7 +197,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see
* org.springframework.data.repository.CrudRepository#delete(java.lang.Object)
*/
@@ -208,7 +208,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see
* org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable)
*/
@@ -267,7 +267,7 @@ public class SimpleGemfireRepository implements Gemf
/*
* (non-Javadoc)
- *
+ *
* @see org.springframework.data.repository.CrudRepository#deleteAll()
*/
@Override
diff --git a/src/test/java/org/springframework/data/gemfire/repository/OqlKeywordUnitTests.java b/src/test/java/org/springframework/data/gemfire/repository/OqlKeywordUnitTests.java
new file mode 100644
index 00000000..3312a3de
--- /dev/null
+++ b/src/test/java/org/springframework/data/gemfire/repository/OqlKeywordUnitTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 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.data.gemfire.repository;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.springframework.data.gemfire.repository.query.support.OqlKeyword;
+
+/**
+ * Test suite of test cases testing the contract and functionality
+ * of the {@link OqlKeyword} enumerated type.
+ *
+ * @author John Blum
+ * @see org.junit.Test
+ * @see org.springframework.data.gemfire.repository.query.support.OqlKeyword
+ * @since 1.0.0
+ */
+public class OqlKeywordUnitTests {
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void valueOfIgnoreCaseWithEnumeratedValuesIsSuccessful() {
+ for (OqlKeyword oqlKeyword : OqlKeyword.values()) {
+ assertThat(OqlKeyword.valueOfIgnoreCase(oqlKeyword.getKeyword())).isEqualTo(oqlKeyword);
+ }
+ }
+
+ @Test
+ public void valueOfIgnoreCaseWithUnconventionalValuesIsSuccessful() {
+ assertThat(OqlKeyword.valueOfIgnoreCase("and")).isEqualTo(OqlKeyword.AND);
+ assertThat(OqlKeyword.valueOfIgnoreCase("As")).isEqualTo(OqlKeyword.AS);
+ assertThat(OqlKeyword.valueOfIgnoreCase("CoUnT")).isEqualTo(OqlKeyword.COUNT);
+ assertThat(OqlKeyword.valueOfIgnoreCase(" DISTINCT ")).isEqualTo(OqlKeyword.DISTINCT);
+ assertThat(OqlKeyword.valueOfIgnoreCase(" Order BY ")).isEqualTo(OqlKeyword.ORDER_BY);
+ }
+
+ @Test
+ public void valueOfIgnoreCaseWithIllegalValuesThrowsIllegalArgumentException() {
+ assertIllegalOqlKeyword("AN");
+ assertIllegalOqlKeyword("ASS");
+ assertIllegalOqlKeyword("CNT");
+ assertIllegalOqlKeyword("EXTINCT");
+ assertIllegalOqlKeyword("TO");
+ assertIllegalOqlKeyword("EXPORT");
+ assertIllegalOqlKeyword("OUT");
+ assertIllegalOqlKeyword("IS DEFINED");
+ assertIllegalOqlKeyword("IS-UNDEFINED");
+ assertIllegalOqlKeyword("UNLIKE");
+ assertIllegalOqlKeyword("NIL");
+ assertIllegalOqlKeyword("NULL VALUE");
+ assertIllegalOqlKeyword("XOR");
+ assertIllegalOqlKeyword("ORDER_BY");
+ assertIllegalOqlKeyword("INSERT");
+ assertIllegalOqlKeyword("UPDATE");
+ assertIllegalOqlKeyword("LIST");
+ assertIllegalOqlKeyword("CLASS");
+ assertIllegalOqlKeyword("WHAT");
+ assertIllegalOqlKeyword("WHEN");
+ }
+
+ protected void assertIllegalOqlKeyword(String keyword) {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectCause(is(nullValue(Throwable.class)));
+ exception.expectMessage(String.format("[%s] is not a valid GemFire OQL Keyword", keyword));
+
+ OqlKeyword.valueOfIgnoreCase(keyword);
+ }
+
+ @Test
+ public void getKeywordEqualsNameExceptForOrderBy() {
+ for (OqlKeyword oqlKeyword : OqlKeyword.values()) {
+ if (!OqlKeyword.ORDER_BY.equals(oqlKeyword)) {
+ assertThat(oqlKeyword.getKeyword()).isEqualTo(oqlKeyword.name());
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderTest.java b/src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderUnitTests.java
similarity index 60%
rename from src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderTest.java
rename to src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderUnitTests.java
index c1eb85f5..4f8f400d 100644
--- a/src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderTest.java
+++ b/src/test/java/org/springframework/data/gemfire/repository/query/QueryBuilderUnitTests.java
@@ -16,11 +16,10 @@
package org.springframework.data.gemfire.repository.query;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -34,48 +33,46 @@ import org.springframework.data.gemfire.mapping.GemfirePersistentEntity;
import org.springframework.data.repository.query.parser.PartTree;
/**
- * The QueryBuilderTest class is a test suite of test cases testing the contract and functionality of the QueryBuilder
- * class.
+ * Test suite of test cases testing the contract and functionality of the {@link QueryBuilder} class.
*
* @author John Blum
- * @see org.junit.Rule
* @see org.junit.Test
* @see org.mockito.Mockito
* @see org.springframework.data.gemfire.repository.query.QueryBuilder
* @since 1.7.0
*/
-public class QueryBuilderTest {
+public class QueryBuilderUnitTests {
@Rule
- public ExpectedException expectedException = ExpectedException.none();
+ public ExpectedException exception = ExpectedException.none();
@Test
- public void createQueryBuilderNonDistinct() {
- GemfirePersistentEntity> mockPersistentEntity = mock(GemfirePersistentEntity.class, "MockGemfirePersistentEntity");
- PartTree mockPartTree = mock(PartTree.class, "MockPartTree");
-
- when(mockPersistentEntity.getRegionName()).thenReturn("Example");
- when(mockPartTree.isDistinct()).thenReturn(false);
-
- QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
-
- assertThat(queryBuilder.toString(), is(equalTo("SELECT * FROM /Example x")));
-
- verify(mockPersistentEntity, times(1)).getRegionName();
- verify(mockPartTree, times(1)).isDistinct();
- }
-
- @Test
- public void createQueryBuilderWithDistinct() {
- GemfirePersistentEntity> mockPersistentEntity = mock(GemfirePersistentEntity.class, "MockGemfirePersistentEntity");
- PartTree mockPartTree = mock(PartTree.class, "MockPartTree");
+ public void createQueryBuilderWithDistinctQuery() {
+ GemfirePersistentEntity> mockPersistentEntity = mock(GemfirePersistentEntity.class);
+ PartTree mockPartTree = mock(PartTree.class);
when(mockPersistentEntity.getRegionName()).thenReturn("Example");
when(mockPartTree.isDistinct()).thenReturn(true);
QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
- assertThat(queryBuilder.toString(), is(equalTo("SELECT DISTINCT * FROM /Example x")));
+ assertThat(queryBuilder.toString()).isEqualTo("SELECT DISTINCT * FROM /Example x");
+
+ verify(mockPersistentEntity, times(1)).getRegionName();
+ verify(mockPartTree, times(1)).isDistinct();
+ }
+
+ @Test
+ public void createQueryBuilderWithNonDistinctQuery() {
+ GemfirePersistentEntity> mockPersistentEntity = mock(GemfirePersistentEntity.class);
+ PartTree mockPartTree = mock(PartTree.class);
+
+ when(mockPersistentEntity.getRegionName()).thenReturn("Example");
+ when(mockPartTree.isDistinct()).thenReturn(false);
+
+ QueryBuilder queryBuilder = new QueryBuilder(mockPersistentEntity, mockPartTree);
+
+ assertThat(queryBuilder.toString()).isEqualTo("SELECT * FROM /Example x");
verify(mockPersistentEntity, times(1)).getRegionName();
verify(mockPartTree, times(1)).isDistinct();
@@ -83,28 +80,38 @@ public class QueryBuilderTest {
@Test
public void createQueryBuilderWithNullQueryString() {
- expectedException.expect(IllegalArgumentException.class);
- expectedException.expectCause(is(nullValue(Throwable.class)));
- expectedException.expectMessage(is(equalTo("The OQL Query must be specified")));
+ exception.expect(IllegalArgumentException.class);
+ exception.expectCause(is(nullValue(Throwable.class)));
+ exception.expectMessage(is(equalTo("An OQL Query must be specified")));
new QueryBuilder(null);
}
@Test
+ @SuppressWarnings("all")
public void createWithPredicate() {
- Predicate mockPredicate = mock(Predicate.class, "MockPredicate");
+ Predicate mockPredicate = mock(Predicate.class);
when(mockPredicate.toString(eq(QueryBuilder.DEFAULT_ALIAS))).thenReturn("x.id = 1");
- QueryBuilder queryBuilder = new QueryBuilder(String.format("SELECT * FROM /Example %s",
- QueryBuilder.DEFAULT_ALIAS));
+ QueryBuilder queryBuilder = new QueryBuilder(
+ String.format("SELECT * FROM /Example %s", QueryBuilder.DEFAULT_ALIAS));
QueryString queryString = queryBuilder.create(mockPredicate);
- assertThat(queryString, is(notNullValue()));
- assertThat(queryString.toString(), is(equalTo("SELECT * FROM /Example x WHERE x.id = 1")));
+ assertThat(queryString).isNotNull();
+ assertThat(queryString.toString()).isEqualTo("SELECT * FROM /Example x WHERE x.id = 1");
verify(mockPredicate, times(1)).toString(eq(QueryBuilder.DEFAULT_ALIAS));
}
+ @Test
+ public void createWithNullPredicate() {
+ QueryBuilder queryBuilder = new QueryBuilder("SELECT * FROM /Example");
+
+ QueryString queryString = queryBuilder.create(null);
+
+ assertThat(queryString).isNotNull();
+ assertThat(queryString.toString()).isEqualTo("SELECT * FROM /Example");
+ }
}
diff --git a/src/test/java/org/springframework/data/gemfire/repository/query/QueryStringUnitTests.java b/src/test/java/org/springframework/data/gemfire/repository/query/QueryStringUnitTests.java
index fd4962ac..59667177 100644
--- a/src/test/java/org/springframework/data/gemfire/repository/query/QueryStringUnitTests.java
+++ b/src/test/java/org/springframework/data/gemfire/repository/query/QueryStringUnitTests.java
@@ -16,19 +16,26 @@
package org.springframework.data.gemfire.repository.query;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.hamcrest.CoreMatchers.sameInstance;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Mockito.never;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.springframework.data.gemfire.repository.query.QueryString.HINT_PATTERN;
+import static org.springframework.data.gemfire.repository.query.QueryString.IMPORT_PATTERN;
+import static org.springframework.data.gemfire.repository.query.QueryString.LIMIT_PATTERN;
+import static org.springframework.data.gemfire.repository.query.QueryString.TRACE_PATTERN;
import java.util.Arrays;
-import java.util.List;
+import java.util.regex.Pattern;
+import com.gemstone.gemfire.cache.Region;
+
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
@@ -36,250 +43,299 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.gemfire.repository.sample.Person;
import org.springframework.data.gemfire.repository.sample.RootUser;
-import com.gemstone.gemfire.cache.Region;
-
/**
- *
+ * Test suite of test cases testing the contract and functionality of the {@link QueryString} class.
+ *
* @author Oliver Gierke
* @author John Blum
+ * @see org.junit.Test
+ * @see org.mockito.Mock
+ * @see org.springframework.data.gemfire.repository.query.QueryString
*/
@RunWith(MockitoJUnitRunner.class)
public class QueryStringUnitTests {
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
@Mock
@SuppressWarnings("rawtypes")
Region region;
- protected Sort.Order createOrder(final String property) {
- return createOrder(property, Sort.Direction.ASC);
+ protected Sort.Order newSortOrder(String property) {
+ return newSortOrder(property, Sort.Direction.ASC);
}
- protected Sort.Order createOrder(final String property, final Sort.Direction direction) {
+ protected Sort.Order newSortOrder(String property, Sort.Direction direction) {
return new Sort.Order(direction, property);
}
- protected Sort createSort(Sort.Order... orders) {
+ protected Sort newSort(Sort.Order... orders) {
return new Sort(orders);
}
@Test
- public void createQueryStringWithCount() {
- QueryString queryString = new QueryString(Person.class, true);
-
- assertThat(queryString, is(notNullValue()));
- assertThat(queryString.toString(), is(equalTo("SELECT count(*) FROM /Person")));
+ public void createQueryStringWithDomainType() {
+ assertThat(new QueryString(Person.class).toString()).isEqualTo("SELECT * FROM /Person");
}
@Test
- public void createQueryStringWithoutCount() {
- QueryString queryString = new QueryString(Person.class);
+ public void createQueryStringWithDomainTypeHavingCount() {
+ assertThat(new QueryString(Person.class, true).toString()).isEqualTo("SELECT count(*) FROM /Person");
+ }
- assertThat(queryString, is(notNullValue()));
- assertThat(queryString.toString(), is(equalTo("SELECT * FROM /Person")));
+ @Test
+ public void createQueryStringWithNullDomainType() {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectCause(is(nullValue(Throwable.class)));
+ exception.expectMessage(is(equalTo("domainType must not be null")));
+
+ new QueryString((Class>) null);
+ }
+
+ @Test
+ public void createQueryStringWithQuery() {
+ String query = "SELECT * FROM /Example";
+
+ assertThat(new QueryString(query).toString()).isEqualTo(query);
+ }
+
+ @Test
+ public void createQueryStringWithUnspecifiedQueryThrowsIllegalArgumentException() {
+ assertUnspecifiedQueryThrowsIllegalArgumentException("");
+ assertUnspecifiedQueryThrowsIllegalArgumentException(" ");
+ assertUnspecifiedQueryThrowsIllegalArgumentException(null);
+ }
+
+ protected void assertUnspecifiedQueryThrowsIllegalArgumentException(String query) {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectCause(is(nullValue(Throwable.class)));
+ exception.expectMessage(is(equalTo("An OQL Query must be specified")));
+
+ new QueryString(query);
}
@Test
public void hintPatternMatches() {
- assertThat(QueryString.HINT_PATTERN.matcher("").find(), is(true));
- assertThat(QueryString.HINT_PATTERN.matcher(" SELECT * FROM /Example WHERE id = $1").find(), is(true));
- assertThat(QueryString.HINT_PATTERN.matcher(" SELECT * FROM /Person WHERE lastName = $1 AND birthDate = $2").find(), is(true));
+ assertThat(matches(HINT_PATTERN, "")).isTrue();
+ assertThat(matches(HINT_PATTERN, " SELECT * FROM /Example WHERE id = $1")).isTrue();
+ assertThat(matches(HINT_PATTERN, " SELECT * FROM /Person WHERE lastName = $1 AND birthDate = $2")).isTrue();
}
@Test
public void hintPatternNoMatches() {
- assertThat(QueryString.HINT_PATTERN.matcher("HINT").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("SELECT * FROM /Example").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("SELECT * FROM /Hint").find(), is(false));
- assertThat(QueryString.HINT_PATTERN.matcher("SELECT x.hint FROM /Clues x WHERE x.hint > $1").find(), is(false));
+ assertThat(matches(HINT_PATTERN, "HINT")).isFalse();
+ assertThat(matches(HINT_PATTERN, "")).isFalse();
+ assertThat(matches(HINT_PATTERN, "")).isFalse();
+ assertThat(matches(HINT_PATTERN, "")).isFalse();
+ assertThat(matches(HINT_PATTERN, "")).isFalse();
+ assertThat(matches(HINT_PATTERN, "")).isFalse();
+ assertThat(matches(HINT_PATTERN, "SELECT * FROM /Example")).isFalse();
+ assertThat(matches(HINT_PATTERN, "SELECT * FROM /Hint")).isFalse();
+ assertThat(matches(HINT_PATTERN, "SELECT x.hint FROM /Clues x WHERE x.hint > $1")).isFalse();
}
@Test
public void importPatternMatches() {
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT *;").find(), is(true));
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.*;").find(), is(true));
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.Type;").find(), is(true));
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT org.example.app.DomainType; SELECT * FROM /Domain").find(), is(true));
+ assertThat(matches(IMPORT_PATTERN, "IMPORT *;")).isTrue();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.*;")).isTrue();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.Type;")).isTrue();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT org.example.app.domain.DomainType; SELECT * FROM /DomainType")).isTrue();
}
@Test
public void importPatternNoMatches() {
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT").find(), is(false));
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT ;").find(), is(false));
- assertThat(QueryString.IMPORT_PATTERN.matcher("IMPORT *").find(), is(false));
- assertThat(QueryString.IMPORT_PATTERN.matcher("SELECT * FROM /Example").find(), is(false));
+ assertThat(matches(IMPORT_PATTERN, "IMPORT")).isFalse();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT ;")).isFalse();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT *")).isFalse();
+ assertThat(matches(IMPORT_PATTERN, "IMPORT *:")).isFalse();
+ assertThat(matches(IMPORT_PATTERN, "SELECT * FROM /Example")).isFalse();
}
@Test
public void limitPatternMatches() {
- assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT 10").find(), is(true));
- assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example LIMIT 10").find(), is(true));
- assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example WHERE id = $1 LIMIT 10").find(), is(true));
+ assertThat(matches(LIMIT_PATTERN, "LIMIT 0")).isTrue();
+ assertThat(matches(LIMIT_PATTERN, "LIMIT 1")).isTrue();
+ assertThat(matches(LIMIT_PATTERN, "LIMIT 10")).isTrue();
+ assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example LIMIT 10")).isTrue();
+ assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example WHERE id = $1 LIMIT 10")).isTrue();
}
@Test
public void limitPatternNoMatches() {
- assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT").find(), is(false));
- assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT lO").find(), is(false));
- assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT FF").find(), is(false));
- assertThat(QueryString.LIMIT_PATTERN.matcher("LIMIT ten").find(), is(false));
- assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example LIMIT").find(), is(false));
- assertThat(QueryString.LIMIT_PATTERN.matcher("SELECT * FROM /Example WHERE id = $1 LIM 10").find(), is(false));
+ assertThat(matches(LIMIT_PATTERN, "LIMIT")).isFalse();
+ assertThat(matches(LIMIT_PATTERN, "LIMIT lO")).isFalse();
+ assertThat(matches(LIMIT_PATTERN, "LIMIT AF")).isFalse();
+ assertThat(matches(LIMIT_PATTERN, "LIMIT ten")).isFalse();
+ assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example LIMIT")).isFalse();
+ assertThat(matches(LIMIT_PATTERN, "SELECT * FROM /Example WHERE id = $1 LIM 10")).isFalse();
}
@Test
public void tracePatternMatches() {
- assertThat(QueryString.TRACE_PATTERN.matcher("").find(), is(true));
- assertThat(QueryString.TRACE_PATTERN.matcher(" SELECT * FROM /Example").find(), is(true));
- assertThat(QueryString.TRACE_PATTERN.matcher("SELECT * FROM /Example").find(), is(true));
- assertThat(QueryString.TRACE_PATTERN.matcher("SELECT * FROM /Example").find(), is(true));
+ assertThat(matches(TRACE_PATTERN, "")).isTrue();
+ assertThat(matches(TRACE_PATTERN, " SELECT * FROM /Example")).isTrue();
+ assertThat(matches(TRACE_PATTERN, "SELECT * FROM /Example")).isTrue();
+ assertThat(matches(TRACE_PATTERN, "SELECT * FROM /Example")).isTrue();
+ }
+
+ @Test
+ public void tracePatternNoMatches() {
+ assertThat(matches(TRACE_PATTERN, "TRACE")).isFalse();
+ assertThat(matches(TRACE_PATTERN, "TRACE SELECT * FROM /Example")).isFalse();
+ assertThat(matches(TRACE_PATTERN, "")).isFalse();
+ }
+
+ protected boolean matches(Pattern pattern, String value) {
+ return pattern.matcher(value).find();
}
// SGF-251
@Test
- public void replacesDomainObjectWithRegionPathCorrectly() {
- QueryString query = new QueryString("SELECT * FROM /Person p WHERE p.firstname = $1");
+ public void replacesDomainTypeSimpleNameWithRegionPathCorrectly() {
+ QueryString query = new QueryString(Person.class);
when(region.getFullPath()).thenReturn("/foo/bar");
- assertThat(query.forRegion(Person.class, region).toString(), is("SELECT * FROM /foo/bar p WHERE p.firstname = $1"));
+ assertThat(query.forRegion(Person.class, region).toString()).isEqualTo("SELECT * FROM /foo/bar");
- verify(region, never()).getName();
+ verify(region, times(1)).getFullPath();
}
-
- // SGF-156
- // SGF-251
+
+ // SGF-156, SGF-251
@Test
- public void replacesDomainObjectWithPluralRegionPathCorrectly() {
- QueryString query = new QueryString("SELECT * FROM /Persons p WHERE p.firstname = $1");
+ public void replacesFromClauseWithRegionPathCorrectly() {
+ QueryString query = new QueryString("SELECT * FROM /Persons p WHERE p.lastname = $1");
when(region.getFullPath()).thenReturn("/People");
- assertThat(query.forRegion(Person.class, region).toString(),
- is("SELECT * FROM /People p WHERE p.firstname = $1"));
+ assertThat(query.forRegion(Person.class, region).toString())
+ .isEqualTo("SELECT * FROM /People p WHERE p.lastname = $1");
- verify(region, never()).getName();
+ verify(region, times(1)).getFullPath();
}
// SGF-252
@Test
- public void replacesFullyQualifiedSubRegionReferenceWithRegionPathCorrectly() {
+ public void replacesFullyQualifiedSubRegionPathWithRegionPathCorrectly() {
QueryString query = new QueryString("SELECT * FROM //Local/Root/Users u WHERE u.username = $1");
- when(region.getFullPath()).thenReturn("/Local/Root/Users");
+ when(region.getFullPath()).thenReturn("/Remote/Root/Users");
- assertThat(query.forRegion(RootUser.class, region).toString(), is(equalTo(
- "SELECT * FROM /Local/Root/Users u WHERE u.username = $1")));
+ assertThat(query.forRegion(RootUser.class, region).toString())
+ .isEqualTo("SELECT * FROM /Remote/Root/Users u WHERE u.username = $1");
- verify(region, never()).getName();
+ verify(region, times(1)).getFullPath();
}
@Test
public void bindsInValuesCorrectly() {
- QueryString query = new QueryString("SELECT * FROM /Person p WHERE p.firstname IN SET $1");
- List values = Arrays.asList(1, 2, 3);
- assertThat(query.bindIn(values).toString(), is("SELECT * FROM /Person p WHERE p.firstname IN SET ('1', '2', '3')"));
+ QueryString query = new QueryString("SELECT * FROM /Collection WHERE elements IN SET $1");
+
+ assertThat(query.bindIn(Arrays.asList(1, 2, 3)).toString())
+ .isEqualTo("SELECT * FROM /Collection WHERE elements IN SET ('1', '2', '3')");
}
@Test
public void detectsInParameterIndexesCorrectly() {
- QueryString query = new QueryString("IN SET $1 OR IN SET $2");
- Iterable indexes = query.getInParameterIndexes();
- assertThat(indexes, is((Iterable) Arrays.asList(1, 2)));
+ QueryString query = new QueryString("SELECT * FROM /Example WHERE values IN SET $1 OR IN SET $2");
+
+ assertThat(query.getInParameterIndexes()).isEqualTo(Arrays.asList(1, 2));
}
@Test
public void addsNoOrderByClauseCorrectly() {
QueryString query = new QueryString("SELECT * FROM /People p").orderBy(null);
- assertThat(query.toString(), is(equalTo("SELECT * FROM /People p")));
+ assertThat(query.toString()).isEqualTo("SELECT * FROM /People p");
}
@Test
public void addsOrderByClauseCorrectly() {
QueryString query = new QueryString("SELECT * FROM /People p WHERE p.lastName = $1")
- .orderBy(createSort(createOrder("lastName", Sort.Direction.DESC), createOrder("firstName")));
+ .orderBy(newSort(newSortOrder("lastName", Sort.Direction.DESC), newSortOrder("firstName")));
- assertThat(query.toString(), is(equalTo(
- "SELECT * FROM /People p WHERE p.lastName = $1 ORDER BY lastName DESC, firstName ASC")));
+ assertThat(query.toString())
+ .isEqualTo("SELECT DISTINCT * FROM /People p WHERE p.lastName = $1 ORDER BY lastName DESC, firstName ASC");
}
@Test
public void addsSingleOrderByClauseCorrectly() {
QueryString query = new QueryString("SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1")
- .orderBy(createSort(createOrder("lastName")));
+ .orderBy(newSort(newSortOrder("lastName")));
- assertThat(query.toString(), is(equalTo(
- "SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1 ORDER BY lastName ASC")));
+ assertThat(query.toString())
+ .isEqualTo("SELECT DISTINCT p.lastName FROM /People p WHERE p.firstName = $1 ORDER BY lastName ASC");
}
@Test
public void withHints() {
- assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").toString(),
- is(equalTo(" SELECT * FROM /Example")));
- assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx", "SpatialIdx", "TxDateIdx").toString(),
- is(equalTo(" SELECT * FROM /Example")));
+ assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").toString())
+ .isEqualTo(" SELECT * FROM /Example");
+
+ assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx", "SpatialIdx", "TxDateIdx").toString())
+ .isEqualTo(" SELECT * FROM /Example");
}
@Test
public void withoutHints() {
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
- assertThat(expectedQueryString.withHints((String[]) null), is(sameInstance(expectedQueryString)));
- assertThat(expectedQueryString.withHints(), is(sameInstance(expectedQueryString)));
+ assertThat(expectedQueryString.withHints()).isSameAs(expectedQueryString);
+ assertThat(expectedQueryString.withHints((String[]) null)).isSameAs(expectedQueryString);
}
@Test
public void withImport() {
- assertThat(new QueryString("SELECT * FROM /People").withImport("org.example.app.domain.Person").toString(),
- is(equalTo("IMPORT org.example.app.domain.Person; SELECT * FROM /People")));
+ assertThat(new QueryString("SELECT * FROM /People").withImport("org.example.app.domain.Person").toString())
+ .isEqualTo("IMPORT org.example.app.domain.Person; SELECT * FROM /People");
}
@Test
public void withoutImport() {
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
- assertThat(expectedQueryString.withImport(null), is(sameInstance(expectedQueryString)));
- assertThat(expectedQueryString.withImport(""), is(sameInstance(expectedQueryString)));
- assertThat(expectedQueryString.withImport(" "), is(sameInstance(expectedQueryString)));
+ assertThat(expectedQueryString.withImport(null)).isSameAs(expectedQueryString);
+ assertThat(expectedQueryString.withImport("")).isSameAs(expectedQueryString);
+ assertThat(expectedQueryString.withImport(" ")).isSameAs(expectedQueryString);
}
@Test
public void withLimit() {
- assertThat(new QueryString("SELECT * FROM /Example").withLimit(10).toString(),
- is(equalTo("SELECT * FROM /Example LIMIT 10")));
- assertThat(new QueryString("SELECT * FROM /Example").withLimit(-5).toString(),
- is(equalTo("SELECT * FROM /Example LIMIT -5")));
- assertThat(new QueryString("SELECT * FROM /Example").withLimit(0).toString(),
- is(equalTo("SELECT * FROM /Example LIMIT 0")));
+ assertThat(new QueryString("SELECT * FROM /Example").withLimit(10).toString())
+ .isEqualTo("SELECT * FROM /Example LIMIT 10");
+
+ assertThat(new QueryString("SELECT * FROM /Example").withLimit(0).toString())
+ .isEqualTo("SELECT * FROM /Example LIMIT 0");
+
+ assertThat(new QueryString("SELECT * FROM /Example").withLimit(-5).toString())
+ .isEqualTo("SELECT * FROM /Example LIMIT -5");
}
@Test
public void withoutLimit() {
QueryString expectedQueryString = new QueryString("SELECT * FROM /Example");
- assertThat(expectedQueryString.withLimit(null), is(sameInstance(expectedQueryString)));
+
+ assertThat(expectedQueryString.withLimit(null)).isSameAs(expectedQueryString);
}
@Test
public void withTrace() {
- assertThat(new QueryString("SELECT * FROM /Example").withTrace().toString(),
- is(equalTo(" SELECT * FROM /Example")));
+ assertThat(new QueryString("SELECT * FROM /Example").withTrace().toString())
+ .isEqualTo(" SELECT * FROM /Example");
}
@Test
public void withHintAndTrace() {
- assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").withTrace().toString(),
- is(equalTo(" SELECT * FROM /Example")));
+ assertThat(new QueryString("SELECT * FROM /Example").withHints("IdIdx").withTrace().toString())
+ .isEqualTo(" SELECT * FROM /Example");
}
@Test
public void withHintImportLimitAndTrace() {
- assertThat(new QueryString("SELECT * FROM /Example").withImport("org.example.domain.Type")
- .withHints("IdIdx", "NameIdx").withLimit(20).withTrace().toString(),
- is(equalTo(" IMPORT org.example.domain.Type; SELECT * FROM /Example LIMIT 20")));
- }
+ QueryString query = new QueryString("SELECT * FROM /Example");
+ assertThat(query.withImport("org.example.domain.Type").withHints("IdIdx", "NameIdx").withLimit(20).withTrace().toString())
+ .isEqualTo(" IMPORT org.example.domain.Type; SELECT * FROM /Example LIMIT 20");
+ }
}
diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepository.java b/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepository.java
index a4c28395..c283817c 100644
--- a/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepository.java
+++ b/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepository.java
@@ -52,11 +52,14 @@ public interface PersonRepository extends GemfireRepository {
Collection findByFirstnameAndLastname(String firstName, String lastName);
- @Trace
Collection findByFirstnameIgnoreCaseAndLastnameIgnoreCase(String firstName, String lastName);
+ Collection findByFirstnameAndLastnameAllIgnoringCase(String firstName, String lastName);
+
Collection findByFirstnameOrLastname(String firstName, String lastName);
+ Collection findDistinctByFirstnameOrLastname(String firstName, String lastName, Sort order);
+
Person findByLastname(String lastName);
Collection findByLastnameEndingWith(String lastName);
diff --git a/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryTest.java b/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryIntegrationTests.java
similarity index 63%
rename from src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryTest.java
rename to src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryIntegrationTests.java
index 88f0e8f2..e802a195 100644
--- a/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryTest.java
+++ b/src/test/java/org/springframework/data/gemfire/repository/sample/PersonRepositoryIntegrationTests.java
@@ -16,14 +16,12 @@
package org.springframework.data.gemfire.repository.sample;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicLong;
@@ -48,7 +46,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
- * The PersonRepositoryTest class...
+ * The PersonRepositoryIntegrationTests class...
*
* @author John Blum
* @see org.junit.Test
@@ -60,18 +58,20 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* @since 1.4.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = PersonRepositoryTest.GemFireConfiguration.class)
+@ContextConfiguration(classes = PersonRepositoryIntegrationTests.GemFireConfiguration.class)
@SuppressWarnings("unused")
-public class PersonRepositoryTest {
+public class PersonRepositoryIntegrationTests {
- private static final String GEMFIRE_LOG_LEVEL = System.getProperty("gemfire.log-level", "warning");
+ private static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
+ private static final String GEMFIRE_LOG_LEVEL = System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
- protected final AtomicLong ID_SEQUENCE = new AtomicLong(0l);
+ protected final AtomicLong ID_SEQUENCE = new AtomicLong(0L);
private Person cookieDoe = newPerson("Cookie", "Doe");
private Person janeDoe = newPerson("Jane", "Doe");
private Person jonDoe = newPerson("Jon", "Doe");
private Person pieDoe = newPerson("Pie", "Doe");
+ private Person sourDoe = newPerson("Sour", "Doe");
private Person jackHandy = newPerson("Jack", "Handy");
private Person sandyHandy = newPerson("Sandy", "Handy");
private Person imaPigg = newPerson("Ima", "Pigg");
@@ -82,6 +82,7 @@ public class PersonRepositoryTest {
@Before
public void setup() {
if (personRepository.count() == 0) {
+ sourDoe = personRepository.save(sourDoe);
sandyHandy = personRepository.save(sandyHandy);
jonDoe = personRepository.save(jonDoe);
jackHandy = personRepository.save(jackHandy);
@@ -91,18 +92,28 @@ public class PersonRepositoryTest {
cookieDoe = personRepository.save(cookieDoe);
}
- assertThat(personRepository.count(), is(equalTo(7L)));
+ assertThat(personRepository.count()).isEqualTo(8L);
+ }
+
+ protected List asList(Iterable iterable) {
+ List list = new ArrayList();
+
+ for (T element : iterable) {
+ list.add(element);
+ }
+
+ return list;
}
protected Person newPerson(String firstName, String lastName) {
return new Person(ID_SEQUENCE.incrementAndGet(), firstName, lastName);
}
- protected Sort.Order newOrder(String property) {
- return newOrder(property, Sort.Direction.ASC);
+ protected Sort.Order newSortOrder(String property) {
+ return newSortOrder(property, Sort.Direction.ASC);
}
- protected Sort.Order newOrder(String property, Sort.Direction direction) {
+ protected Sort.Order newSortOrder(String property, Sort.Direction direction) {
return new Sort.Order(direction, property);
}
@@ -111,33 +122,71 @@ public class PersonRepositoryTest {
}
@Test
- public void findDistinctPeopleOrderedByFirstnameDescending() {
- List actualPeople = personRepository.findDistinctPeopleByOrderByLastnameDesc(
- newSort(newOrder("firstname")));
+ public void findAllPeopleSorted() {
+ Iterable people = personRepository.findAll(newSort(newSortOrder("firstname")));
- assertThat(actualPeople, is(notNullValue(List.class)));
- assertThat(actualPeople.size(), is(equalTo(7)));
- assertThat(actualPeople, is(equalTo(Arrays.asList(
- imaPigg, jackHandy, sandyHandy, cookieDoe, janeDoe, jonDoe, pieDoe))));
+ assertThat(people).isNotNull();
+
+ List peopleList = asList(people);
+
+ assertThat(peopleList.size()).isEqualTo(8);
+ assertThat(peopleList).isEqualTo(
+ Arrays.asList(cookieDoe, imaPigg, jackHandy, janeDoe, jonDoe, pieDoe, sandyHandy, sourDoe));
}
@Test
- public void findDistinctPersonWithUnordered() {
+ public void findDistinctPeopleOrderedByLastnameDescendingFirstnameAscending() {
+ List actualPeople = personRepository.findDistinctPeopleByOrderByLastnameDesc(
+ newSort(newSortOrder("firstname")));
+
+ assertThat(actualPeople).isNotNull();
+ assertThat(actualPeople.size()).isEqualTo(8);
+ assertThat(actualPeople).isEqualTo(Arrays.asList(
+ imaPigg, jackHandy, sandyHandy, cookieDoe, janeDoe, jonDoe, pieDoe, sourDoe));
+ }
+
+ @Test
+ public void findDistinctPeopleByLastnameUnordered() {
List actualPeople = personRepository.findDistinctByLastname("Handy", null);
- assertThat(actualPeople, is(notNullValue(List.class)));
- assertThat(actualPeople.size(), is(equalTo(2)));
- assertThat(String.format("Expected '%1$s'; but was '%2$s'", Arrays.asList(jackHandy, sandyHandy), actualPeople),
- actualPeople, contains(jackHandy, sandyHandy));
+ assertThat(actualPeople).isNotNull();
+ assertThat(actualPeople.size()).isEqualTo(2);
+ assertThat(actualPeople).containsAll(Arrays.asList(jackHandy, sandyHandy));
+ }
+
+ @Test
+ public void findDistinctPeopleByFirstOrLastNameWithSort() {
+ Collection people = personRepository.findDistinctByFirstnameOrLastname("Cookie", "Pigg",
+ newSort(newSortOrder("lastname", Sort.Direction.DESC), newSortOrder("firstname", Sort.Direction.ASC)));
+
+ assertThat(people).isNotNull();
+ assertThat(people.size()).isEqualTo(2);
+
+ Iterator peopleIterator = people.iterator();
+
+ assertThat(peopleIterator.hasNext()).isTrue();
+ assertThat(peopleIterator.next()).isEqualTo(imaPigg);
+ assertThat(peopleIterator.hasNext()).isTrue();
+ assertThat(peopleIterator.next()).isEqualTo(cookieDoe);
+ assertThat(peopleIterator.hasNext()).isFalse();
}
@Test
public void findPersonByFirstAndLastNameIgnoringCase() {
Collection people = personRepository.findByFirstnameIgnoreCaseAndLastnameIgnoreCase("jON", "doE");
- assertThat(people, is(notNullValue(Collection.class)));
- assertThat(people.size(), is(equalTo(1)));
- assertThat(people.iterator().next(), is(equalTo(jonDoe)));
+ assertThat(people).isNotNull();
+ assertThat(people.size()).isEqualTo(1);
+ assertThat(people.iterator().next()).isEqualTo(jonDoe);
+ }
+
+ @Test
+ public void findByFirstAndLastNameAllIgnoringCase() {
+ Collection people = personRepository.findByFirstnameAndLastnameAllIgnoringCase("IMa", "PIGg");
+
+ assertThat(people).isNotNull();
+ assertThat(people.size()).isEqualTo(1);
+ assertThat(people.iterator().next()).isEqualTo(imaPigg);
}
@Configuration
@@ -146,24 +195,25 @@ public class PersonRepositoryTest {
value = org.springframework.data.gemfire.repository.sample.PersonRepository.class))
public static class GemFireConfiguration {
- String applicationName() {
- return PersonRepositoryTest.class.getSimpleName();
- }
-
- String logLevel() {
- return GEMFIRE_LOG_LEVEL;
- }
-
Properties gemfireProperties() {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
gemfireProperties.setProperty("mcast-port", "0");
+ gemfireProperties.setProperty("locators", "");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
+ String applicationName() {
+ return PersonRepositoryIntegrationTests.class.getSimpleName();
+ }
+
+ String logLevel() {
+ return GEMFIRE_LOG_LEVEL;
+ }
+
@Bean
CacheFactoryBean gemfireCache() {
CacheFactoryBean gemfireCache = new CacheFactoryBean();