SGF-402 - Add Lucene Integration support.

(cherry picked from commit f104d5752725469837254e7dda773539505a26c4)
Signed-off-by: John Blum <jblum@pivotal.io>
This commit is contained in:
John Blum
2017-03-08 15:17:36 -08:00
parent d20f3b6667
commit d914820272
23 changed files with 3659 additions and 33 deletions

View File

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

View File

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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

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

View File

@@ -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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -124,4 +124,8 @@ public abstract class CacheUtils extends DistributedSystemUtils {
return null;
}
}
public static GemFireCache resolveGemFireCache() {
return defaultIfNull(getCache(), CacheUtils::getClientCache);
}
}

View File

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

View File

@@ -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;
}
}
}