diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/AbstractRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/AbstractRegionParser.java index 92265a90..4a8f28a1 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/AbstractRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/AbstractRegionParser.java @@ -31,7 +31,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedArray; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.data.gemfire.GemfireUtils; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; @@ -111,8 +110,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { } ParsingUtils.setPropertyValue(element, regionBuilder, "name"); - ParsingUtils.setPropertyValue(element, regionBuilder, "ignore-if-exists", "lookupEnabled"); ParsingUtils.setPropertyValue(element, regionBuilder, "data-policy"); + ParsingUtils.setPropertyValue(element, regionBuilder, "ignore-if-exists", "lookupEnabled"); ParsingUtils.setPropertyValue(element, regionBuilder, "persistent"); ParsingUtils.setPropertyValue(element, regionBuilder, "shortcut"); @@ -121,37 +120,13 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { regionBuilder.addDependsOn(element.getAttribute("disk-store-ref")); } - ParsingUtils.parseOptionalRegionAttributes(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseSubscription(parserContext, element, regionAttributesBuilder); + ParsingUtils.parseOptionalRegionAttributes(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseSubscription(element, parserContext, regionAttributesBuilder); ParsingUtils.parseStatistics(element, regionAttributesBuilder); - ParsingUtils.parseMembershipAttributes(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseExpiration(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseEviction(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseCompressor(parserContext, element, regionAttributesBuilder); - - String enableGateway = element.getAttribute("enable-gateway"); - String hubId = element.getAttribute("hub-id"); - - // Factory will enable gateway if it is not set and hub-id is set. - if (StringUtils.hasText(enableGateway)) { - if (GemfireUtils.isGemfireVersion7OrAbove()) { - log.warn("'enable-gateway' has been deprecated since Gemfire 7.0"); - } - } - - ParsingUtils.setPropertyValue(element, regionBuilder, "enable-gateway"); - - if (StringUtils.hasText(hubId)) { - if (GemfireUtils.isGemfireVersion7OrAbove()) { - log.warn("'hub-id' has been deprecated since Gemfire 7.0"); - } - if (!CollectionUtils.isEmpty(DomUtils.getChildElementsByTagName(element, "gateway-sender"))) { - parserContext.getReaderContext().error("specifying both 'hub-id' and 'gateway-sender' is invalid", - element); - } - } - - ParsingUtils.setPropertyValue(element, regionBuilder, "hub-id"); + ParsingUtils.parseMembershipAttributes(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseExpiration(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseEviction(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseCompressor(element, parserContext, regionAttributesBuilder); parseCollectionOfCustomSubElements(element, parserContext, regionBuilder, AsyncEventQueue.class.getName(), "async-event-queue", "asyncEventQueues"); @@ -164,15 +139,15 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { for (Element subElement : subElements) { if (subElement.getLocalName().equals("cache-listener")) { regionBuilder.addPropertyValue("cacheListeners", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } else if (subElement.getLocalName().equals("cache-loader")) { regionBuilder.addPropertyValue("cacheLoader", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } else if (subElement.getLocalName().equals("cache-writer")) { regionBuilder.addPropertyValue("cacheWriter", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } } @@ -233,7 +208,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { ManagedArray array = new ManagedArray(className, subElements.size()); for (Element subElement : subElements) { - array.add(ParsingUtils.parseRefOrNestedCustomElement(parserContext, subElement, builder)); + array.add(ParsingUtils.parseRefOrNestedCustomElement(subElement, parserContext, builder)); } builder.addPropertyValue(propertyName, array); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/AsyncEventQueueParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/AsyncEventQueueParser.java index 80bc5576..411e098b 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/AsyncEventQueueParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/AsyncEventQueueParser.java @@ -96,8 +96,9 @@ class AsyncEventQueueParser extends AbstractSingleBeanDefinitionParser { private void parseAsyncEventListener(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { Element asyncEventListenerElement = DomUtils.getChildElementByTagName(element, "async-event-listener"); - Object asyncEventListener = ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext, - asyncEventListenerElement, builder); + Object asyncEventListener = ParsingUtils.parseRefOrSingleNestedBeanDeclaration(asyncEventListenerElement, + parserContext, + builder); builder.addPropertyValue("asyncEventListener", asyncEventListener); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/CacheParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/CacheParser.java index af26c7c4..cd278496 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/CacheParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/CacheParser.java @@ -93,7 +93,7 @@ class CacheParser extends AbstractSingleBeanDefinitionParser { for (Element txListener : txListeners) { transactionListeners.add(ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, txListener, builder)); + txListener, parserContext, builder)); } builder.addPropertyValue("transactionListeners", transactionListeners); @@ -103,7 +103,7 @@ class CacheParser extends AbstractSingleBeanDefinitionParser { if (txWriter != null) { builder.addPropertyValue("transactionWriter", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, txWriter, builder)); + txWriter, parserContext, builder)); } Element gatewayConflictResolver = DomUtils.getChildElementByTagName(element, "gateway-conflict-resolver"); @@ -111,7 +111,7 @@ class CacheParser extends AbstractSingleBeanDefinitionParser { if (gatewayConflictResolver != null) { ParsingUtils.throwExceptionIfNotGemfireV7(element.getLocalName(), "gateway-conflict-resolver", parserContext); builder.addPropertyValue("gatewayConflictResolver", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, gatewayConflictResolver, builder)); + gatewayConflictResolver, parserContext, builder)); } parseDynamicRegionFactory(element, builder); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/ClientRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/ClientRegionParser.java index 62d7fd5b..724c4bee 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/ClientRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/ClientRegionParser.java @@ -84,11 +84,11 @@ class ClientRegionParser extends AbstractRegionParser { mergeRegionTemplateAttributes(element, parserContext, regionBuilder, regionAttributesBuilder); - ParsingUtils.parseOptionalRegionAttributes(parserContext, element, regionAttributesBuilder); + ParsingUtils.parseOptionalRegionAttributes(element, parserContext, regionAttributesBuilder); ParsingUtils.parseStatistics(element, regionAttributesBuilder); - ParsingUtils.parseExpiration(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseEviction(parserContext, element, regionAttributesBuilder); - ParsingUtils.parseCompressor(parserContext, element, regionAttributesBuilder); + ParsingUtils.parseExpiration(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseEviction(element, parserContext, regionAttributesBuilder); + ParsingUtils.parseCompressor(element, parserContext, regionAttributesBuilder); regionBuilder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition()); @@ -101,15 +101,15 @@ class ClientRegionParser extends AbstractRegionParser { if ("cache-listener".equals(subElementLocalName)) { regionBuilder.addPropertyValue("cacheListeners", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } else if ("cache-loader".equals(subElementLocalName)) { regionBuilder.addPropertyValue("cacheLoader", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } else if ("cache-writer".equals(subElementLocalName)) { regionBuilder.addPropertyValue("cacheWriter", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, subElement, regionBuilder)); + subElement, parserContext, regionBuilder)); } else if ("key-interest".equals(subElementLocalName)) { interests.add(parseKeyInterest(subElement, parserContext)); @@ -149,8 +149,9 @@ class ClientRegionParser extends AbstractRegionParser { private Object parseKeyInterest(Element keyInterestElement, ParserContext parserContext) { BeanDefinitionBuilder keyInterestBuilder = BeanDefinitionBuilder.genericBeanDefinition(KeyInterest.class); - keyInterestBuilder.addConstructorArgValue(ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, - keyInterestElement, keyInterestBuilder, "key-ref")); + keyInterestBuilder.addConstructorArgValue(ParsingUtils.parseRefOrNestedBeanDeclaration(keyInterestElement, + parserContext, + keyInterestBuilder, "key-ref")); parseCommonInterestAttributes(keyInterestElement, keyInterestBuilder); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/FunctionServiceParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/FunctionServiceParser.java index 43a30115..94dcf867 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/FunctionServiceParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/FunctionServiceParser.java @@ -57,7 +57,7 @@ class FunctionServiceParser extends AbstractSimpleBeanDefinitionParser { if (functionElement != null) { builder.addPropertyValue("functions", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, functionElement, builder)); + functionElement, parserContext, builder)); } } diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/GatewaySenderParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/GatewaySenderParser.java index 00f57f01..07a764ff 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/GatewaySenderParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/GatewaySenderParser.java @@ -75,14 +75,14 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser { if (eventFilterElement != null) { builder.addPropertyValue("eventFilters", ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, eventFilterElement, builder)); + eventFilterElement, parserContext, builder)); } Element eventSubstitutionFilterElement = DomUtils.getChildElementByTagName(element, "event-substitution-filter"); if (eventSubstitutionFilterElement != null) { builder.addPropertyValue("eventSubstitutionFilter", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, eventSubstitutionFilterElement, builder)); + eventSubstitutionFilterElement, parserContext, builder)); } ParsingUtils.parseTransportFilters(element, parserContext, builder); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/GemfireNamespaceHandler.java b/src/main/java/org/springframework/data/gemfire/config/xml/GemfireNamespaceHandler.java index 6038b781..599b9fb3 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/GemfireNamespaceHandler.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/GemfireNamespaceHandler.java @@ -49,6 +49,8 @@ class GemfireNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("local-region", new LocalRegionParser()); registerBeanDefinitionParser("local-region-template", new LocalRegionParser()); registerBeanDefinitionParser("lookup-region", new LookupRegionParser()); + registerBeanDefinitionParser("lucene-index", new LuceneIndexParser()); + registerBeanDefinitionParser("lucene-service", new LuceneServiceParser()); registerBeanDefinitionParser("partitioned-region", new PartitionedRegionParser()); registerBeanDefinitionParser("partitioned-region-template", new PartitionedRegionParser()); registerBeanDefinitionParser("pool", new PoolParser()); diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/LookupRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/LookupRegionParser.java index 2c7dff69..900b8a73 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/LookupRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/LookupRegionParser.java @@ -60,7 +60,7 @@ class LookupRegionParser extends AbstractRegionParser { ParsingUtils.setPropertyValue(element, builder, "cloning-enabled"); ParsingUtils.setPropertyValue(element, builder, "eviction-maximum"); ParsingUtils.setPropertyValue(element, builder, "name"); - ParsingUtils.parseExpiration(parserContext, element, builder); + ParsingUtils.parseExpiration(element, parserContext, builder); parseCollectionOfCustomSubElements(element, parserContext, builder, AsyncEventQueue.class.getName(), "async-event-queue", "asyncEventQueues"); @@ -71,22 +71,23 @@ class LookupRegionParser extends AbstractRegionParser { Element cacheListenerElement = DomUtils.getChildElementByTagName(element, "cache-listener"); if (cacheListenerElement != null) { - builder.addPropertyValue("cacheListeners", ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, - cacheListenerElement, builder)); + builder.addPropertyValue("cacheListeners", ParsingUtils.parseRefOrNestedBeanDeclaration( + cacheListenerElement, parserContext, + builder)); } Element cacheLoaderElement = DomUtils.getChildElementByTagName(element, "cache-loader"); if (cacheLoaderElement != null) { builder.addPropertyValue("cacheLoader", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, cacheLoaderElement, builder)); + cacheLoaderElement, parserContext, builder)); } Element cacheWriterElement = DomUtils.getChildElementByTagName(element, "cache-writer"); if (cacheWriterElement != null) { builder.addPropertyValue("cacheWriter", ParsingUtils.parseRefOrSingleNestedBeanDeclaration( - parserContext, cacheWriterElement, builder)); + cacheWriterElement, parserContext, builder)); } if (!subRegion) { diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/LuceneIndexParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/LuceneIndexParser.java new file mode 100644 index 00000000..a7078b31 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/xml/LuceneIndexParser.java @@ -0,0 +1,74 @@ +/* + * 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.config.xml; + +import java.util.Arrays; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; + +/** + * Spring XML {@link AbstractSingleBeanDefinitionParser parser} for the {@link LuceneIndexFactoryBean} bean definition. + * + * @author John Blum + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder + * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser + * @see org.springframework.data.gemfire.search.lucene.LuceneIndexFactoryBean + * @since 1.1.0 + */ +class LuceneIndexParser extends AbstractSingleBeanDefinitionParser { + + /** + * @inheritDoc + */ + @Override + protected Class getBeanClass(Element element) { + return LuceneIndexFactoryBean.class; + } + + /** + * @inheritDoc + */ + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + super.doParse(element, parserContext, builder); + + ParsingUtils.setCacheReference(element, builder); + ParsingUtils.setPropertyValue(element, builder, "name", "indexName"); + ParsingUtils.setPropertyValue(element, builder, "destroy"); + ParsingUtils.setPropertyReference(element, builder, "lucene-service-ref", "luceneService"); + ParsingUtils.setPropertyReference(element, builder, "region-ref", "region"); + ParsingUtils.setPropertyValue(element, builder, "region-path"); + + Optional.ofNullable(element.getAttribute("fields")).filter(StringUtils::hasText).ifPresent((fields) -> { + builder.addPropertyValue("fields", Arrays.stream(fields.split(",")) + .map(String::trim).collect(Collectors.toList())); + }); + + Optional.ofNullable(DomUtils.getChildElementByTagName(element, "field-analyzers")) + .ifPresent((fieldAnalyzersElement) -> builder.addPropertyValue("fieldAnalyzers", + ParsingUtils.parseRefOrSingleNestedBeanDeclaration(fieldAnalyzersElement, parserContext, builder))); + } +} diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/LuceneServiceParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/LuceneServiceParser.java new file mode 100644 index 00000000..dfe92182 --- /dev/null +++ b/src/main/java/org/springframework/data/gemfire/config/xml/LuceneServiceParser.java @@ -0,0 +1,52 @@ +/* + * 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.config.xml; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.data.gemfire.search.lucene.LuceneServiceFactoryBean; +import org.w3c.dom.Element; + +/** + * Spring XML {@link AbstractSingleBeanDefinitionParser parser} for a {@link LuceneServiceFactoryBean} bean definition. + * + * @author John Blum + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder + * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser + * @see org.springframework.data.gemfire.search.lucene.LuceneServiceFactoryBean + * @since 1.1.0 + */ +class LuceneServiceParser extends AbstractSingleBeanDefinitionParser { + + /** + * @inheritDoc + */ + @Override + protected Class getBeanClass(Element element) { + return LuceneServiceFactoryBean.class; + } + + /** + * @inheritDoc + */ + @Override + protected void doParse(Element element, BeanDefinitionBuilder builder) { + super.doParse(element, builder); + ParsingUtils.setCacheReference(element, builder); + } +} diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java b/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java index 5fd6e29e..1c74b884 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/ParsingUtils.java @@ -40,12 +40,21 @@ import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; /** - * Utilities used by the Spring Data GemFire XML Namespace parsers. + * Utilities used by the Spring Data GemFire XML Namespace Parsers. * * @author Costin Leau * @author David Turanski * @author Lyndon Adams * @author John Blum + * @see org.springframework.beans.factory.config.BeanDefinition + * @see org.springframework.beans.factory.config.RuntimeBeanReference + * @see org.springframework.beans.factory.support.BeanDefinitionBuilder + * @see org.springframework.beans.factory.support.ManagedList + * @see org.springframework.beans.factory.xml.ParserContext + * @see org.springframework.core.Conventions + * @see org.springframework.util.xml.DomUtils + * @see org.w3c.dom.Element + * @since 1.0.0 */ abstract class ParsingUtils { @@ -111,30 +120,8 @@ abstract class ParsingUtils { setPropertyValue(builder, source, propertyName, false); } - /** - * Utility method handling parsing of nested definition of the type: - * - *
-	 *   
-	 * 
- * - * or - * - *
-	 *   
-	 *     
-	 *   
-	 * 
- * - * @param element the XML element. - * @return Bean reference or nested Bean definition. - */ - static Object parseRefOrNestedBeanDeclaration(ParserContext parserContext, Element element, - BeanDefinitionBuilder builder) { - return parseRefOrNestedBeanDeclaration(parserContext, element, builder, "ref", false); - } + static Object getBeanReference(Element element, ParserContext parserContext, String refAttributeName) { - static Object getBeanReference(ParserContext parserContext, Element element, String refAttributeName) { String refAttributeValue = element.getAttribute(refAttributeName); Object returnValue = null; @@ -151,27 +138,61 @@ abstract class ParsingUtils { return returnValue; } - static Object parseRefOrNestedCustomElement(ParserContext parserContext, Element element, + static Object parseRefOrNestedCustomElement(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - Object beanRef = ParsingUtils.getBeanReference(parserContext, element, "bean"); + + Object beanRef = ParsingUtils.getBeanReference(element, parserContext, "bean"); + return (beanRef != null ? beanRef : parserContext.getDelegate().parseCustomElement( element, builder.getBeanDefinition())); } - static Object parseRefOrSingleNestedBeanDeclaration(ParserContext parserContext, Element element, + /** + * Utility method handling parsing of nested bean definition of the type: + * + *
+	 *   
+	 * 
+ * + * or + * + *
+	 *   
+	 *     
+	 *   
+	 * 
+ * + * @param element the XML element. + * @return Bean reference or nested Bean definition. + */ + static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - return parseRefOrNestedBeanDeclaration(parserContext, element, builder, "ref", true); + + return parseRefOrNestedBeanDeclaration(element, parserContext, builder, "ref", false); } - static Object parseRefOrNestedBeanDeclaration(ParserContext parserContext, Element element, + static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, String refAttributeName) { - return parseRefOrNestedBeanDeclaration(parserContext, element, builder, refAttributeName, false); + + return parseRefOrNestedBeanDeclaration(element, parserContext, builder, refAttributeName, false); } - static Object parseRefOrNestedBeanDeclaration(ParserContext parserContext, Element element, + static Object parseRefOrSingleNestedBeanDeclaration(Element element, ParserContext parserContext, + BeanDefinitionBuilder builder) { + + return parseRefOrNestedBeanDeclaration(element, parserContext, builder, "ref", true); + } + + static Object parseRefOrSingleNestedBeanDeclaration(Element element, ParserContext parserContext, + BeanDefinitionBuilder builder, String refAttributeName) { + + return parseRefOrNestedBeanDeclaration(element, parserContext, builder, refAttributeName, true); + } + + static Object parseRefOrNestedBeanDeclaration(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, String refAttributeName, boolean single) { - Object beanReference = getBeanReference(parserContext, element, refAttributeName); + Object beanReference = getBeanReference(element, parserContext, refAttributeName); if (beanReference != null) { return beanReference; @@ -182,8 +203,8 @@ abstract class ParsingUtils { // parse nested bean definition if (childElements.size() == 1) { - return parserContext.getDelegate().parsePropertySubElement(childElements.get(0), - builder.getRawBeanDefinition()); + return parserContext.getDelegate().parsePropertySubElement( + childElements.get(0), builder.getRawBeanDefinition()); } else { // TODO also triggered when there are no child elements; need to change the message... @@ -194,7 +215,7 @@ abstract class ParsingUtils { } } - ManagedList list = new ManagedList(); + ManagedList list = new ManagedList<>(); for (Element childElement : childElements) { list.add(parserContext.getDelegate().parsePropertySubElement(childElement, builder.getRawBeanDefinition())); @@ -206,12 +227,12 @@ abstract class ParsingUtils { /** * Parses the eviction sub-element. Populates the given attribute factory with the proper attributes. * - * @param parserContext the context used for parsing the XML document. * @param element the XML elements being parsed. + * @param parserContext the context used for parsing the XML document. * @param regionAttributesBuilder the Region Attributes builder. * @return true if parsing actually occurred, false otherwise. */ - static boolean parseEviction(ParserContext parserContext, Element element, + static boolean parseEviction(Element element, ParserContext parserContext, BeanDefinitionBuilder regionAttributesBuilder) { Element evictionElement = DomUtils.getChildElementByTagName(element, "eviction"); @@ -227,7 +248,7 @@ abstract class ParsingUtils { Element objectSizerElement = DomUtils.getChildElementByTagName(evictionElement, "object-sizer"); if (objectSizerElement != null) { - Object sizer = parseRefOrNestedBeanDeclaration(parserContext, objectSizerElement, + Object sizer = parseRefOrNestedBeanDeclaration(objectSizerElement, parserContext, evictionAttributesBuilder); evictionAttributesBuilder.addPropertyValue("objectSizer", sizer); } @@ -244,14 +265,14 @@ abstract class ParsingUtils { /** * Parses the subscription sub-element. Populates the given attribute factory with the proper attributes. * - * @param parserContext the context used while parsing the XML document. * @param element the XML element being parsed. + * @param parserContext the context used while parsing the XML document. * @param regionAttributesBuilder the Region Attributes builder. * @return true if parsing actually occurred, false otherwise. */ @SuppressWarnings("unused") - static boolean parseSubscription(ParserContext parserContext, Element element, - BeanDefinitionBuilder regionAttributesBuilder) { + static boolean parseSubscription(Element element, ParserContext parserContext, + BeanDefinitionBuilder regionAttributesBuilder) { Element subscriptionElement = DomUtils.getChildElementByTagName(element, "subscription"); @@ -274,8 +295,9 @@ abstract class ParsingUtils { Element transportFilterElement = DomUtils.getChildElementByTagName(element, "transport-filter"); if (transportFilterElement != null) { - builder.addPropertyValue("transportFilters", parseRefOrNestedBeanDeclaration(parserContext, - transportFilterElement, builder)); + builder.addPropertyValue("transportFilters", parseRefOrNestedBeanDeclaration(transportFilterElement, + parserContext, + builder)); } } @@ -286,13 +308,13 @@ abstract class ParsingUtils { /** * Parses the expiration sub-elements. Populates the given attribute factory with proper attributes. * - * @param parserContext the context used while parsing the XML document. * @param element the XML element being parsed. + * @param parserContext the context used while parsing the XML document. * @param regionAttributesBuilder the Region Attributes builder. * @return a boolean indicating whether Region expiration attributes were specified. */ - static boolean parseExpiration(ParserContext parserContext, Element element, - BeanDefinitionBuilder regionAttributesBuilder) { + static boolean parseExpiration(Element element, ParserContext parserContext, + BeanDefinitionBuilder regionAttributesBuilder) { boolean result = parseExpiration(element, "region-ttl", "regionTimeToLive", regionAttributesBuilder); @@ -313,8 +335,8 @@ abstract class ParsingUtils { } @SuppressWarnings("unused") - static void parseOptionalRegionAttributes(ParserContext parserContext, Element element, - BeanDefinitionBuilder regionAttributesBuilder) { + static void parseOptionalRegionAttributes(Element element, ParserContext parserContext, + BeanDefinitionBuilder regionAttributesBuilder) { setPropertyValue(element, regionAttributesBuilder, "cloning-enabled"); setPropertyValue(element, regionAttributesBuilder, "concurrency-level"); @@ -343,8 +365,8 @@ abstract class ParsingUtils { } } - @SuppressWarnings("unused") - static void parseMembershipAttributes(ParserContext parserContext, Element element, + @SuppressWarnings({ "deprecation", "unused" }) + static void parseMembershipAttributes(Element element, ParserContext parserContext, BeanDefinitionBuilder regionAttributesBuilder) { Element membershipAttributes = DomUtils.getChildElementByTagName(element, "membership-attributes"); @@ -410,26 +432,29 @@ abstract class ParsingUtils { private static boolean parseCustomExpiration(Element rootElement, ParserContext parserContext, String elementName, String propertyName, BeanDefinitionBuilder regionAttributesBuilder) { + Element expirationElement = DomUtils.getChildElementByTagName(rootElement, elementName); if (expirationElement != null) { - Object customExpiry = parseRefOrSingleNestedBeanDeclaration(parserContext, expirationElement, - regionAttributesBuilder); + Object customExpiry = + parseRefOrSingleNestedBeanDeclaration(expirationElement, parserContext, regionAttributesBuilder); + regionAttributesBuilder.addPropertyValue(propertyName, customExpiry); + return true; } return false; } - static void parseCompressor(ParserContext parserContext, Element element, + static void parseCompressor(Element element, ParserContext parserContext, BeanDefinitionBuilder regionAttributesBuilder) { Element compressorElement = DomUtils.getChildElementByTagName(element, "compressor"); if (compressorElement != null) { regionAttributesBuilder.addPropertyValue("compressor", parseRefOrSingleNestedBeanDeclaration( - parserContext, compressorElement, regionAttributesBuilder)); + compressorElement, parserContext, regionAttributesBuilder)); } } diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/PartitionedRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/PartitionedRegionParser.java index 81a116d5..49a37ec9 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/PartitionedRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/PartitionedRegionParser.java @@ -174,13 +174,13 @@ class PartitionedRegionParser extends AbstractRegionParser { private Object parsePartitionResolver(Element subElement, ParserContext parserContext, BeanDefinitionBuilder builder) { - return ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext, subElement, builder); + return ParsingUtils.parseRefOrSingleNestedBeanDeclaration(subElement, parserContext, builder); } /* (non-Javadoc) */ private Object parsePartitionListeners(Element subElement, ParserContext parserContext, BeanDefinitionBuilder builder) { - return ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, subElement, builder); + return ParsingUtils.parseRefOrNestedBeanDeclaration(subElement, parserContext, builder); } } diff --git a/src/main/java/org/springframework/data/gemfire/config/xml/SnapshotServiceParser.java b/src/main/java/org/springframework/data/gemfire/config/xml/SnapshotServiceParser.java index df11651f..5c35d29a 100644 --- a/src/main/java/org/springframework/data/gemfire/config/xml/SnapshotServiceParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/xml/SnapshotServiceParser.java @@ -89,7 +89,7 @@ class SnapshotServiceParser extends AbstractSingleBeanDefinitionParser { if (isSnapshotFilterSpecified(snapshotMetadataElement)) { snapshotMetadataBuilder.addConstructorArgValue(ParsingUtils.parseRefOrNestedBeanDeclaration( - parserContext, snapshotMetadataElement, snapshotMetadataBuilder, "filter-ref", true)); + snapshotMetadataElement, parserContext, snapshotMetadataBuilder, "filter-ref", true)); } snapshotMetadataBuilder.addConstructorArgValue(snapshotMetadataElement.getAttribute("format")); diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-data-geode-1.1.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-data-geode-1.1.xsd new file mode 100644 index 00000000..bdd6e7ae --- /dev/null +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-data-geode-1.1.xsd @@ -0,0 +1,253 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a MappingContext. If not set a default one will be created. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Determines whether imports are suppressed on initialization of the GemFire Snapshot Service. + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-2.0.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-2.0.xsd index 433295ea..45e5f990 100644 --- a/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-2.0.xsd +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-gemfire-2.0.xsd @@ -2273,6 +2273,117 @@ The type of index: FUNCTIONAL, HASH, PRIMARY_KEY. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2535,36 +2646,6 @@ The port number of the connection (between 1 and 65535 inclusive). - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/springframework/data/gemfire/config/spring-geode-1.1.xsd b/src/main/resources/org/springframework/data/gemfire/config/spring-geode-1.1.xsd new file mode 100644 index 00000000..4f987903 --- /dev/null +++ b/src/main/resources/org/springframework/data/gemfire/config/spring-geode-1.1.xsd @@ -0,0 +1,3250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + namespace and its 'properties' element. + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies the parent, template Region from which to inherit the Region attribute configuration. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/java/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests.java b/src/test/java/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests.java new file mode 100644 index 00000000..df7637f3 --- /dev/null +++ b/src/test/java/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests.java @@ -0,0 +1,265 @@ +/* + * 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.config.xml; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.doAnswer; +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 java.util.Collections; +import java.util.Map; +import java.util.Optional; + +import org.apache.geode.cache.GemFireCache; +import org.apache.geode.cache.lucene.LuceneIndex; +import org.apache.geode.cache.lucene.LuceneService; +import org.apache.lucene.analysis.Analyzer; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +/** + * Unit tests for the {@link LuceneServiceParser} and {@link LuceneIndexParser}. + * + * @author John Blum + * @see org.junit.Test + * @see org.junit.runner.RunWith + * @see org.springframework.test.context.ContextConfiguration + * @see org.springframework.test.context.junit4.SpringRunner + * @since 1.1.0 + */ +@RunWith(SpringRunner.class) +@ContextConfiguration +@SuppressWarnings("unused") +public class LuceneNamespaceUnitTests { + + private static final String[] EMPTY_STRING_ARRAY = {}; + + @Autowired + private LuceneService luceneService; + + @Autowired + @Qualifier("IndexOne") + private LuceneIndex luceneIndexOne; + + @Autowired + @Qualifier("IndexTwo") + private LuceneIndex luceneIndexTwo; + + @Autowired + @Qualifier("IndexThree") + private LuceneIndex luceneIndexThree; + + @Autowired + @Qualifier("IndexFour") + private LuceneIndex luceneIndexFour; + + protected void assertLuceneIndex(LuceneIndex index, String name, String regionPath) { + assertThat(index).isNotNull(); + assertThat(index.getName()).isEqualTo(name); + assertThat(index.getRegionPath()).isEqualTo(regionPath); + } + + protected void assertLuceneIndexWithFieldAnalyzers(LuceneIndex index, String name, String regionPath, + String... keys) { + + assertLuceneIndex(index, name, regionPath); + assertThat(index.getFieldNames()).isEmpty(); + assertThat(index.getFieldAnalyzers()).hasSize(keys.length); + assertThat(index.getFieldAnalyzers()).containsKeys(keys); + } + + protected void assertLuceneIndexWithFields(LuceneIndex index, String name, String regionPath, String... fieldNames) { + assertLuceneIndex(index, name, regionPath); + assertThat(index.getFieldAnalyzers()).isEmpty(); + assertThat(index.getFieldNames()).contains(fieldNames); + } + + @Test + @SuppressWarnings({ "deprecation", "unchecked" }) + public void luceneServiceConfigurationAndInteractionsAreCorrect() { + assertThat(this.luceneService).isNotNull(); + + verify(this.luceneService, times(1)) + .createIndex(eq("IndexOne"), eq("/Example"), eq("fieldOne"), eq("fieldTwo")); + + verify(this.luceneService, times(1)) + .createIndex(eq("IndexTwo"), eq("/AnotherExample"), isA(Map.class)); + + verify(this.luceneService, never()).destroyIndex(any(LuceneIndex.class)); + } + + @Test + public void luceneIndexOneIsConfiguredCorrectly() { + assertLuceneIndexWithFields(this.luceneIndexOne, "IndexOne", "/Example", + "fieldOne", "fieldTwo"); + } + + @Test + public void luceneIndexTwoIsConfiguredCorrectly() { + assertLuceneIndexWithFieldAnalyzers(this.luceneIndexTwo, "IndexTwo", "/AnotherExample", + "fieldOne", "fieldTwo"); + } + + @Test + public void luceneIndexThreeIsConfiguredCorrectly() { + assertLuceneIndexWithFields(this.luceneIndexThree, "IndexThree", "/Example", + "singleField"); + } + + @Test + public void luceneIndexFourIsConfiguredCorrectly() { + assertLuceneIndexWithFieldAnalyzers(this.luceneIndexFour, "IndexFour", "/YetAnotherExample", + "singleField"); + } + + public static class LuceneNamespaceUnitTestsBeanFactoryPostProcessor implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { + beanFactory.getBeanDefinition("luceneService") + .setBeanClassName(MockLuceneServiceFactoryBean.class.getName()); + } + } + + public static class MockLuceneServiceFactoryBean implements FactoryBean, InitializingBean { + + @SuppressWarnings("all") + private GemFireCache gemfireCache; + + private LuceneService luceneService; + + @Override + public void afterPropertiesSet() throws Exception { + assertThat(this.gemfireCache).describedAs("GemFireCache must not be null").isNotNull(); + } + + @Override + @SuppressWarnings("unchecked") + public LuceneService getObject() throws Exception { + return Optional.ofNullable(this.luceneService).orElseGet(() -> { + this.luceneService = mock(LuceneService.class); + + Answer mockLuceneIndex = newMockLuceneIndex(this.luceneService); + + doAnswer(mockLuceneIndex).when(this.luceneService) + .createIndex(anyString(), anyString(), (String[]) any()); + + doAnswer(mockLuceneIndex).when(this.luceneService) + .createIndex(anyString(), anyString(), isA(Map.class)); + + return this.luceneService; + }); + } + + @SuppressWarnings("unchecked") + private Answer newMockLuceneIndex(LuceneService mockLuceneService) { + return (invocationOnMock) -> { + String indexName = invocationOnMock.getArgument(0); + String regionPath = invocationOnMock.getArgument(1); + + LuceneIndex mockLuceneIndex = mock(LuceneIndex.class, indexName); + + when(mockLuceneIndex.getName()).thenReturn(indexName); + when(mockLuceneIndex.getRegionPath()).thenReturn(regionPath); + + if (invocationOnMock.getArguments().length > 2) { + Object fields = invocationOnMock.getArgument(2); + + if (fields instanceof Map) { + when(mockLuceneIndex.getFieldAnalyzers()).thenReturn((Map) fields); + when(mockLuceneIndex.getFieldNames()).thenReturn(EMPTY_STRING_ARRAY); + } + else { + when(mockLuceneIndex.getFieldAnalyzers()).thenReturn(Collections.emptyMap()); + when(mockLuceneIndex.getFieldNames()).thenReturn(extractFields(invocationOnMock)); + } + } + + when(mockLuceneService.getIndex(eq(indexName), eq(regionPath))).thenReturn(mockLuceneIndex); + + return mockLuceneIndex; + }; + } + + private String[] asStringArray(Object fields) { + return (fields instanceof String[] ? (String[]) fields : String.valueOf(fields).split(", ")); + } + + @SuppressWarnings("all") + private String[] extractFields(InvocationOnMock invocationOnMock) { + String[] fields = new String[invocationOnMock.getArguments().length - 2]; + System.arraycopy(invocationOnMock.getArguments(), 2, fields, 0, fields.length); + return fields; + } + + @Override + public Class getObjectType() { + return Optional.ofNullable(this.luceneService).>map(LuceneService::getClass) + .orElse(LuceneService.class); + } + + public void setCache(GemFireCache gemfireCache) { + this.gemfireCache = gemfireCache; + } + } + + public static class MockAnalyzerFactoryBean implements FactoryBean { + + @SuppressWarnings("unused") + private Analyzer analyzer; + + private String name; + + @Override + public Analyzer getObject() throws Exception { + return Optional.ofNullable(this.analyzer).orElseGet(() -> this.analyzer = mock(Analyzer.class, getName())); + } + + @Override + public Class getObjectType() { + return Optional.ofNullable(this.analyzer).>map(Analyzer::getClass).orElse(Analyzer.class); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + } +} diff --git a/src/test/resources/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests-context.xml b/src/test/resources/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests-context.xml new file mode 100644 index 00000000..403bc3fe --- /dev/null +++ b/src/test/resources/org/springframework/data/gemfire/config/xml/LuceneNamespaceUnitTests-context.xml @@ -0,0 +1,59 @@ + + + + + LuceneNamespaceUnitTests + warning + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +