SGF-402 - Add Lucene Integration support.
(cherry picked from commit f104d5752725469837254e7dda773539505a26c4) Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
@@ -97,8 +97,8 @@ dependencies {
|
||||
// GemFire
|
||||
compile("io.pivotal.gemfire:geode-core:$gemfireVersion")
|
||||
compile("io.pivotal.gemfire:geode-cq:$gemfireVersion")
|
||||
compile("io.pivotal.gemfire:geode-lucene:$gemfireVersion")
|
||||
compile("io.pivotal.gemfire:geode-wan:$gemfireVersion")
|
||||
optional("com.google.code.findbugs:annotations:$googleCodeFindbugsVersion")
|
||||
optional("org.apache.shiro:shiro-spring:$shiroVersion")
|
||||
runtime("antlr:antlr:$antlrVersion")
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
antlrVersion=2.7.7
|
||||
aspectjVersion=1.8.9
|
||||
assertjVersion=3.5.2
|
||||
assertjVersion=3.6.2
|
||||
cdiVersion=1.0
|
||||
gemfireVersion=9.0.2
|
||||
googleCodeFindbugsVersion=2.0.2
|
||||
hamcrestVersion=1.3
|
||||
jacksonVersion=2.8.6
|
||||
junitVersion=4.12
|
||||
|
||||
10
pom.xml
10
pom.xml
@@ -18,6 +18,7 @@
|
||||
<properties>
|
||||
<antlr.version>2.7.7</antlr.version>
|
||||
<apache-shiro.version>1.3.2</apache-shiro.version>
|
||||
<assertj.version>3.6.2</assertj.version>
|
||||
<gemfire.version>9.0.2</gemfire.version>
|
||||
<google-code-findbugs.version>2.0.2</google-code-findbugs.version>
|
||||
<multithreadedtc.version>1.01</multithreadedtc.version>
|
||||
@@ -79,7 +80,16 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<<<<<<< HEAD
|
||||
<groupId>io.pivotal.gemfire</groupId>
|
||||
=======
|
||||
<groupId>org.apache.geode</groupId>
|
||||
<artifactId>geode-lucene</artifactId>
|
||||
<version>${gemfire.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geode</groupId>
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
<artifactId>geode-wan</artifactId>
|
||||
<version>${gemfire.version}</version>
|
||||
</dependency>
|
||||
|
||||
@@ -48,12 +48,12 @@ public interface GemfireOperations {
|
||||
|
||||
<K, V> V putIfAbsent(K key, V value);
|
||||
|
||||
<K, V> V remove(K key);
|
||||
|
||||
<K, V> V replace(K key, V value);
|
||||
|
||||
<K, V> boolean replace(K key, V oldValue, V newValue);
|
||||
|
||||
<K, V> V remove(K key);
|
||||
|
||||
/**
|
||||
* Executes a GemFire query with the given (optional) parameters and returns the result. Note this method expects the query to return multiple results; for queries that return only one
|
||||
* element use {@link #findUnique(String, Object...)}.
|
||||
|
||||
@@ -78,6 +78,10 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
private String indexName;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cache, "The GemFire Cache reference must not be null!");
|
||||
|
||||
@@ -251,15 +255,27 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Index getObject() {
|
||||
index = (index != null ? index : getExistingIndex(queryService, indexName));
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return (index != null ? index.getClass() : Index.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
@@ -381,7 +397,7 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
|
||||
private final String indexName;
|
||||
|
||||
protected IndexWrapper(final QueryService queryService, final String indexName) {
|
||||
protected IndexWrapper(QueryService queryService, String indexName) {
|
||||
Assert.notNull(queryService, "QueryService must not be null");
|
||||
Assert.hasText(indexName, "The name of the Index must be specified!");
|
||||
this.queryService = queryService;
|
||||
@@ -470,7 +486,7 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
@@ -499,5 +515,4 @@ public class IndexFactoryBean implements InitializingBean, FactoryBean<Index>, B
|
||||
return (index != null ? String.valueOf(index) : getIndexName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.SpringUtils.safeGetValue;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneQuery;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryException;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryFactory;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.geode.cache.lucene.LuceneServiceProvider;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.gemfire.search.lucene.support.LuceneOperationsSupport;
|
||||
import org.springframework.data.gemfire.util.CacheUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link LuceneAccessor} is an abstract class supporting implementations of the {@link LuceneOperations} interface
|
||||
* encapsulating common functionality necessary to execute Lucene queries.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.springframework.data.gemfire.search.lucene.support.LuceneOperationsSupport
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.lucene.LuceneQuery
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.lucene.LuceneServiceProvider
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class LuceneAccessor extends LuceneOperationsSupport implements InitializingBean {
|
||||
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
private LuceneIndex luceneIndex;
|
||||
|
||||
private LuceneService luceneService;
|
||||
|
||||
private Region<?, ?> region;
|
||||
|
||||
private String indexName;
|
||||
private String regionPath;
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of {@link LuceneAccessor}.
|
||||
*/
|
||||
public LuceneAccessor() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of the {@link LuceneAccessor} initialized with the given {@link LuceneIndex}
|
||||
* used to perform Lucene queries (searches).
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} used in Lucene queries.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
*/
|
||||
public LuceneAccessor(LuceneIndex luceneIndex) {
|
||||
this.luceneIndex = luceneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of the {@link LuceneAccessor} initialized with the given Lucene index name
|
||||
* and {@link Region} reference upon which Lucene queries are executed.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex} used in Lucene queries.
|
||||
* @param region {@link Region} on which Lucene queries are executed.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public LuceneAccessor(String indexName, Region<?, ?> region) {
|
||||
this.indexName = indexName;
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of the {@link LuceneAccessor} initialized with the given Lucene index name
|
||||
* and {@link Region} reference upon which Lucene queries are executed.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex} used in Lucene queries.
|
||||
* @param regionPath {@link String} containing the name of the {@link Region} on which Lucene queries are executed.
|
||||
*/
|
||||
public LuceneAccessor(String indexName, String regionPath) {
|
||||
this.indexName = indexName;
|
||||
this.regionPath = regionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.gemfireCache = resolveCache();
|
||||
this.luceneService = resolveLuceneService();
|
||||
this.indexName = resolveIndexName();
|
||||
this.regionPath = resolveRegionPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
*
|
||||
* @return an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see #getLuceneService()
|
||||
*/
|
||||
public LuceneQueryFactory createLuceneQueryFactory() {
|
||||
return resolveLuceneService().createLuceneQueryFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
*
|
||||
* @param projectionFields {@link String[]} containing the fields of the object to project.
|
||||
* @return an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see #createLuceneQueryFactory(int, int, String...)
|
||||
*/
|
||||
public LuceneQueryFactory createLuceneQueryFactory(String... projectionFields) {
|
||||
return createLuceneQueryFactory(DEFAULT_RESULT_LIMIT, DEFAULT_PAGE_SIZE, projectionFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
*
|
||||
* @param resultLimit limit to the number of results returned by the query.
|
||||
* @param projectionFields {@link String[]} containing the fields of the object to project.
|
||||
* @return an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see #createLuceneQueryFactory(int, int, String...)
|
||||
*/
|
||||
public LuceneQueryFactory createLuceneQueryFactory(int resultLimit, String... projectionFields) {
|
||||
return createLuceneQueryFactory(resultLimit, DEFAULT_PAGE_SIZE, projectionFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
*
|
||||
* @param resultLimit limit to the number of results returned by the query.
|
||||
* @param pageSize number of results appearing on a single page.
|
||||
* @param projectionFields {@link String[]} containing the fields of the object to project.
|
||||
* @return an instance of the {@link LuceneQueryFactory} to create and execute {@link LuceneQuery Lucene queries}.
|
||||
* @see #createLuceneQueryFactory()
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public LuceneQueryFactory createLuceneQueryFactory(int resultLimit, int pageSize, String... projectionFields) {
|
||||
return createLuceneQueryFactory().setResultLimit(resultLimit).setPageSize(pageSize)
|
||||
.setProjectionFields(nullSafeArray(projectionFields, String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @return a reference to the single instance of the {@link GemFireCache}.
|
||||
* @see org.springframework.data.gemfire.util.CacheUtils#resolveGemFireCache()
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #getCache()
|
||||
*/
|
||||
protected GemFireCache resolveCache() {
|
||||
return Optional.ofNullable(getCache()).orElseGet(CacheUtils::resolveGemFireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link LuceneService} used by this data access object to perform Lucene queries.
|
||||
*
|
||||
* @return a reference to the {@link GemFireCache} {@link LuceneService}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see #getLuceneService()
|
||||
* @see #resolveCache()
|
||||
* @see #resolveLuceneService(GemFireCache)
|
||||
*/
|
||||
protected LuceneService resolveLuceneService() {
|
||||
return Optional.ofNullable(getLuceneService()).orElseGet(() -> resolveLuceneService(resolveCache()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link LuceneService} used by this data access object to perform Lucene queries.
|
||||
*
|
||||
* @param gemfireCache {@link GemFireCache} used to resolve the {@link LuceneService}.
|
||||
* @return a reference to the {@link GemFireCache} {@link LuceneService}.
|
||||
* @throws IllegalArgumentException if {@link GemFireCache} is {@literal null}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
protected LuceneService resolveLuceneService(GemFireCache gemfireCache) {
|
||||
Assert.notNull(gemfireCache, "Cache reference was not properly configured");
|
||||
return LuceneServiceProvider.get(gemfireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the name of the {@link LuceneIndex} required in the Lucene data access, query operations
|
||||
* when a {@link LuceneIndex} is not specifically provided.
|
||||
*
|
||||
* @return the name of the resolve {@link LuceneIndex}.
|
||||
* @throws IllegalStateException if the name of the {@link LuceneIndex} cannot be resolved.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex#getName()
|
||||
* @see #getIndexName()
|
||||
* @see #getLuceneIndex()
|
||||
*/
|
||||
protected String resolveIndexName() {
|
||||
String resolvedIndexName = Optional.ofNullable(getIndexName())
|
||||
.orElseGet(() -> safeGetValue(() -> getLuceneIndex().getName()));
|
||||
|
||||
Assert.state(StringUtils.hasText(resolvedIndexName),
|
||||
"The name of the Lucene Index could not be resolved");
|
||||
|
||||
return resolvedIndexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the fully-qualified pathname of the {@link Region} to which the Lucene data access, query operations
|
||||
* are performed and the {@link LuceneIndex} is applied, when a {@link String region path}
|
||||
* is not specifically provided.
|
||||
*
|
||||
* @return a {@link String} containing the fully-qualified pathname of the {@link Region} on which the Lucene
|
||||
* data access, query operations are performed and the {@link LuceneIndex} is applied.
|
||||
* @throws IllegalStateException if the fully-qualified pathname of the {@link Region} cannot be resolved.
|
||||
* @see #getRegionPath()
|
||||
* @see #getRegion()
|
||||
*/
|
||||
protected String resolveRegionPath() {
|
||||
String resolvedRegionPath = Optional.ofNullable(getRegionPath())
|
||||
.orElseGet(() -> safeGetValue(() -> getRegion().getFullPath()));
|
||||
|
||||
Assert.state(StringUtils.hasText(resolvedRegionPath), "Region path could not be resolved");
|
||||
|
||||
return resolvedRegionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param gemfireCache {@link GemFireCache} reference.
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setCache(GemFireCache gemfireCache) {
|
||||
this.gemfireCache = gemfireCache;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @return a reference to the {@link GemFireCache}.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #resolveCache()
|
||||
*/
|
||||
protected GemFireCache getCache() {
|
||||
return this.gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the {@link LuceneIndex} used in Lucene queries.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see #setLuceneIndex(LuceneIndex)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the {@link LuceneIndex} used in Lucene queries.
|
||||
*
|
||||
* @return a {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @see #resolveIndexName()
|
||||
* @see #getLuceneIndex()
|
||||
*/
|
||||
public String getIndexName() {
|
||||
return this.indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link LuceneIndex} used in Lucene queries.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param luceneIndex {@link LuceneIndex} used in Lucene data access, query operations.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see #setIndexName(String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setLuceneIndex(LuceneIndex luceneIndex) {
|
||||
this.luceneIndex = luceneIndex;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link LuceneIndex} used in Lucene queries.
|
||||
*
|
||||
* @return a {@link LuceneIndex} used in Lucene data access, query operations.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see #resolveIndexName()
|
||||
* @see #getIndexName()
|
||||
*/
|
||||
public LuceneIndex getLuceneIndex() {
|
||||
return this.luceneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link LuceneService} used to perform Lucene query data access operations.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param luceneService {@link LuceneService} used to perform Lucene queries.
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setLuceneService(LuceneService luceneService) {
|
||||
this.luceneService = luceneService;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link LuceneService} used to perform Lucene query data access operations.
|
||||
*
|
||||
* @return a reference to the {@link LuceneService} used to perform Lucene queries.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
*/
|
||||
protected LuceneService getLuceneService() {
|
||||
return this.luceneService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link Region} used to specify Lucene queries.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param region {@link Region} used to specify Lucene queries.
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #setRegionPath(String)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setRegion(Region<?, ?> region) {
|
||||
this.region = region;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link Region} used to specify Lucene queries.
|
||||
*
|
||||
* @return a {@link Region} used to specify Lucene queries.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #resolveRegionPath()
|
||||
* @see #getRegionPath()
|
||||
*/
|
||||
public Region<?, ?> getRegion() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a fully-qualified pathname to the {@link Region} used to specify Lucene queries.
|
||||
*
|
||||
* @param <T> {@link Class} type of the {@link LuceneAccessor}.
|
||||
* @param regionPath {@link String} containing the fully-qualified pathname to the {@link Region}
|
||||
* used to specify Lucene queries.
|
||||
* @return this {@link LuceneAccessor}.
|
||||
* @see #setRegion(Region)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends LuceneAccessor> T setRegionPath(String regionPath) {
|
||||
this.regionPath = regionPath;
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fully-qualified pathname to the {@link Region} used to specify Lucene queries.
|
||||
*
|
||||
* @return a {@link String} containing the fully-qualified pathname to the {@link Region}
|
||||
* used to specify Lucene queries.
|
||||
* @see #resolveRegionPath()
|
||||
* @see #getRegion()
|
||||
*/
|
||||
public String getRegionPath() {
|
||||
return this.regionPath;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected <T> T doFind(LuceneQueryExecutor<T> queryExecutor, Object query, String regionPath, String indexName) {
|
||||
try {
|
||||
return queryExecutor.execute();
|
||||
}
|
||||
catch (LuceneQueryException e) {
|
||||
throw new DataRetrievalFailureException(String.format(
|
||||
"Failed to execute Lucene Query [%1$s] on Region [%2$s] with Lucene Index [%3$s]",
|
||||
query, regionPath, indexName), e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@FunctionalInterface
|
||||
protected interface LuceneQueryExecutor<T> {
|
||||
T execute() throws LuceneQueryException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeList;
|
||||
import static org.springframework.data.gemfire.util.CollectionUtils.nullSafeMap;
|
||||
import static org.springframework.util.CollectionUtils.isEmpty;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.geode.cache.lucene.LuceneServiceProvider;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.gemfire.util.CacheUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} used to construct {@link LuceneIndex Lucene Indexes} on application domain object fields.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.beans.factory.BeanNameAware
|
||||
* @see org.springframework.beans.factory.DisposableBean
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.lucene.LuceneServiceProvider
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LuceneIndexFactoryBean implements FactoryBean<LuceneIndex>,
|
||||
BeanFactoryAware, BeanNameAware, InitializingBean, DisposableBean {
|
||||
|
||||
protected static final boolean DEFAULT_DESTROY = false;
|
||||
|
||||
private boolean destroy = DEFAULT_DESTROY;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
private List<String> fields;
|
||||
|
||||
private LuceneIndex luceneIndex;
|
||||
|
||||
private LuceneService luceneService;
|
||||
|
||||
private Map<String, Analyzer> fieldAnalyzers;
|
||||
|
||||
private Region<?, ?> region;
|
||||
|
||||
private String indexName;
|
||||
private String regionPath;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
String indexName = getIndexName();
|
||||
|
||||
this.gemfireCache = resolveCache();
|
||||
this.luceneService = resolveLuceneService();
|
||||
this.regionPath = resolveRegionPath();
|
||||
|
||||
setLuceneIndex(createIndex(indexName, getRegionPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link LuceneIndex} with the given {@code indexName} on the {@link GemFireCache} {@link Region}
|
||||
* identified by the given {@code regionPath}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name for the {@link LuceneIndex}.
|
||||
* @param regionPath {@link String} containing the fully-qualified pathname to
|
||||
* the {@link GemFireCache} {@link Region}.
|
||||
* @return a new instance of {@link LuceneIndex} with the given {@code indexName} on the named {@link Region}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService#createIndex(String, String, Map)
|
||||
* @see org.apache.geode.cache.lucene.LuceneService#createIndex(String, String, String...)
|
||||
* @see org.apache.geode.cache.lucene.LuceneService#getIndex(String, String)
|
||||
* @see #resolveLuceneService()
|
||||
* @see #getFieldAnalyzers()
|
||||
* @see #getFields()
|
||||
* @see #resolveFields(List)
|
||||
*/
|
||||
protected LuceneIndex createIndex(String indexName, String regionPath) {
|
||||
LuceneService luceneService = resolveLuceneService();
|
||||
|
||||
Map<String, Analyzer> fieldAnalyzers = getFieldAnalyzers();
|
||||
|
||||
if (isEmpty(fieldAnalyzers)) {
|
||||
luceneService.createIndex(indexName, regionPath, asArray(resolveFields(getFields())));
|
||||
}
|
||||
else {
|
||||
luceneService.createIndex(indexName, regionPath, fieldAnalyzers);
|
||||
}
|
||||
|
||||
return luceneService.getIndex(indexName, regionPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the {@link List} of {@link String Strings} into an {@link String[]} array.
|
||||
*
|
||||
* @param list {@link List} to convert into a typed array.
|
||||
* @return a {@link String[]} array for the {@link List} of {@link String Strings}.
|
||||
* @see java.util.List#toArray(Object[])
|
||||
*/
|
||||
private String[] asArray(List<String> list) {
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public void destroy() throws Exception {
|
||||
LuceneIndex luceneIndex = getObject();
|
||||
|
||||
if (isLuceneIndexDestroyable(luceneIndex)) {
|
||||
resolveLuceneService().destroyIndex(luceneIndex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the given {@link LuceneIndex} created by this {@link FactoryBean} is destroyable.
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} subject to destruction.
|
||||
* @return a boolean value indicating whether the given {@link LuceneIndex} created by this {@link FactoryBean}
|
||||
* is destroyable.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see #isDestroy()
|
||||
*/
|
||||
protected boolean isLuceneIndexDestroyable(LuceneIndex luceneIndex) {
|
||||
return (luceneIndex != null && isDestroy());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public LuceneIndex getObject() throws Exception {
|
||||
if (this.luceneIndex == null) {
|
||||
setLuceneIndex(Optional.ofNullable(resolveLuceneService())
|
||||
.map((luceneService) -> luceneService.getIndex(getIndexName(), resolveRegionPath()))
|
||||
.orElse(null));
|
||||
}
|
||||
|
||||
return this.luceneIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Optional.ofNullable(this.luceneIndex).<Class<?>>map(LuceneIndex::getClass).orElse(LuceneIndex.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @return a reference to the single instance of the {@link GemFireCache}.
|
||||
* @see org.springframework.data.gemfire.util.CacheUtils#resolveGemFireCache()
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #getCache()
|
||||
*/
|
||||
protected GemFireCache resolveCache() {
|
||||
return Optional.ofNullable(getCache()).orElseGet(CacheUtils::resolveGemFireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link List} of fields on the object to index.
|
||||
*
|
||||
* @param fields {@link List} of fields to evaluate.
|
||||
* @return a resolve {@link List} of object fields to index.
|
||||
*/
|
||||
protected List<String> resolveFields(List<String> fields) {
|
||||
return (!isEmpty(fields) ? fields : Collections.singletonList(LuceneService.REGION_VALUE_FIELD));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link LuceneService} used by this {@link FactoryBean} to create the {@link LuceneIndex}.
|
||||
*
|
||||
* @return a reference to the {@link GemFireCache}, {@link LuceneService}.
|
||||
* @see org.springframework.beans.factory.BeanFactory#getBean(Class)
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see #getBeanFactory()
|
||||
* @see #getLuceneService()
|
||||
* @see #resolveCache()
|
||||
* @see #resolveLuceneService(GemFireCache)
|
||||
*/
|
||||
protected LuceneService resolveLuceneService() {
|
||||
return Optional.ofNullable(getLuceneService()).orElseGet(() ->
|
||||
Optional.ofNullable(getBeanFactory()).map(beanFactory -> {
|
||||
try {
|
||||
return beanFactory.getBean(LuceneService.class);
|
||||
}
|
||||
catch (BeansException ignore) {
|
||||
return null;
|
||||
}
|
||||
}).orElseGet(() -> resolveLuceneService(resolveCache())));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the {@link LuceneService} used by this {@link FactoryBean} to create the {@link LuceneIndex}.
|
||||
*
|
||||
* @param gemfireCache {@link GemFireCache} used to resolve the {@link LuceneService}.
|
||||
* @return a reference to the {@link GemFireCache} {@link LuceneService}.
|
||||
* @throws IllegalArgumentException if {@link GemFireCache} is {@literal null}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
protected LuceneService resolveLuceneService(GemFireCache gemfireCache) {
|
||||
Assert.notNull(gemfireCache, "A reference to the GemFireCache was not properly configured");
|
||||
return LuceneServiceProvider.get(gemfireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex} will be created.
|
||||
*
|
||||
* @return a reference to the {@link GemFireCache} {@link Region} on which he {@link LuceneIndex} will be created.
|
||||
* Returns {@literal null} if the {@link Region} cannot be resolved.
|
||||
* @see org.apache.geode.cache.RegionService#getRegion(String)
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #resolveCache()
|
||||
* @see #getRegionPath()
|
||||
*/
|
||||
protected Region<?, ?> resolveRegion() {
|
||||
return Optional.ofNullable(getRegion()).orElseGet(() -> {
|
||||
GemFireCache cache = resolveCache();
|
||||
String regionPath = getRegionPath();
|
||||
|
||||
return (cache != null && StringUtils.hasText(regionPath) ? cache.getRegion(regionPath) : null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the fully-qualified pathname of the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex}
|
||||
* will be created.
|
||||
*
|
||||
* @return a {@link String} containing the fully-qualified pathname of the {@link GemFireCache} {@link Region}
|
||||
* on which the {@link LuceneIndex} will be created.
|
||||
* @throws IllegalStateException if the {@link Region} pathname could not resolved.
|
||||
* @see #resolveRegion()
|
||||
* @see #getRegionPath()
|
||||
*/
|
||||
protected String resolveRegionPath() {
|
||||
String regionPath = Optional.ofNullable(resolveRegion())
|
||||
.map(Region::getFullPath).orElseGet(this::getRegionPath);
|
||||
|
||||
Assert.state(StringUtils.hasText(regionPath), "Either Region or regionPath must be specified");
|
||||
|
||||
return regionPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the containing Spring {@link BeanFactory} if set.
|
||||
*
|
||||
* @return a reference to the containing Spring {@link BeanFactory} if set.
|
||||
* @see org.springframework.beans.factory.BeanFactory
|
||||
*/
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return this.beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void setBeanName(String name) {
|
||||
setIndexName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @param gemfireCache {@link GemFireCache} reference.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
public void setCache(GemFireCache gemfireCache) {
|
||||
this.gemfireCache = gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link GemFireCache}.
|
||||
*
|
||||
* @return a reference to the {@link GemFireCache}.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see #resolveCache()
|
||||
*/
|
||||
protected GemFireCache getCache() {
|
||||
return this.gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to destroy the {@link LuceneIndex} on shutdown.
|
||||
*
|
||||
* @param destroy boolean value indicating whether to destroy the {@link LuceneIndex} on shutdown.
|
||||
*/
|
||||
public void setDestroy(boolean destroy) {
|
||||
this.destroy = destroy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the {@link LuceneIndex} will be destroyed on shutdown.
|
||||
*
|
||||
* @return a boolean value indicating whether the {@link LuceneIndex} will be destroyed on shutdown.
|
||||
* @see org.springframework.beans.factory.DisposableBean#destroy()
|
||||
*/
|
||||
protected boolean isDestroy() {
|
||||
return this.destroy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link Map} of application domain object field names to {@link Analyzer Analyzers} used in the construction
|
||||
* of the {@link LuceneIndex Lucene Indexes} for each field.
|
||||
*
|
||||
* @param fieldAnalyzers {@link Map} of fields names to {@link Analyzer Analyzers}.
|
||||
* @see org.apache.lucene.analysis.Analyzer
|
||||
* @see java.util.Map
|
||||
*/
|
||||
public void setFieldAnalyzers(Map<String, Analyzer> fieldAnalyzers) {
|
||||
this.fieldAnalyzers = fieldAnalyzers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Map} of application domain object field names to {@link Analyzer Analyzers} used in
|
||||
* the construction of the {@link LuceneIndex Lucene Indexes} for each field.
|
||||
*
|
||||
* @return a {@link Map} of fields names to {@link Analyzer Analyzers}.
|
||||
* @see org.apache.lucene.analysis.Analyzer
|
||||
* @see java.util.Map
|
||||
* @see #getFields()
|
||||
*/
|
||||
protected Map<String, Analyzer> getFieldAnalyzers() {
|
||||
return nullSafeMap(this.fieldAnalyzers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application domain object fields to index.
|
||||
*
|
||||
* @param fields array of {@link String Strings} containing the names of the object fields ot index.
|
||||
* @see #setFields(List)
|
||||
*/
|
||||
public void setFields(String... fields) {
|
||||
setFields(Arrays.asList(nullSafeArray(fields, String.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application domain object fields to index.
|
||||
*
|
||||
* @param fields {@link List} of {@link String Strings} containing the names of the object fields ot index.
|
||||
*/
|
||||
public void setFields(List<String> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link List} of application domain object fields to be indexed.
|
||||
*
|
||||
* @return a {@link List} of application domain object fields to be indexed.
|
||||
* @see #getFieldAnalyzers()
|
||||
* @see java.util.List
|
||||
*/
|
||||
protected List<String> getFields() {
|
||||
return nullSafeList(this.fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the {@link LuceneIndex} as identified in the {@link GemFireCache}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @see #setBeanName(String)
|
||||
*/
|
||||
public void setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the {@link LuceneIndex} as identified in the {@link GemFireCache}.
|
||||
*
|
||||
* @return a {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @throws IllegalStateException if the {@code indexName} was not specified.
|
||||
*/
|
||||
protected String getIndexName() {
|
||||
Assert.state(StringUtils.hasText(this.indexName), "indexName was not properly initialized");
|
||||
return this.indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link LuceneIndex} as the index created by this {@link FactoryBean}.
|
||||
*
|
||||
* This method is for testing purposes only!
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} created by this {@link FactoryBean}.
|
||||
* @return this {@link LuceneIndexFactoryBean}.
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
*/
|
||||
protected LuceneIndexFactoryBean setLuceneIndex(LuceneIndex luceneIndex) {
|
||||
this.luceneIndex = luceneIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link LuceneService} used by this {@link FactoryBean} to create the {@link LuceneIndex}.
|
||||
*
|
||||
* @param luceneService {@link LuceneService} used to create the {@link LuceneIndex}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
*/
|
||||
public void setLuceneService(LuceneService luceneService) {
|
||||
this.luceneService = luceneService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link LuceneService} used by this {@link FactoryBean} to create
|
||||
* the {@link LuceneIndex}.
|
||||
*
|
||||
* @return a reference to the {@link LuceneService} used to create the {@link LuceneIndex}.
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see #resolveLuceneService()
|
||||
*/
|
||||
protected LuceneService getLuceneService() {
|
||||
return this.luceneService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex} will be created.
|
||||
*
|
||||
* @param region {@link Region} on which the {@link LuceneIndex} will be created.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #setRegionPath(String)
|
||||
*/
|
||||
public void setRegion(Region<?, ?> region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex} will be created.
|
||||
*
|
||||
* @return a reference to the {@link Region} on which the {@link LuceneIndex} will be created.
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see #getRegionPath()
|
||||
* @see #resolveRegion()
|
||||
*/
|
||||
protected Region<?, ?> getRegion() {
|
||||
return this.region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fully-qualified pathname to the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex}
|
||||
* will be created.
|
||||
*
|
||||
* @param pathname {@link String} containing the fully-qualified pathname to the {@link GemFireCache} {@link Region}
|
||||
* on which the {@link LuceneIndex} will be created.
|
||||
* @see #setRegion(Region)
|
||||
*/
|
||||
public void setRegionPath(String pathname) {
|
||||
this.regionPath = pathname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully-qualified pathname to the {@link GemFireCache} {@link Region} on which the {@link LuceneIndex}
|
||||
* will be created.
|
||||
*
|
||||
* @return a {@link String} containing the fully-qualified pathname to the {@link GemFireCache} {@link Region}
|
||||
* on which the {@link LuceneIndex} will be created.
|
||||
* @see #getRegion()
|
||||
*/
|
||||
protected String getRegionPath() {
|
||||
return this.regionPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneQueryFactory;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.apache.geode.cache.lucene.LuceneResultStruct;
|
||||
import org.apache.geode.cache.lucene.PageableLuceneQueryResults;
|
||||
|
||||
/**
|
||||
* The {@link LuceneOperations} interface defines a contract for implementations defining data access operations
|
||||
* using Lucene queries.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryProvider
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see org.apache.geode.cache.lucene.PageableLuceneQueryResults
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface LuceneOperations {
|
||||
|
||||
int DEFAULT_PAGE_SIZE = LuceneQueryFactory.DEFAULT_PAGESIZE;
|
||||
int DEFAULT_RESULT_LIMIT = LuceneQueryFactory.DEFAULT_LIMIT;
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query}.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link List} of {@link LuceneResultStruct} containing the query results.
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see #query(String, String, int, String...)
|
||||
* @see java.util.List
|
||||
*/
|
||||
default <K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField,
|
||||
String... projectionFields) {
|
||||
|
||||
return query(query, defaultField, DEFAULT_RESULT_LIMIT, projectionFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} with a limit on the number of results returned.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @param resultLimit limit on the number of query results to return.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link List} of {@link LuceneResultStruct} containing the query results.
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see java.util.List
|
||||
*/
|
||||
<K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField,
|
||||
int resultLimit, String... projectionFields);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} with a limit on the number of results returned
|
||||
* along with a page size for paging.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @param resultLimit limit on the number of query results to return.
|
||||
* @param pageSize number of results per page.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link PageableLuceneQueryResults} data structure containing the results of the Lucene query.
|
||||
* @see org.apache.geode.cache.lucene.PageableLuceneQueryResults
|
||||
*/
|
||||
<K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
|
||||
int resultLimit, int pageSize, String... projectionFields);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query}.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link List} of {@link LuceneResultStruct} containing the query results.
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see #query(LuceneQueryProvider, int, String...)
|
||||
* @see java.util.List
|
||||
*/
|
||||
default <K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider,
|
||||
String... projectionFields) {
|
||||
|
||||
return query(queryProvider, DEFAULT_RESULT_LIMIT, projectionFields);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} with a limit on the number of results returned.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @param resultLimit limit on the number of query results to return.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link List} of {@link LuceneResultStruct} containing the query results.
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see java.util.List
|
||||
*/
|
||||
<K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, String... projectionFields);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} with a limit on the number of results returned
|
||||
* along with a page size for paging.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @param resultLimit limit on the number of query results to return.
|
||||
* @param pageSize number of results per page.
|
||||
* @param projectionFields array of {@link String} values specifying the query projection.
|
||||
* @return a {@link PageableLuceneQueryResults} data structure containing the results of the Lucene query.
|
||||
* @see org.apache.geode.cache.lucene.PageableLuceneQueryResults
|
||||
*/
|
||||
<K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, int pageSize, String... projectionFields);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of keys
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* The number of keys returned is limited by {@link LuceneQueryFactory#DEFAULT_LIMIT}.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @return a {@link Collection} of keys matching the Lucene query clause (predicate).
|
||||
* @see #queryForKeys(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
default <K> Collection<K> queryForKeys(String query, String defaultField) {
|
||||
return queryForKeys(query, defaultField, DEFAULT_RESULT_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of keys
|
||||
* matching the query clause/predicate with a limit on the number of keys returned.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @param resultLimit limit on the number of keys returned.
|
||||
* @return a {@link Collection} of keys matching the Lucene query clause (predicate).
|
||||
* @see #queryForKeys(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
<K> Collection<K> queryForKeys(String query, String defaultField, int resultLimit);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of keys
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* The number of keys returned is limited by {@link LuceneQueryFactory#DEFAULT_LIMIT}.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @return a {@link Collection} of keys matching the Lucene query clause (predicate).
|
||||
* @see #queryForKeys(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
default <K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider) {
|
||||
return queryForKeys(queryProvider, DEFAULT_RESULT_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of keys
|
||||
* matching the query clause/predicate with a limit on the number of keys returned.
|
||||
*
|
||||
* @param <K> {@link Class} type of the key.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @param resultLimit limit on the number of keys returned.
|
||||
* @return a {@link Collection} of keys matching the Lucene query clause (predicate).
|
||||
* @see #queryForKeys(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
<K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider, int resultLimit);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of values
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* The number of values returned is limited by {@link LuceneQueryFactory#DEFAULT_LIMIT}.
|
||||
*
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @return a {@link Collection} of values matching Lucene query clause (predicate).
|
||||
* @see #queryForValues(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
default <V> Collection<V> queryForValues(String query, String defaultField) {
|
||||
return queryForValues(query, defaultField, DEFAULT_RESULT_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of values
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param query {@link String} containing the Lucene query to execute.
|
||||
* @param defaultField {@link String} specifying the default field used in Lucene queries when a field
|
||||
* is not explicitly defined in the Lucene query clause.
|
||||
* @param resultLimit limit on the number of values returned.
|
||||
* @return a {@link Collection} of values matching Lucene query clause (predicate).
|
||||
* @see #queryForValues(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
<V> Collection<V> queryForValues(String query, String defaultField, int resultLimit);
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of values
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* The number of values returned is limited by {@link LuceneQueryFactory#DEFAULT_LIMIT}.
|
||||
*
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @return a {@link Collection} of values matching Lucene query clause (predicate).
|
||||
* @see #queryForValues(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
default <V> Collection<V> queryForValues(LuceneQueryProvider queryProvider) {
|
||||
return queryForValues(queryProvider, DEFAULT_RESULT_LIMIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given Lucene {@link String query} returning a {@link Collection} of values
|
||||
* matching the query clause/predicate.
|
||||
*
|
||||
* @param <V> {@link Class} type of the value.
|
||||
* @param queryProvider {@link LuceneQueryProvider} is a provider implementation supplying the Lucene query
|
||||
* to execute as well as de/serialize to distribute across the cluster.
|
||||
* @param resultLimit limit on the number of values returned.
|
||||
* @return a {@link Collection} of values matching Lucene query clause (predicate).
|
||||
* @see #queryForValues(String, String, int)
|
||||
* @see java.util.Collection
|
||||
*/
|
||||
<V> Collection<V> queryForValues(LuceneQueryProvider queryProvider, int resultLimit);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.geode.cache.lucene.LuceneServiceProvider;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring {@link FactoryBean} used to get an instance of the {@link GemFireCache} {@link LuceneService}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
* @see org.apache.geode.cache.lucene.LuceneServiceProvider
|
||||
* @see org.springframework.beans.factory.FactoryBean
|
||||
* @see org.springframework.beans.factory.InitializingBean
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LuceneServiceFactoryBean implements FactoryBean<LuceneService>, InitializingBean {
|
||||
|
||||
private GemFireCache gemfireCache;
|
||||
|
||||
private LuceneService luceneService;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
GemFireCache gemfireCache = getCache();
|
||||
|
||||
Assert.state(gemfireCache != null,
|
||||
"A reference to the GemFireCache was not properly configured");
|
||||
|
||||
this.luceneService = resolveLuceneService(gemfireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to resolve the Singleton instance of the {@link GemFireCache} {@link LuceneService}
|
||||
* from given the {@link GemFireCache}.
|
||||
*
|
||||
* @param gemFireCache {@link GemFireCache} used to resolve the {@link LuceneService} instance.
|
||||
* @return a single instance of the GemFire {@link LuceneService}.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
* @see org.apache.geode.cache.lucene.LuceneService
|
||||
*/
|
||||
protected LuceneService resolveLuceneService(GemFireCache gemFireCache) {
|
||||
return LuceneServiceProvider.get(gemfireCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public LuceneService getObject() throws Exception {
|
||||
return this.luceneService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return Optional.ofNullable(this.luceneService).<Class<?>>map(LuceneService::getClass).orElse(LuceneService.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a reference to the single {@link GemFireCache} instance.
|
||||
*
|
||||
* @param gemfireCache {@link GemFireCache} reference.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
public void setCache(GemFireCache gemfireCache) {
|
||||
this.gemfireCache = gemfireCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the single {@link GemFireCache} instance.
|
||||
*
|
||||
* @return a reference to the single {@link GemFireCache} instance.
|
||||
* @see org.apache.geode.cache.GemFireCache
|
||||
*/
|
||||
protected GemFireCache getCache() {
|
||||
return this.gemfireCache;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneQuery;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryFactory;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.apache.geode.cache.lucene.LuceneResultStruct;
|
||||
import org.apache.geode.cache.lucene.PageableLuceneQueryResults;
|
||||
import org.springframework.data.gemfire.search.lucene.support.LuceneAccessorSupport;
|
||||
|
||||
/**
|
||||
* {@link LuceneTemplate} is a Lucene data access operations class encapsulating functionality
|
||||
* for performing Lucene queries and other Lucene data access operations.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneAccessor
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneOperations
|
||||
* @see org.apache.geode.cache.Region
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
* @see org.apache.geode.cache.lucene.LuceneQuery
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryFactory
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryProvider
|
||||
* @see org.apache.geode.cache.lucene.LuceneResultStruct
|
||||
* @see org.apache.geode.cache.lucene.PageableLuceneQueryResults
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class LuceneTemplate extends LuceneAccessorSupport implements LuceneOperations {
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of {@link LuceneTemplate}.
|
||||
*/
|
||||
public LuceneTemplate() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneTemplate} initialized with the given {@link LuceneIndex}.
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} used in Lucene queries.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
*/
|
||||
public LuceneTemplate(LuceneIndex luceneIndex) {
|
||||
super(luceneIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneTemplate} initialized with the given Lucene {@link String index name}
|
||||
* and {@link Region}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param region {@link Region} on which the Lucene query is executed.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public LuceneTemplate(String indexName, Region<?, ?> region) {
|
||||
super(indexName, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneTemplate} initialized with the given Lucene {@link String index name}
|
||||
* and {@link String fully-qualified Region path}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param regionPath {@link String} containing the fully-qualified path of the {@link Region}.
|
||||
*/
|
||||
public LuceneTemplate(String indexName, String regionPath) {
|
||||
super(indexName, regionPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit, projectionFields);
|
||||
|
||||
LuceneQuery<K, V> queryWrapper = queryFactory.create(indexName, regionPath, query, defaultField);
|
||||
|
||||
return doFind(queryWrapper::findResults, query, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit, pageSize, projectionFields);
|
||||
|
||||
LuceneQuery<K, V> queryWrapper = queryFactory.create(indexName, regionPath, query, defaultField);
|
||||
|
||||
return doFind(queryWrapper::findPages, query, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit, projectionFields);
|
||||
|
||||
LuceneQuery<K, V> queryWrapper = queryFactory.create(indexName, regionPath, queryProvider);
|
||||
|
||||
return doFind(queryWrapper::findResults, queryProvider, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit, pageSize, projectionFields);
|
||||
|
||||
LuceneQuery<K, V> queryWrapper = queryFactory.create(indexName, regionPath, queryProvider);
|
||||
|
||||
return doFind(queryWrapper::findPages, queryProvider, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(String query, String defaultField, int resultLimit) {
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit);
|
||||
|
||||
LuceneQuery<K, ?> queryWrapper = queryFactory.create(indexName, regionPath, query, defaultField);
|
||||
|
||||
return doFind(queryWrapper::findKeys, query, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit);
|
||||
|
||||
LuceneQuery<K, ?> queryWrapper = queryFactory.create(indexName, regionPath, queryProvider);
|
||||
|
||||
return doFind(queryWrapper::findKeys, queryProvider, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(String query, String defaultField, int resultLimit) {
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit);
|
||||
|
||||
LuceneQuery<?, V> queryWrapper = queryFactory.create(indexName, regionPath, query, defaultField);
|
||||
|
||||
return doFind(queryWrapper::findValues, query, regionPath, indexName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
String indexName = resolveIndexName();
|
||||
String regionPath = resolveRegionPath();
|
||||
|
||||
LuceneQueryFactory queryFactory = createLuceneQueryFactory(resultLimit);
|
||||
|
||||
LuceneQuery<?, V> queryWrapper = queryFactory.create(indexName, regionPath, queryProvider);
|
||||
|
||||
return doFind(queryWrapper::findValues, queryProvider, regionPath, indexName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
/**
|
||||
* The {@link MappingLuceneOperations} interface defines a contract for implementing classes to execute
|
||||
* Lucene data access operations and mapping the results to entity domain {@link Class types}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.domain.Page
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneOperations
|
||||
* @see org.apache.geode.cache.lucene.LuceneQueryProvider
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface MappingLuceneOperations extends LuceneOperations {
|
||||
|
||||
default <T> List<T> query(Class<T> entityType, String query, String defaultField,
|
||||
String... projectionFields) {
|
||||
|
||||
return query(entityType, query, defaultField, DEFAULT_RESULT_LIMIT, projectionFields);
|
||||
}
|
||||
|
||||
<T> List<T> query(Class<T> entityType, String query, String defaultField,
|
||||
int resultLimit, String... projectionFields);
|
||||
|
||||
<T> Page<T> query(Class<T> entityType, String query, String defaultField,
|
||||
int resultLimit, int pageSize, String... projectionFields);
|
||||
|
||||
default <T> List<T> query(Class<T> entityType, LuceneQueryProvider queryProvider,
|
||||
String... projectionFields) {
|
||||
|
||||
return query(entityType, queryProvider, DEFAULT_RESULT_LIMIT, projectionFields);
|
||||
}
|
||||
|
||||
<T> List<T> query(Class<T> entityType, LuceneQueryProvider queryProvider,
|
||||
int resultLimit, String... projectionFields);
|
||||
|
||||
<T> Page<T> query(Class<T> entityType, LuceneQueryProvider queryProvider,
|
||||
int resultLimit, int pageSize, String... projectionFields);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newUnsupportedOperationException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.apache.geode.cache.lucene.LuceneResultStruct;
|
||||
import org.apache.geode.cache.lucene.PageableLuceneQueryResults;
|
||||
import org.springframework.data.gemfire.search.lucene.LuceneAccessor;
|
||||
import org.springframework.data.gemfire.util.RuntimeExceptionFactory;
|
||||
|
||||
/**
|
||||
* {@link LuceneAccessorSupport} is a {@link LuceneAccessor} class implementation providing support
|
||||
* for extending classes.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneAccessor
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class LuceneAccessorSupport extends LuceneAccessor {
|
||||
|
||||
/**
|
||||
* Constructs an uninitialized instance of {@link LuceneAccessorSupport}.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public LuceneAccessorSupport() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneAccessorSupport} initialized with the given {@link LuceneIndex}.
|
||||
*
|
||||
* @param luceneIndex {@link LuceneIndex} used in Lucene queries.
|
||||
* @see org.apache.geode.cache.lucene.LuceneIndex
|
||||
*/
|
||||
public LuceneAccessorSupport(LuceneIndex luceneIndex) {
|
||||
super(luceneIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneAccessorSupport} initialized with the given Lucene
|
||||
* {@link String index name} and {@link Region}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param region {@link Region} on which the Lucene query is executed.
|
||||
* @see org.apache.geode.cache.Region
|
||||
*/
|
||||
public LuceneAccessorSupport(String indexName, Region<?, ?> region) {
|
||||
super(indexName, region);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of {@link LuceneAccessorSupport} initialized with the given Lucene
|
||||
* {@link String index name} and {@link String fully-qualified Region path}.
|
||||
*
|
||||
* @param indexName {@link String} containing the name of the {@link LuceneIndex}.
|
||||
* @param regionPath {@link String} containing the fully-qualified path of the {@link Region}.
|
||||
*/
|
||||
public LuceneAccessorSupport(String indexName, String regionPath) {
|
||||
super(indexName, regionPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(String query, String defaultField, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(String query, String defaultField, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene.support;
|
||||
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newUnsupportedOperationException;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.apache.geode.cache.lucene.LuceneResultStruct;
|
||||
import org.apache.geode.cache.lucene.PageableLuceneQueryResults;
|
||||
import org.springframework.data.gemfire.search.lucene.LuceneOperations;
|
||||
import org.springframework.data.gemfire.util.RuntimeExceptionFactory;
|
||||
|
||||
/**
|
||||
* {@link LuceneOperationsSupport} is a abstract supporting class for implementations
|
||||
* of the {@link LuceneOperations} interface.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneOperations
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class LuceneOperationsSupport implements LuceneOperations {
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(String query, String defaultField,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(String query, String defaultField,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> List<LuceneResultStruct<K, V>> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K, V> PageableLuceneQueryResults<K, V> query(LuceneQueryProvider queryProvider,
|
||||
int resultLimit, int pageSize, String... projectionFields) {
|
||||
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(String query, String defaultField, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <K> Collection<K> queryForKeys(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(String query, String defaultField, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public <V> Collection<V> queryForValues(LuceneQueryProvider queryProvider, int resultLimit) {
|
||||
throw newUnsupportedOperationException(RuntimeExceptionFactory.NOT_IMPLEMENTED);
|
||||
}
|
||||
}
|
||||
@@ -124,4 +124,8 @@ public abstract class CacheUtils extends DistributedSystemUtils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static GemFireCache resolveGemFireCache() {
|
||||
return defaultIfNull(getCache(), CacheUtils::getClientCache);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,25 @@ import java.text.MessageFormat;
|
||||
* with the added convenience of message formatting and optional {@link Throwable causes}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @since 1.0.0
|
||||
* @see java.lang.RuntimeException
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public abstract class RuntimeExceptionFactory {
|
||||
|
||||
public static final String NOT_IMPLEMENTED = "Not Implemented";
|
||||
|
||||
/**
|
||||
* Constructs and initializes an {@link IllegalArgumentException} with the given {@link String message}
|
||||
* and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
<<<<<<< HEAD
|
||||
* @param message {@link String} describing the exception.
|
||||
* @param args {@link Object[] arguments} used in the message to replace format placeholders.
|
||||
=======
|
||||
* @param message {@link String} describing the {@link IllegalArgumentException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}.
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
* @return a new {@link IllegalArgumentException} with the given {@link String message}.
|
||||
* @see #newIllegalArgumentException(Throwable, String, Object...)
|
||||
* @see java.lang.IllegalArgumentException
|
||||
@@ -63,8 +71,8 @@ public abstract class RuntimeExceptionFactory {
|
||||
* Constructs and initializes an {@link IllegalStateException} with the given {@link String message}
|
||||
* and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
* @param message {@link String} describing the exception.
|
||||
* @param args {@link Object[] arguments} used in the message to replace format placeholders.
|
||||
* @param message {@link String} describing the {@link IllegalStateException exception}.
|
||||
* @param args {@link Object} array of arguments used to replace format placeholders in the {@link String message}.
|
||||
* @return a new {@link IllegalStateException} with the given {@link String message}.
|
||||
* @see #newIllegalStateException(Throwable, String, Object...)
|
||||
* @see java.lang.IllegalStateException
|
||||
@@ -78,9 +86,15 @@ public abstract class RuntimeExceptionFactory {
|
||||
* {@link String message} and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
* @param cause {@link Throwable} identifying the reason the {@link IllegalStateException} was thrown.
|
||||
<<<<<<< HEAD
|
||||
* @param message {@link String} describing the exception.
|
||||
* @param args {@link Object[] arguments} used in the message to replace format placeholders.
|
||||
* @return a new {@link IllegalStateException} with the given {@link String message}.
|
||||
=======
|
||||
* @param message {@link String} describing the {@link IllegalStateException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}.
|
||||
* @return a new {@link IllegalStateException} with the given {@link Throwable cause} and {@link String message}.
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
* @see java.lang.IllegalStateException
|
||||
*/
|
||||
public static IllegalStateException newIllegalStateException(Throwable cause, String message, Object... args) {
|
||||
@@ -91,8 +105,13 @@ public abstract class RuntimeExceptionFactory {
|
||||
* Constructs and initializes an {@link RuntimeException} with the given {@link String message}
|
||||
* and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
<<<<<<< HEAD
|
||||
* @param message {@link String} describing the exception.
|
||||
* @param args {@link Object[] arguments} used in the message to replace format placeholders.
|
||||
=======
|
||||
* @param message {@link String} describing the {@link RuntimeException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}.
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
* @return a new {@link RuntimeException} with the given {@link String message}.
|
||||
* @see #newRuntimeException(Throwable, String, Object...)
|
||||
* @see java.lang.RuntimeException
|
||||
@@ -106,9 +125,15 @@ public abstract class RuntimeExceptionFactory {
|
||||
* {@link String message} and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
* @param cause {@link Throwable} identifying the reason the {@link RuntimeException} was thrown.
|
||||
<<<<<<< HEAD
|
||||
* @param message {@link String} describing the exception.
|
||||
* @param args {@link Object[] arguments} used in the message to replace format placeholders.
|
||||
* @return a new {@link RuntimeException} with the given {@link String message}.
|
||||
=======
|
||||
* @param message {@link String} describing the {@link RuntimeException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}.
|
||||
* @return a new {@link RuntimeException} with the given {@link Throwable cause} and {@link String message}.
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
* @see java.lang.RuntimeException
|
||||
*/
|
||||
public static RuntimeException newRuntimeException(Throwable cause, String message, Object... args) {
|
||||
@@ -116,6 +141,40 @@ public abstract class RuntimeExceptionFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
* Constructs and initializes an {@link UnsupportedOperationException} with the given {@link String message}
|
||||
* and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
* @param message {@link String} describing the {@link UnsupportedOperationException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}
|
||||
* @return a new {@link UnsupportedOperationException} with the given {@link String message}.
|
||||
* @see #newUnsupportedOperationException(Throwable, String, Object...)
|
||||
* @see java.lang.UnsupportedOperationException
|
||||
*/
|
||||
public static UnsupportedOperationException newUnsupportedOperationException(String message, Object... args) {
|
||||
return newUnsupportedOperationException(null, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and initializes an {@link UnsupportedOperationException} with the given {@link Throwable cause},
|
||||
* {@link String message} and {@link Object[] arguments} used to format the message.
|
||||
*
|
||||
* @param cause {@link Throwable} identifying the reason the {@link UnsupportedOperationException} was thrown.
|
||||
* @param message {@link String} describing the {@link UnsupportedOperationException exception}.
|
||||
* @param args {@link Object[] arguments} used to replace format placeholders in the {@link String message}.
|
||||
* @return a new {@link UnsupportedOperationException} with the given {@link Throwable cause}
|
||||
* and {@link String message}.
|
||||
* @see java.lang.UnsupportedOperationException
|
||||
*/
|
||||
public static UnsupportedOperationException newUnsupportedOperationException(Throwable cause,
|
||||
String message, Object... args) {
|
||||
|
||||
return new UnsupportedOperationException(format(message, args), cause);
|
||||
}
|
||||
|
||||
/**
|
||||
>>>>>>> f104d57... SGF-402 - Add Lucene Integration support.
|
||||
* Formats the given {@link String message} using the given {@link Object[] arguments}.
|
||||
*
|
||||
* @param message {@link String} containing the message pattern to format.
|
||||
|
||||
@@ -20,8 +20,10 @@ package org.springframework.data.gemfire.util;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
@@ -34,15 +36,15 @@ import org.springframework.util.StringUtils;
|
||||
* @since 1.8.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
// TODO rename this utiltiy class using a more descriptive, intuitive and meaningful name
|
||||
// TODO rename this utility class using a more descriptive, intuitive and meaningful name
|
||||
public abstract class SpringUtils {
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static BeanDefinition addDependsOn(BeanDefinition bean, String beanName) {
|
||||
public static BeanDefinition addDependsOn(BeanDefinition bean, String... beanNames) {
|
||||
List<String> dependsOnList = new ArrayList<>();
|
||||
|
||||
Collections.addAll(dependsOnList, nullSafeArray(bean.getDependsOn(), String.class));
|
||||
dependsOnList.add(beanName);
|
||||
dependsOnList.addAll(Arrays.asList(nullSafeArray(beanNames, String.class)));
|
||||
bean.setDependsOn(dependsOnList.toArray(new String[dependsOnList.size()]));
|
||||
|
||||
return bean;
|
||||
@@ -58,6 +60,16 @@ public abstract class SpringUtils {
|
||||
return (value != null ? value : defaultValue);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static <T> T defaultIfNull(T value, Supplier<T> supplier) {
|
||||
return (value != null ? value : supplier.get());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String dereferenceBean(String beanName) {
|
||||
return String.format("%1$s%2$s", BeanFactory.FACTORY_BEAN_PREFIX, beanName);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static boolean equalsIgnoreNull(Object obj1, Object obj2) {
|
||||
return (obj1 == null ? obj2 == null : obj1.equals(obj2));
|
||||
@@ -74,7 +86,17 @@ public abstract class SpringUtils {
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static String dereferenceBean(String beanName) {
|
||||
return String.format("%1$s%2$s", BeanFactory.FACTORY_BEAN_PREFIX, beanName);
|
||||
public static <T> T safeGetValue(Supplier<T> supplier) {
|
||||
return safeGetValue(supplier, null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
public static <T> T safeGetValue(Supplier<T> supplier, T defaultValue) {
|
||||
try {
|
||||
return supplier.get();
|
||||
}
|
||||
catch (Throwable ignore) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.isA;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyVararg;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.search.lucene.LuceneAccessor.LuceneQueryExecutor;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryException;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryFactory;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.junit.Before;
|
||||
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;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.gemfire.search.lucene.support.LuceneAccessorSupport;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LuceneAccessor}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneAccessor
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LuceneAccessorUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private GemFireCache mockCache;
|
||||
|
||||
// SUT
|
||||
private LuceneAccessor luceneAccessor;
|
||||
|
||||
@Mock
|
||||
private LuceneIndex mockLuceneIndex;
|
||||
|
||||
@Mock
|
||||
private LuceneQueryFactory mockLuceneQueryFactory;
|
||||
|
||||
@Mock
|
||||
private LuceneService mockLuceneService;
|
||||
|
||||
@Mock
|
||||
private Region<?, ?> mockRegion;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
luceneAccessor = spy(new LuceneAccessorSupport() { });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetInitializesLuceneAccessorProperly() throws Exception {
|
||||
assertThat(luceneAccessor.getCache()).isNull();
|
||||
assertThat(luceneAccessor.getLuceneService()).isNull();
|
||||
assertThat(luceneAccessor.getIndexName()).isNullOrEmpty();
|
||||
assertThat(luceneAccessor.getRegion()).isNull();
|
||||
assertThat(luceneAccessor.getRegionPath()).isNullOrEmpty();
|
||||
|
||||
doReturn(mockCache).when(luceneAccessor).resolveCache();
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService();
|
||||
doReturn("TestIndex").when(luceneAccessor).resolveIndexName();
|
||||
doReturn("/Example").when(luceneAccessor).resolveRegionPath();
|
||||
|
||||
luceneAccessor.afterPropertiesSet();
|
||||
|
||||
assertThat(luceneAccessor.getCache()).isEqualTo(mockCache);
|
||||
assertThat(luceneAccessor.getLuceneService()).isEqualTo(mockLuceneService);
|
||||
assertThat(luceneAccessor.getIndexName()).isEqualTo("TestIndex");
|
||||
assertThat(luceneAccessor.getRegion()).isNull();
|
||||
assertThat(luceneAccessor.getRegionPath()).isEqualTo("/Example");
|
||||
|
||||
verify(luceneAccessor, times(1)).resolveCache();
|
||||
verify(luceneAccessor, times(1)).resolveLuceneService();
|
||||
verify(luceneAccessor, times(1)).resolveIndexName();
|
||||
verify(luceneAccessor, times(1)).resolveRegionPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createLuceneQueryFactory() {
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService();
|
||||
when(mockLuceneService.createLuceneQueryFactory()).thenReturn(mockLuceneQueryFactory);
|
||||
|
||||
assertThat(luceneAccessor.createLuceneQueryFactory()).isEqualTo(mockLuceneQueryFactory);
|
||||
|
||||
verify(luceneAccessor).resolveLuceneService();
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void createLuceneQueryFactoryWithProjectionFields() {
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService();
|
||||
when(mockLuceneService.createLuceneQueryFactory()).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setPageSize(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setProjectionFields(anyVararg())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setResultLimit(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
|
||||
assertThat(luceneAccessor.createLuceneQueryFactory("fieldOne", "fieldTwo"))
|
||||
.isEqualTo(mockLuceneQueryFactory);
|
||||
|
||||
verify(luceneAccessor).resolveLuceneService();
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setResultLimit(eq(LuceneAccessor.DEFAULT_RESULT_LIMIT));
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setPageSize(eq(LuceneAccessor.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setProjectionFields(eq("fieldOne"), eq("fieldTwo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void createLuceneQueryFactoryWithResultLimitAndProjectionFields() {
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService();
|
||||
when(mockLuceneService.createLuceneQueryFactory()).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setPageSize(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setProjectionFields(anyVararg())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setResultLimit(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
|
||||
assertThat(luceneAccessor.createLuceneQueryFactory(1000, "fieldOne", "fieldTwo"))
|
||||
.isEqualTo(mockLuceneQueryFactory);
|
||||
|
||||
verify(luceneAccessor).resolveLuceneService();
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(1000));
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setPageSize(eq(LuceneAccessor.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setProjectionFields(eq("fieldOne"), eq("fieldTwo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void createLuceneQueryFactoryWithResultLimitPageSizeAndProjectionFields() {
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService();
|
||||
when(mockLuceneService.createLuceneQueryFactory()).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setPageSize(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setProjectionFields(anyVararg())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setResultLimit(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
|
||||
assertThat(luceneAccessor.createLuceneQueryFactory(1000, 20,
|
||||
"fieldOne", "fieldTwo")).isEqualTo(mockLuceneQueryFactory);
|
||||
|
||||
verify(luceneAccessor).resolveLuceneService();
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(1000));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(20));
|
||||
verify(mockLuceneQueryFactory, times(1))
|
||||
.setProjectionFields(eq("fieldOne"), eq("fieldTwo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveCacheReturnsConfiguredCache() {
|
||||
luceneAccessor.setCache(mockCache);
|
||||
|
||||
assertThat(luceneAccessor.getCache()).isSameAs(mockCache);
|
||||
assertThat(luceneAccessor.resolveCache()).isSameAs(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceReturnsConfiguredLuceneService() {
|
||||
luceneAccessor.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(luceneAccessor.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(luceneAccessor.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceLooksUpLuceneService() {
|
||||
doReturn(mockCache).when(luceneAccessor).resolveCache();
|
||||
doReturn(mockLuceneService).when(luceneAccessor).resolveLuceneService(eq(mockCache));
|
||||
|
||||
assertThat(luceneAccessor.getLuceneService()).isNull();
|
||||
assertThat(luceneAccessor.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
verify(luceneAccessor, times(1)).resolveCache();
|
||||
verify(luceneAccessor, times(1)).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceThrowsIllegalArgumentExceptionWhenCacheIsNull() {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("Cache reference was not properly configured");
|
||||
|
||||
luceneAccessor.resolveLuceneService(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveIndexNameReturnsConfiguredIndexName() {
|
||||
luceneAccessor.setIndexName("TestIndex");
|
||||
|
||||
assertThat(luceneAccessor.getIndexName()).isEqualTo("TestIndex");
|
||||
assertThat(luceneAccessor.resolveIndexName()).isEqualTo("TestIndex");
|
||||
|
||||
verify(luceneAccessor, never()).getLuceneIndex();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveIndexNameReturnsLuceneIndexName() {
|
||||
luceneAccessor.setLuceneIndex(mockLuceneIndex);
|
||||
|
||||
when(mockLuceneIndex.getName()).thenReturn("MockIndex");
|
||||
|
||||
assertThat(luceneAccessor.getIndexName()).isNullOrEmpty();
|
||||
assertThat(luceneAccessor.resolveIndexName()).isEqualTo("MockIndex");
|
||||
|
||||
verify(luceneAccessor, times(1)).getLuceneIndex();
|
||||
verify(mockLuceneIndex, times(1)).getName();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveIndexNameThrowsIllegalStateExceptionWhenIndexNameIsUnresolvable() {
|
||||
assertThat(luceneAccessor.getIndexName()).isNullOrEmpty();
|
||||
assertThat(luceneAccessor.getLuceneIndex()).isNull();
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("The name of the Lucene Index could not be resolved");
|
||||
|
||||
luceneAccessor.resolveIndexName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveRegionPathReturnsConfiguredRegionPath() {
|
||||
luceneAccessor.setRegionPath("/Example");
|
||||
|
||||
assertThat(luceneAccessor.getRegionPath()).isEqualTo("/Example");
|
||||
assertThat(luceneAccessor.resolveRegionPath()).isEqualTo("/Example");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionPathReturnsRegionFullPath() {
|
||||
when(mockRegion.getFullPath()).thenReturn("/Example");
|
||||
|
||||
luceneAccessor.setRegion(mockRegion);
|
||||
|
||||
assertThat(luceneAccessor.resolveRegionPath()).isEqualTo("/Example");
|
||||
|
||||
verify(luceneAccessor, times(1)).getRegionPath();
|
||||
verify(luceneAccessor, times(1)).getRegion();
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveRegionPathThrowsIllegalStatueExceptionWhenRegionPathIsUnresolvable() {
|
||||
assertThat(luceneAccessor.getRegion()).isNull();
|
||||
assertThat(luceneAccessor.getRegionPath()).isNullOrEmpty();
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("Region path could not be resolved");
|
||||
|
||||
luceneAccessor.resolveRegionPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doFind() throws LuceneQueryException {
|
||||
LuceneQueryExecutor<String> mockQueryExecutor = mock(LuceneQueryExecutor.class);
|
||||
|
||||
when(mockQueryExecutor.execute()).thenReturn("test");
|
||||
|
||||
assertThat(luceneAccessor.doFind(mockQueryExecutor, "title : 'Up Shit Creek Without a Paddle",
|
||||
"/Example", "ExampleIndex")).isEqualTo("test");
|
||||
|
||||
verify(mockQueryExecutor, times(1)).execute();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void doFindHandlesLuceneQueryException() throws LuceneQueryException {
|
||||
LuceneQueryExecutor<String> mockQueryExecutor = mock(LuceneQueryExecutor.class);
|
||||
|
||||
when(mockQueryExecutor.execute()).thenThrow(new LuceneQueryException("test"));
|
||||
|
||||
try {
|
||||
exception.expect(DataRetrievalFailureException.class);
|
||||
exception.expectCause(isA(LuceneQueryException.class));
|
||||
exception.expectMessage(containsString(
|
||||
"Failed to execute Lucene Query [title : Up Shit Creek Without a Paddle] on Region [/Example] with Lucene Index [ExampleIndex]"));
|
||||
|
||||
luceneAccessor.doFind(mockQueryExecutor, "title : Up Shit Creek Without a Paddle",
|
||||
"/Example", "ExampleIndex");
|
||||
}
|
||||
finally {
|
||||
verify(mockQueryExecutor, times(1)).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void luceneAccessorInitializedCorrectly() {
|
||||
luceneAccessor.setCache(mockCache);
|
||||
luceneAccessor.setIndexName("ExampleIndex");
|
||||
luceneAccessor.setLuceneIndex(mockLuceneIndex);
|
||||
luceneAccessor.setLuceneService(mockLuceneService);
|
||||
luceneAccessor.setRegion(mockRegion);
|
||||
luceneAccessor.setRegionPath("/Example");
|
||||
|
||||
assertThat(luceneAccessor.getCache()).isSameAs(mockCache);
|
||||
assertThat(luceneAccessor.getIndexName()).isEqualTo("ExampleIndex");
|
||||
assertThat(luceneAccessor.getLuceneIndex()).isSameAs(mockLuceneIndex);
|
||||
assertThat(luceneAccessor.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(luceneAccessor.getRegion()).isSameAs(mockRegion);
|
||||
assertThat(luceneAccessor.getRegionPath()).isEqualTo("/Example");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.assertj.core.api.Java6Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.Region;
|
||||
import org.apache.geode.cache.lucene.LuceneIndex;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.junit.Before;
|
||||
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;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LuceneIndexFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LuceneIndexFactoryBeanUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private Analyzer mockAnalyzer;
|
||||
|
||||
@Mock
|
||||
private BeanFactory mockBeanFactory;
|
||||
|
||||
@Mock
|
||||
private GemFireCache mockCache;
|
||||
|
||||
@Mock
|
||||
private LuceneIndex mockLuceneIndex;
|
||||
|
||||
@Mock
|
||||
private LuceneService mockLuceneService;
|
||||
|
||||
@Mock
|
||||
private Region<Object, Object> mockRegion;
|
||||
|
||||
private LuceneIndexFactoryBean factoryBean;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
factoryBean = spy(new LuceneIndexFactoryBean());
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetResolvesCacheLuceneServiceRegionPathAndCreatesLuceneIndex() throws Exception {
|
||||
doReturn(mockCache).when(factoryBean).resolveCache();
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService();
|
||||
doReturn("/Example").when(factoryBean).resolveRegionPath();
|
||||
doReturn(mockLuceneIndex).when(factoryBean).createIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
|
||||
factoryBean.setIndexName("ExampleIndex");
|
||||
|
||||
assertThat(factoryBean.getIndexName()).isEqualTo("ExampleIndex");
|
||||
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
assertThat(factoryBean.getObject()).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(factoryBean, times(1)).resolveCache();
|
||||
verify(factoryBean, times(1)).resolveLuceneService();
|
||||
verify(factoryBean, times(1)).resolveRegionPath();
|
||||
verify(factoryBean, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetThrowsIllegalStateExceptionIndexNameNotSet() throws Exception {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("indexName was not properly initialized");
|
||||
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithAllFields() {
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
when(mockLuceneService.getIndex(eq("ExampleIndex"), eq("/Example"))).thenReturn(mockLuceneIndex);
|
||||
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEmpty();
|
||||
assertThat(factoryBean.getFields()).isEmpty();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq(LuceneService.REGION_VALUE_FIELD));
|
||||
verify(mockLuceneService, times(1))
|
||||
.getIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithFieldAnalyzers() {
|
||||
Map<String, Analyzer> fieldAnalyzers = Collections.singletonMap("fieldOne", mockAnalyzer);
|
||||
|
||||
factoryBean.setFieldAnalyzers(fieldAnalyzers);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
when(mockLuceneService.getIndex(eq("ExampleIndex"), eq("/Example"))).thenReturn(mockLuceneIndex);
|
||||
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEqualTo(fieldAnalyzers);
|
||||
assertThat(factoryBean.getFields()).isEmpty();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq(fieldAnalyzers));
|
||||
verify(mockLuceneService, times(1))
|
||||
.getIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createIndexWithTargetedFields() {
|
||||
factoryBean.setFields("fieldOne", "fieldTwo");
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
when(mockLuceneService.getIndex(eq("ExampleIndex"), eq("/Example"))).thenReturn(mockLuceneIndex);
|
||||
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEmpty();
|
||||
assertThat(factoryBean.getFields()).containsAll(Arrays.asList("fieldOne", "fieldTwo"));
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.createIndex("ExampleIndex", "/Example")).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.createIndex(eq("ExampleIndex"), eq("/Example"), eq("fieldOne"), eq("fieldTwo"));
|
||||
verify(mockLuceneService, times(1))
|
||||
.getIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void destroyIsSuccessful() throws Exception {
|
||||
factoryBean.setDestroy(true);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isTrue();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
doReturn(mockLuceneIndex).when(factoryBean).getObject();
|
||||
|
||||
factoryBean.destroy();
|
||||
|
||||
verify(factoryBean, times(1)).getObject();
|
||||
verify(mockLuceneService, times(1)).destroyIndex(eq(mockLuceneIndex));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void destroyDoesNothingWhenDestroyIsFalse() throws Exception {
|
||||
factoryBean.setDestroy(false);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isFalse();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
doReturn(mockLuceneIndex).when(factoryBean).getObject();
|
||||
|
||||
factoryBean.destroy();
|
||||
|
||||
verify(factoryBean, times(1)).getObject();
|
||||
verify(mockLuceneService, never()).destroyIndex(any(LuceneIndex.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void destroyDoesNothingWhenLuceneIndexIsNull() throws Exception {
|
||||
factoryBean.setDestroy(true);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isTrue();
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
doReturn(null).when(factoryBean).getObject();
|
||||
|
||||
factoryBean.destroy();
|
||||
|
||||
verify(factoryBean, times(1)).getObject();
|
||||
verify(mockLuceneService, never()).destroyIndex(isNull(LuceneIndex.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLuceneIndexDestroyableReturnsTrue() {
|
||||
factoryBean.setDestroy(true);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isTrue();
|
||||
assertThat(factoryBean.isLuceneIndexDestroyable(mockLuceneIndex)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLuceneIndexDestroyableWhenDestroyIsFalseReturnsFalse() {
|
||||
factoryBean.setDestroy(false);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isFalse();
|
||||
assertThat(factoryBean.isLuceneIndexDestroyable(mockLuceneIndex)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isLuceneIndexDestroyableWhenLuceneIndexIsNullReturnsFalse() {
|
||||
factoryBean.setDestroy(true);
|
||||
|
||||
assertThat(factoryBean.isDestroy()).isTrue();
|
||||
assertThat(factoryBean.isLuceneIndexDestroyable(null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsLuceneIndexFromLuceneService() throws Exception {
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.setIndexName("ExampleIndex");
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
factoryBean.setRegionPath("/Example");
|
||||
|
||||
when(mockLuceneService.getIndex(eq("ExampleIndex"), eq("/Example"))).thenReturn(mockLuceneIndex);
|
||||
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getIndexName()).isEqualTo("ExampleIndex");
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.getRegionPath()).isEqualTo("/Example");
|
||||
assertThat(factoryBean.getObject()).isEqualTo(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, times(1))
|
||||
.getIndex(eq("ExampleIndex"), eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsExistingLuceneIndex() throws Exception {
|
||||
factoryBean.setLuceneIndex(mockLuceneIndex);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.getObject()).isSameAs(mockLuceneIndex);
|
||||
|
||||
verify(mockLuceneService, never()).getIndex(anyString(), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectReturnsNullWhenLuceneServiceIsNull() throws Exception {
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.setRegionPath("/Example");
|
||||
|
||||
doReturn(null).when(factoryBean).resolveLuceneService(eq(mockCache));
|
||||
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getLuceneService()).isNull();
|
||||
assertThat(factoryBean.getRegionPath()).isEqualTo("/Example");
|
||||
assertThat(factoryBean.getObject()).isNull();
|
||||
|
||||
verify(factoryBean, times(1)).resolveLuceneService();
|
||||
verify(factoryBean, times(1)).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeBeforeInitialization() {
|
||||
assertThat(factoryBean.getObjectType()).isEqualTo(LuceneIndex.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeAfterInitialization() {
|
||||
assertThat(factoryBean.setLuceneIndex(mockLuceneIndex).getObjectType()).isEqualTo(mockLuceneIndex.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSingletonReturnsTrue() {
|
||||
assertThat(factoryBean.isSingleton()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveCacheReturnsConfiguredCache() {
|
||||
factoryBean.setCache(mockCache);
|
||||
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.resolveCache()).isSameAs(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveFieldsReturnsGivenFields() {
|
||||
List<String> expectedFields = Arrays.asList("fieldOne", "fieldTwo");
|
||||
|
||||
assertThat(factoryBean.resolveFields(expectedFields)).isSameAs(expectedFields);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveFieldsWithEmptyListReturnsAllFields() {
|
||||
assertThat(factoryBean.resolveFields(Collections.emptyList()))
|
||||
.isEqualTo(Collections.singletonList(LuceneService.REGION_VALUE_FIELD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveFieldsWithNullReturnsAllFields() {
|
||||
assertThat(factoryBean.resolveFields(null))
|
||||
.isEqualTo(Collections.singletonList(LuceneService.REGION_VALUE_FIELD));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceReturnsConfiguredLuceneService() {
|
||||
factoryBean.setBeanFactory(mockBeanFactory);
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.getBeanFactory()).isSameAs(mockBeanFactory);
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
verifyZeroInteractions(mockBeanFactory);
|
||||
verifyZeroInteractions(mockCache);
|
||||
verify(factoryBean, never()).resolveLuceneService(any(GemFireCache.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceFromBeanFactory() {
|
||||
factoryBean.setBeanFactory(mockBeanFactory);
|
||||
factoryBean.setCache(mockCache);
|
||||
|
||||
when(mockBeanFactory.getBean(eq(LuceneService.class))).thenReturn(mockLuceneService);
|
||||
|
||||
assertThat(factoryBean.getBeanFactory()).isSameAs(mockBeanFactory);
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getLuceneService()).isNull();
|
||||
assertThat(factoryBean.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
verify(mockBeanFactory, times(1)).getBean(eq(LuceneService.class));
|
||||
verifyZeroInteractions(mockCache);
|
||||
verify(factoryBean, never()).resolveLuceneService(any(GemFireCache.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceFromGemFireCache() {
|
||||
factoryBean.setCache(mockCache);
|
||||
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService(eq(mockCache));
|
||||
|
||||
assertThat(factoryBean.getBeanFactory()).isNull();
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getLuceneService()).isNull();
|
||||
assertThat(factoryBean.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
verifyZeroInteractions(mockCache);
|
||||
verify(factoryBean, times(1)).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void resolveLuceneServiceFromGemFireCacheWithBeanFactoryThrowinBeansException() {
|
||||
factoryBean.setBeanFactory(mockBeanFactory);
|
||||
factoryBean.setCache(mockCache);
|
||||
|
||||
when(mockBeanFactory.getBean(any(Class.class))).thenThrow(new NoSuchBeanDefinitionException("test"));
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService(eq(mockCache));
|
||||
|
||||
assertThat(factoryBean.getBeanFactory()).isSameAs(mockBeanFactory);
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.getLuceneService()).isNull();
|
||||
assertThat(factoryBean.resolveLuceneService()).isSameAs(mockLuceneService);
|
||||
|
||||
verify(mockBeanFactory, times(1)).getBean(eq(LuceneService.class));
|
||||
verifyZeroInteractions(mockCache);
|
||||
verify(factoryBean, times(1)).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveLuceneServiceThrowsIllegalArgumentExceptionWhenGemFireCacheIsNotConfigured() {
|
||||
exception.expect(IllegalArgumentException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("A reference to the GemFireCache was not properly configured");
|
||||
|
||||
factoryBean.resolveLuceneService(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionReturnsConfiguredRegion() {
|
||||
factoryBean.setRegion(mockRegion);
|
||||
|
||||
assertThat(factoryBean.resolveRegion()).isSameAs(mockRegion);
|
||||
|
||||
verify(factoryBean, times(1)).getRegion();
|
||||
verify(factoryBean, never()).resolveCache();
|
||||
verify(factoryBean, never()).getRegionPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionReturnsRegionFromCache() {
|
||||
factoryBean.setRegionPath("/Example");
|
||||
|
||||
doReturn(mockCache).when(factoryBean).resolveCache();
|
||||
when(mockCache.getRegion(eq("/Example"))).thenReturn(mockRegion);
|
||||
|
||||
assertThat(factoryBean.resolveRegion()).isEqualTo(mockRegion);
|
||||
|
||||
verify(factoryBean, times(1)).getRegion();
|
||||
verify(factoryBean, times(1)).resolveCache();
|
||||
verify(factoryBean, times(1)).getRegionPath();
|
||||
verify(mockCache, times(1)).getRegion(eq("/Example"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionReturnsNullWhenCacheNotConfigured() {
|
||||
factoryBean.setRegionPath("/Example");
|
||||
|
||||
doReturn(null).when(factoryBean).resolveCache();
|
||||
|
||||
assertThat(factoryBean.resolveRegion()).isNull();
|
||||
|
||||
verify(factoryBean, times(1)).getRegion();
|
||||
verify(factoryBean, times(1)).resolveCache();
|
||||
verify(factoryBean, times(1)).getRegionPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionReturnsNullWhenRegionPathNotConfigured() {
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.setRegionPath(" ");
|
||||
|
||||
assertThat(factoryBean.resolveRegion()).isNull();
|
||||
|
||||
verify(factoryBean, times(1)).getRegion();
|
||||
verify(factoryBean, times(1)).resolveCache();
|
||||
verify(factoryBean, times(1)).getRegionPath();
|
||||
verify(mockCache, never()).getRegion(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionPathReturnsConfiguredRegionPath() {
|
||||
factoryBean.setRegionPath("/Example");
|
||||
|
||||
doReturn(null).when(factoryBean).resolveRegion();
|
||||
|
||||
assertThat(factoryBean.resolveRegionPath()).isEqualTo("/Example");
|
||||
|
||||
verify(factoryBean, times(1)).resolveRegion();
|
||||
verify(factoryBean, times(1)).getRegionPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionPathReturnsRegionFullPath() {
|
||||
doReturn(mockRegion).when(factoryBean).resolveRegion();
|
||||
when(mockRegion.getFullPath()).thenReturn("/Example");
|
||||
|
||||
assertThat(factoryBean.resolveRegionPath()).isEqualTo("/Example");
|
||||
|
||||
verify(factoryBean, times(1)).resolveRegion();
|
||||
verify(factoryBean, never()).getRegionPath();
|
||||
verify(mockRegion, times(1)).getFullPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("all")
|
||||
public void resolveRegionPathThrowsIllegalStateException() {
|
||||
doReturn(null).when(factoryBean).resolveRegion();
|
||||
|
||||
factoryBean.setRegionPath(null);
|
||||
|
||||
try {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("Either Region or regionPath must be specified");
|
||||
|
||||
factoryBean.resolveRegionPath();
|
||||
}
|
||||
finally {
|
||||
verify(factoryBean, times(1)).resolveRegion();
|
||||
verify(factoryBean, times(1)).getRegionPath();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetFieldAnalyzers() {
|
||||
Map<String, Analyzer> fieldAnalyzers = factoryBean.getFieldAnalyzers();
|
||||
|
||||
assertThat(fieldAnalyzers).isNotNull();
|
||||
assertThat(fieldAnalyzers).isEmpty();
|
||||
|
||||
fieldAnalyzers = Collections.singletonMap("mockField", mockAnalyzer);
|
||||
factoryBean.setFieldAnalyzers(fieldAnalyzers);
|
||||
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEqualTo(fieldAnalyzers);
|
||||
|
||||
factoryBean.setFieldAnalyzers(null);
|
||||
fieldAnalyzers = factoryBean.getFieldAnalyzers();
|
||||
|
||||
assertThat(fieldAnalyzers).isNotNull();
|
||||
assertThat(fieldAnalyzers).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetFields() {
|
||||
List<String> fields = factoryBean.getFields();
|
||||
|
||||
assertThat(fields).isNotNull();
|
||||
assertThat(fields).isEmpty();
|
||||
|
||||
factoryBean.setFields(Arrays.asList("fieldOne", "fieldTwo"));
|
||||
|
||||
assertThat(factoryBean.getFields()).containsAll(Arrays.asList("fieldOne", "fieldTwo"));
|
||||
|
||||
factoryBean.setFields((String[]) null);
|
||||
fields = factoryBean.getFields();
|
||||
|
||||
assertThat(fields).isNotNull();
|
||||
assertThat(fields).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetIndexName() {
|
||||
factoryBean.setBeanName("IndexOne");
|
||||
|
||||
assertThat(factoryBean.getIndexName()).isEqualTo("IndexOne");
|
||||
|
||||
factoryBean.setIndexName("IndexTwo");
|
||||
|
||||
assertThat(factoryBean.getIndexName()).isEqualTo("IndexTwo");
|
||||
|
||||
factoryBean.setIndexName(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUninitializedIndexName() {
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("indexName was not properly initialized");
|
||||
|
||||
factoryBean.getIndexName();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void factoryBeanInitializationIsSuccessful() {
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.setDestroy(true);
|
||||
factoryBean.setFieldAnalyzers(Collections.singletonMap("fieldThree", mockAnalyzer));
|
||||
factoryBean.setFields("fieldOne", "fieldTwo");
|
||||
factoryBean.setIndexName("TestIndex");
|
||||
factoryBean.setLuceneService(mockLuceneService);
|
||||
factoryBean.setRegion(mockRegion);
|
||||
factoryBean.setRegionPath("/Grandparent/Parent/Child");
|
||||
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
assertThat(factoryBean.isDestroy()).isTrue();
|
||||
assertThat(factoryBean.getFieldAnalyzers()).isEqualTo(Collections.singletonMap("fieldThree", mockAnalyzer));
|
||||
assertThat(factoryBean.getFields()).containsAll(Arrays.asList("fieldOne", "fieldTwo"));
|
||||
assertThat(factoryBean.getIndexName()).isEqualTo("TestIndex");
|
||||
assertThat(factoryBean.getLuceneService()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.getRegion()).isSameAs(mockRegion);
|
||||
assertThat(factoryBean.getRegionPath()).isEqualTo("/Grandparent/Parent/Child");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.anyVararg;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link LuceneOperations} interface.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneOperations
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LuceneOperationsUnitTests {
|
||||
|
||||
@Mock
|
||||
private LuceneQueryProvider mockLuceneQueryProvider;
|
||||
|
||||
@Mock
|
||||
private TestLuceneOperations mockLuceneOperations;
|
||||
|
||||
@Test
|
||||
public void stringQueryCallsQueryWithResultLimit() {
|
||||
when(mockLuceneOperations.query(anyString(), anyString(), anyVararg())).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.query("title : Up Shit Creek Without a Paddle", "title",
|
||||
"content");
|
||||
|
||||
verify(mockLuceneOperations, times(1)).query(
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("title"),
|
||||
eq(LuceneOperations.DEFAULT_RESULT_LIMIT), eq("content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryProviderQueryCallsQueryWithResultLimit() {
|
||||
when(mockLuceneOperations.query(any(LuceneQueryProvider.class), anyVararg())).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.query(mockLuceneQueryProvider, "content");
|
||||
|
||||
verify(mockLuceneOperations, times(1)).query(eq(mockLuceneQueryProvider),
|
||||
eq(LuceneOperations.DEFAULT_RESULT_LIMIT), eq("content"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringQueryForKeysCallsQueryForKeysWithResultLimit() {
|
||||
when(mockLuceneOperations.queryForKeys(anyString(), anyString())).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.queryForKeys("title : Up Shit Creek Without a Paddle", "title");
|
||||
|
||||
verify(mockLuceneOperations, times(1)).queryForKeys(
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("title"),
|
||||
eq(LuceneOperations.DEFAULT_RESULT_LIMIT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryProviderQueryForKeysCallsQueryForKeysWithResultLimit() {
|
||||
when(mockLuceneOperations.queryForKeys(any(LuceneQueryProvider.class))).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.queryForKeys(mockLuceneQueryProvider);
|
||||
|
||||
verify(mockLuceneOperations, times(1)).queryForKeys(
|
||||
eq(mockLuceneQueryProvider), eq(LuceneOperations.DEFAULT_RESULT_LIMIT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringQueryForValuesCallsQueryForValuesWithResultLimit() {
|
||||
when(mockLuceneOperations.queryForValues(anyString(), anyString())).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.queryForValues("title : Up Shit Creek Without a Paddle", "title");
|
||||
|
||||
verify(mockLuceneOperations, times(1)).queryForValues(
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("title"),
|
||||
eq(LuceneOperations.DEFAULT_RESULT_LIMIT));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryProviderQueryForValuesCallsQueryForValuesWithResultLimit() {
|
||||
when(mockLuceneOperations.queryForValues(any(LuceneQueryProvider.class))).thenCallRealMethod();
|
||||
|
||||
mockLuceneOperations.queryForValues(mockLuceneQueryProvider);
|
||||
|
||||
verify(mockLuceneOperations, times(1)).queryForValues(
|
||||
eq(mockLuceneQueryProvider), eq(LuceneOperations.DEFAULT_RESULT_LIMIT));
|
||||
}
|
||||
|
||||
abstract class TestLuceneOperations implements LuceneOperations {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static org.assertj.core.api.Java6Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import org.apache.geode.cache.GemFireCache;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.junit.Before;
|
||||
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.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LuceneServiceFactoryBean}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Rule
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneServiceFactoryBean
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LuceneServiceFactoryBeanUnitTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private GemFireCache mockCache;
|
||||
|
||||
@Mock
|
||||
private LuceneService mockLuceneService;
|
||||
|
||||
private LuceneServiceFactoryBean factoryBean;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
factoryBean = spy(new LuceneServiceFactoryBean());
|
||||
doReturn(mockLuceneService).when(factoryBean).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAndGetCache() {
|
||||
assertThat(factoryBean.getCache()).isNull();
|
||||
|
||||
factoryBean.setCache(mockCache);
|
||||
|
||||
assertThat(factoryBean.getCache()).isSameAs(mockCache);
|
||||
|
||||
factoryBean.setCache(null);
|
||||
|
||||
assertThat(factoryBean.getCache()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetInitializesLuceneService() throws Exception {
|
||||
assertThat(factoryBean.getObject()).isNull();
|
||||
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
assertThat(factoryBean.getObject()).isEqualTo(mockLuceneService);
|
||||
|
||||
verify(factoryBean, times(1)).resolveLuceneService(eq(mockCache));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void afterPropertiesSetThrowsIllegalStateExceptionWhenGemFireCacheIsNull() throws Exception {
|
||||
assertThat(factoryBean.getCache()).isNull();
|
||||
|
||||
exception.expect(IllegalStateException.class);
|
||||
exception.expectCause(is(nullValue(Throwable.class)));
|
||||
exception.expectMessage("A reference to the GemFireCache was not properly configured");
|
||||
|
||||
factoryBean.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeBeforeInitialization() throws Exception {
|
||||
assertThat(factoryBean.getObject()).isNull();
|
||||
assertThat(factoryBean.getObjectType()).isEqualTo(LuceneService.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getObjectTypeAfterInitialization() throws Exception {
|
||||
factoryBean.setCache(mockCache);
|
||||
factoryBean.afterPropertiesSet();
|
||||
|
||||
assertThat(factoryBean.getObject()).isSameAs(mockLuceneService);
|
||||
assertThat(factoryBean.getObjectType()).isEqualTo(mockLuceneService.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSingletonReturnsTrue() {
|
||||
assertThat(factoryBean.isSingleton()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright 2016 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.search.lucene;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyInt;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Matchers.isA;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.search.lucene.LuceneAccessor.LuceneQueryExecutor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.geode.cache.lucene.LuceneQuery;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryException;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryFactory;
|
||||
import org.apache.geode.cache.lucene.LuceneQueryProvider;
|
||||
import org.apache.geode.cache.lucene.LuceneResultStruct;
|
||||
import org.apache.geode.cache.lucene.LuceneService;
|
||||
import org.apache.geode.cache.lucene.PageableLuceneQueryResults;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link LuceneTemplate}.
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.Spy
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.search.lucene.LuceneTemplate
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class LuceneTemplateUnitTests {
|
||||
|
||||
@Mock
|
||||
private LuceneQuery<Object, Object> mockLuceneQuery;
|
||||
|
||||
@Mock
|
||||
private LuceneQueryFactory mockLuceneQueryFactory;
|
||||
|
||||
@Mock
|
||||
private LuceneQueryProvider mockLuceneQueryProvider;
|
||||
|
||||
@Mock
|
||||
private LuceneResultStruct<Object, Object> mockLuceneResultStructOne;
|
||||
|
||||
@Mock
|
||||
private LuceneResultStruct<Object, Object> mockLuceneResultStructTwo;
|
||||
|
||||
@Mock
|
||||
private LuceneService mockLuceneService;
|
||||
|
||||
@Mock
|
||||
private PageableLuceneQueryResults<Object, Object> mockPageableLuceneQueryResults;
|
||||
|
||||
@Spy
|
||||
private LuceneTemplate luceneTemplate;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("deprecation")
|
||||
public void setup() {
|
||||
luceneTemplate.setLuceneService(mockLuceneService);
|
||||
|
||||
when(mockLuceneService.createLuceneQueryFactory()).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setPageSize(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setProjectionFields(any())).thenReturn(mockLuceneQueryFactory);
|
||||
when(mockLuceneQueryFactory.setResultLimit(anyInt())).thenReturn(mockLuceneQueryFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void stringQueryReturnsList() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"), anyString(), anyString()))
|
||||
.thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findResults()).thenReturn(asList(mockLuceneResultStructOne, mockLuceneResultStructTwo));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
List<LuceneResultStruct<Object, Object>> results = luceneTemplate.query(
|
||||
"title : Up Shit Creek Without a Paddle", "title", 100,
|
||||
"content");
|
||||
|
||||
assertThat(results).isNotNull();
|
||||
assertThat(results).hasSize(2);
|
||||
assertThat(results).containsAll(asList(mockLuceneResultStructOne, mockLuceneResultStructTwo));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields(eq("content"));
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq("title : Up Shit Creek Without a Paddle"), eq("title"));
|
||||
verify(mockLuceneQuery, times(1)).findResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void stringQueryWithPageSizeReturnsPageableResults() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"), anyString(), anyString()))
|
||||
.thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findPages()).thenReturn(mockPageableLuceneQueryResults);
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
PageableLuceneQueryResults<Object, Object> results = luceneTemplate.query(
|
||||
"title : Up Shit Creek Without a Paddle", "title", 100, 20,
|
||||
"content");
|
||||
|
||||
assertThat(results).isSameAs(mockPageableLuceneQueryResults);
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(20));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields(eq("content"));
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq("title : Up Shit Creek Without a Paddle"), eq("title"));
|
||||
verify(mockLuceneQuery, times(1)).findPages();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void queryProviderQueryReturnsList() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"),
|
||||
any(LuceneQueryProvider.class))).thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findResults()).thenReturn(asList(mockLuceneResultStructOne, mockLuceneResultStructTwo));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
List<LuceneResultStruct<Object, Object>> results = luceneTemplate.query(mockLuceneQueryProvider,
|
||||
100, "content");
|
||||
|
||||
assertThat(results).isNotNull();
|
||||
assertThat(results).hasSize(2);
|
||||
assertThat(results).containsAll(asList(mockLuceneResultStructOne, mockLuceneResultStructTwo));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq(mockLuceneQueryProvider), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields(eq("content"));
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq(mockLuceneQueryProvider));
|
||||
verify(mockLuceneQuery, times(1)).findResults();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void queryProviderQueryWithPageSizeReturnsPageableResults() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"),
|
||||
any(LuceneQueryProvider.class))).thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findPages()).thenReturn(mockPageableLuceneQueryResults);
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
PageableLuceneQueryResults<Object, Object> results = luceneTemplate.query(mockLuceneQueryProvider,
|
||||
100, 20, "content");
|
||||
|
||||
assertThat(results).isSameAs(mockPageableLuceneQueryResults);
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq(mockLuceneQueryProvider), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(20));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields(eq("content"));
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq(mockLuceneQueryProvider));
|
||||
verify(mockLuceneQuery, times(1)).findPages();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void stringQueryForKeysReturnsKeys() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"), anyString(), anyString()))
|
||||
.thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findKeys()).thenReturn(asList("keyOne", "keyTwo"));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
Collection<String> keys = luceneTemplate.queryForKeys(
|
||||
"title : Up Shit Creek Without a Paddle", "title", 100);
|
||||
|
||||
assertThat(keys).isNotNull();
|
||||
assertThat(keys).hasSize(2);
|
||||
assertThat(keys).containsAll(asList("keyOne", "keyTwo"));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields();
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq("title : Up Shit Creek Without a Paddle"), eq("title"));
|
||||
verify(mockLuceneQuery, times(1)).findKeys();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void queryProviderQueryForKeysReturnsKeys() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"),
|
||||
any(LuceneQueryProvider.class))).thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findKeys()).thenReturn(asList("keyOne", "keyTwo"));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
Collection<String> keys = luceneTemplate.queryForKeys(mockLuceneQueryProvider, 100);
|
||||
|
||||
assertThat(keys).isNotNull();
|
||||
assertThat(keys).hasSize(2);
|
||||
assertThat(keys).containsAll(asList("keyOne", "keyTwo"));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq(mockLuceneQueryProvider), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields();
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq(mockLuceneQueryProvider));
|
||||
verify(mockLuceneQuery, times(1)).findKeys();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void stringQueryForValuesReturnsValues() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"), anyString(), anyString()))
|
||||
.thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findValues()).thenReturn(asList("valueOne", "valueTwo"));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
Collection<String> keys = luceneTemplate.queryForValues(
|
||||
"title : Up Shit Creek Without a Paddle", "title", 100);
|
||||
|
||||
assertThat(keys).isNotNull();
|
||||
assertThat(keys).hasSize(2);
|
||||
assertThat(keys).containsAll(asList("valueOne", "valueTwo"));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq("title : Up Shit Creek Without a Paddle"), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields();
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq("title : Up Shit Creek Without a Paddle"), eq("title"));
|
||||
verify(mockLuceneQuery, times(1)).findValues();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings({ "deprecation", "unchecked" })
|
||||
public void queryProviderQueryForValuesReturnsValues() throws LuceneQueryException {
|
||||
when(mockLuceneQueryFactory.create(eq("TestIndex"), eq("/Example"),
|
||||
any(LuceneQueryProvider.class))).thenReturn(mockLuceneQuery);
|
||||
when(mockLuceneQuery.findValues()).thenReturn(asList("valueOne", "valueTwo"));
|
||||
|
||||
doReturn("TestIndex").when(luceneTemplate).resolveIndexName();
|
||||
doReturn("/Example").when(luceneTemplate).resolveRegionPath();
|
||||
|
||||
Collection<String> keys = luceneTemplate.queryForValues(mockLuceneQueryProvider, 100);
|
||||
|
||||
assertThat(keys).isNotNull();
|
||||
assertThat(keys).hasSize(2);
|
||||
assertThat(keys).containsAll(asList("valueOne", "valueTwo"));
|
||||
|
||||
verify(luceneTemplate, times(1)).resolveIndexName();
|
||||
verify(luceneTemplate, times(1)).resolveRegionPath();
|
||||
verify(luceneTemplate, times(1)).doFind(isA(LuceneQueryExecutor.class),
|
||||
eq(mockLuceneQueryProvider), eq("/Example"), eq("TestIndex"));
|
||||
verify(mockLuceneService, times(1)).createLuceneQueryFactory();
|
||||
verify(mockLuceneQueryFactory, times(1)).setResultLimit(eq(100));
|
||||
verify(mockLuceneQueryFactory, times(1)).setPageSize(eq(LuceneOperations.DEFAULT_PAGE_SIZE));
|
||||
verify(mockLuceneQueryFactory, times(1)).setProjectionFields();
|
||||
verify(mockLuceneQueryFactory, times(1)).create(eq("TestIndex"),
|
||||
eq("/Example"), eq(mockLuceneQueryProvider));
|
||||
verify(mockLuceneQuery, times(1)).findValues();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newRuntimeException;
|
||||
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newUnsupportedOperationException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,7 +36,7 @@ import org.mockito.junit.MockitoJUnitRunner;
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.util.RuntimeExceptionFactory
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@@ -88,4 +89,15 @@ public class RuntimeExceptionFactoryUnitTests {
|
||||
assertThrowable(newRuntimeException(mockCause, "%1$s is a {1}", "This", "test"),
|
||||
RuntimeException.class, "This is a test", mockCause);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newUnsupportedOperationExceptionWithMessage() {
|
||||
assertThrowable(newUnsupportedOperationException("test"), UnsupportedOperationException.class, "test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newUnsupportedOperationExceptionWithFormattedMessageAndCause() {
|
||||
assertThrowable(newUnsupportedOperationException(mockCause, "%1$s is a {1}", "This", "test"),
|
||||
UnsupportedOperationException.class, "This is a test", mockCause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,15 @@
|
||||
|
||||
package org.springframework.data.gemfire.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.data.gemfire.util.ArrayUtils.asArray;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -31,9 +38,10 @@ import org.springframework.beans.factory.config.BeanDefinition;
|
||||
*
|
||||
* @author John Blum
|
||||
* @see org.junit.Test
|
||||
* @see org.junit.runner.RunWith
|
||||
* @see org.mockito.Mock
|
||||
* @see org.mockito.Mockito
|
||||
* @see org.mockito.runners.MockitoJUnitRunner
|
||||
* @see org.mockito.junit.MockitoJUnitRunner
|
||||
* @see org.springframework.data.gemfire.util.SpringUtils
|
||||
* @since 1.9.0
|
||||
*/
|
||||
@@ -45,20 +53,37 @@ public class SpringUtilsUnitTests {
|
||||
|
||||
@Test
|
||||
public void addDependsOnToExistingDependencies() {
|
||||
when(mockBeanDefinition.getDependsOn()).thenReturn(ArrayUtils.asArray("testBeanNameOne", "testBeanNameTwo"));
|
||||
when(mockBeanDefinition.getDependsOn()).thenReturn(asArray("testBeanNameOne", "testBeanNameTwo"));
|
||||
|
||||
assertThat(SpringUtils.addDependsOn(mockBeanDefinition, "testBeanNameThree")).isSameAs(mockBeanDefinition);
|
||||
|
||||
verify(mockBeanDefinition, times(1)).getDependsOn();
|
||||
verify(mockBeanDefinition, times(1)).setDependsOn("testBeanNameOne", "testBeanNameTwo", "testBeanNameThree");
|
||||
verify(mockBeanDefinition, times(1))
|
||||
.setDependsOn("testBeanNameOne", "testBeanNameTwo", "testBeanNameThree");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDependsOnToNonExistingDependencies() {
|
||||
when(mockBeanDefinition.getDependsOn()).thenReturn(null);
|
||||
|
||||
assertThat(SpringUtils.addDependsOn(mockBeanDefinition, "testBeanName")).isSameAs(mockBeanDefinition);
|
||||
|
||||
verify(mockBeanDefinition, times(1)).getDependsOn();
|
||||
verify(mockBeanDefinition, times(1)).setDependsOn("testBeanName");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addDependsOnWithMultipleDependenciesWithExistingDependencies() {
|
||||
when(mockBeanDefinition.getDependsOn()).thenReturn(asArray("testBeanNameOne", "testBeanNameTwo"));
|
||||
|
||||
assertThat(SpringUtils.addDependsOn(mockBeanDefinition, "testBeanNameThree", "testBeanNameFour"))
|
||||
.isSameAs(mockBeanDefinition);
|
||||
|
||||
verify(mockBeanDefinition, times(1)).getDependsOn();
|
||||
verify(mockBeanDefinition, times(1))
|
||||
.setDependsOn("testBeanNameOne", "testBeanNameTwo", "testBeanNameThree", "testBeanNameFour");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void defaultIfEmptyReturnsValue() {
|
||||
assertThat(SpringUtils.defaultIfEmpty("test", "DEFAULT")).isEqualTo("test");
|
||||
@@ -96,6 +121,33 @@ public class SpringUtilsUnitTests {
|
||||
assertThat(SpringUtils.defaultIfNull(null, "DEFAULT")).isEqualTo("DEFAULT");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void defaultIfNullWithSupplierReturnsValue() {
|
||||
Supplier<String> mockSupplier = mock(Supplier.class);
|
||||
|
||||
assertThat(SpringUtils.defaultIfNull("value", mockSupplier)).isEqualTo("value");
|
||||
|
||||
verify(mockSupplier, never()).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void defaultIfNullWithSupplierReturnsSupplierValue() {
|
||||
Supplier<String> mockSupplier = mock(Supplier.class);
|
||||
|
||||
when(mockSupplier.get()).thenReturn("supplier");
|
||||
|
||||
assertThat(SpringUtils.defaultIfNull(null, mockSupplier)).isEqualTo("supplier");
|
||||
|
||||
verify(mockSupplier, times(1)).get();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dereferenceBean() {
|
||||
assertThat(SpringUtils.dereferenceBean("example")).isEqualTo("&example");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equalsIgnoreNullIsTrue() {
|
||||
assertThat(SpringUtils.equalsIgnoreNull(null, null)).isTrue();
|
||||
@@ -118,13 +170,18 @@ public class SpringUtilsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullOrEqualsWithNullIsTrue() {
|
||||
assertThat(SpringUtils.nullOrEquals(null, "test")).isTrue();
|
||||
public void nullOrEqualsWithEqualObjectsIsTrue() {
|
||||
assertThat(SpringUtils.nullOrEquals("test", "test")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullOrEqualsWithEqualObjectsIsTrue() {
|
||||
assertThat(SpringUtils.nullOrEquals("test", "test")).isTrue();
|
||||
public void nullOrEqualsWithNonNullObjectAndNullIsFalse() {
|
||||
assertThat(SpringUtils.nullOrEquals("test", null)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullOrEqualsWithNullIsTrue() {
|
||||
assertThat(SpringUtils.nullOrEquals(null, "test")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -137,11 +194,6 @@ public class SpringUtilsUnitTests {
|
||||
assertThat(SpringUtils.nullSafeEquals("test", "test")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeEqualsWithUnequalObjectsIsFalse() {
|
||||
assertThat(SpringUtils.nullSafeEquals("test", "mock")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullSafeEqualsWithNullObjectsIsFalse() {
|
||||
assertThat(SpringUtils.nullSafeEquals(null, "test")).isFalse();
|
||||
@@ -149,7 +201,23 @@ public class SpringUtilsUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dereferenceBean() {
|
||||
assertThat(SpringUtils.dereferenceBean("example")).isEqualTo("&example");
|
||||
public void nullSafeEqualsWithUnequalObjectsIsFalse() {
|
||||
assertThat(SpringUtils.nullSafeEquals("test", "mock")).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeGetValueReturnsSupplierValue() {
|
||||
assertThat(SpringUtils.safeGetValue(() -> "test", null)).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeGetValueReturnsDefaultValue() {
|
||||
assertThat(SpringUtils.safeGetValue(() -> { throw new RuntimeException("error"); }, "test"))
|
||||
.isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void safeGetValueReturnsNull() {
|
||||
assertThat(SpringUtils.<Object>safeGetValue(() -> { throw new RuntimeException("error"); })).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user