diff --git a/.gitignore b/.gitignore index a87cefbf..52fa69ee 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ target bin build +out .gradle .springBeans pom.xml @@ -21,4 +22,4 @@ _site/ /vf.gf.dmn-events.txt /vf.gf.dmn-license.cfg -/BACKUP* \ No newline at end of file +/BACKUP* diff --git a/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java b/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java index 10ad62df..67f37c9d 100644 --- a/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java +++ b/src/main/java/org/springframework/data/gemfire/SubRegionFactoryBean.java @@ -60,7 +60,7 @@ public class SubRegionFactoryBean extends AttributesFactory implemen + parent.getRegionService()); } else { - log.debug("creating subregion of [" + parent.getFullPath() + "] with name " + regionName); + log.debug("creating subregion of [" + ( parent.getFullPath() == null ? parent.getName() : parent.getFullPath()) + "] with name " + regionName); this.subRegion = this.parent.createSubregion(regionName, create()); } } @@ -86,7 +86,7 @@ public class SubRegionFactoryBean extends AttributesFactory implemen * @param name */ public void setName(String name) { - this.name = name; + this.name = name; } /** @@ -102,7 +102,7 @@ public class SubRegionFactoryBean extends AttributesFactory implemen * @param parent */ public void setParent(Region parent) { - this.parent = parent; + this.parent = parent; } /** diff --git a/src/main/java/org/springframework/data/gemfire/config/AbstractRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/AbstractRegionParser.java index 85de831f..2392fe66 100644 --- a/src/main/java/org/springframework/data/gemfire/config/AbstractRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/AbstractRegionParser.java @@ -16,12 +16,10 @@ package org.springframework.data.gemfire.config; -import java.util.List; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedArray; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; @@ -32,13 +30,20 @@ import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + /** * Base class for all Region Parsers - * + * * @author David Turanski */ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { + + private final Map subRegionElements = new HashMap(); + protected final Log log = LogFactory.getLog(getClass()); @Override @@ -56,55 +61,12 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { super.doParse(element, builder); boolean subRegion = isSubRegion(element); - - doParseRegion(element, parserContext, builder, subRegion); - - if (subRegion) { - builder.addPropertyValue("parent", parserContext.getContainingBeanDefinition().getAttribute("parent")); - builder.addPropertyValue("regionName", element.getAttribute(NAME_ATTRIBUTE)); - } + doParseRegion(element, parserContext, builder, subRegion); } protected abstract void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, boolean subRegion); - protected void doParseSubRegion(Element element, Element subElement, ParserContext parserContext, - BeanDefinitionBuilder builder, boolean subRegion) { - - String regionPath = null; - String parentBeanName = null; - if (subRegion) { - parentBeanName = parserContext.getContainingBeanDefinition().getAttribute("regionPath").toString(); - } - else { - parentBeanName = getRegionNameFromElement(element); - } - regionPath = StringUtils.arrayToDelimitedString(new String[] { parentBeanName, - getRegionNameFromElement(subElement) }, "/"); - if (!regionPath.startsWith("/")) { - regionPath = "/" + regionPath; - } - /* - * The Region parser needs some context to handle recursion correctly - */ - builder.getBeanDefinition().setAttribute("parent", - new BeanDefinitionHolder(builder.getBeanDefinition(), parentBeanName)); - builder.getBeanDefinition().setAttribute("regionPath", regionPath); - - // Make recursive call - BeanDefinition subRegionDef = this.parseSubRegion(subElement, parserContext, builder); - // TODO: Is there a better work-around? - /* - * This setting prevents the BF from generating a name for this been - */ - subRegionDef.setScope(BeanDefinition.SCOPE_PROTOTYPE); - - if (log.isDebugEnabled()) { - log.debug("registering subregion as " + regionPath); - } - this.registerBeanDefinition(new BeanDefinitionHolder(subRegionDef, regionPath), parserContext.getRegistry()); - } - protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext, BeanDefinitionBuilder builder, BeanDefinitionBuilder attrBuilder, boolean subRegion) { @@ -117,7 +79,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { } // add attributes ParsingUtils.setPropertyValue(element, builder, "name"); - + ParsingUtils.parseOptionalRegionAttributes(parserContext, element, attrBuilder); ParsingUtils.parseStatistics(element, attrBuilder); ParsingUtils.setPropertyValue(element, attrBuilder, "publisher"); @@ -179,11 +141,18 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { builder.addPropertyValue("cacheWriter", ParsingUtils.parseRefOrNestedBeanDeclaration(parserContext, subElement, builder)); } - else if (subElement.getLocalName().endsWith("region")) { - doParseSubRegion(element, subElement, parserContext, builder, subRegion); - } } + if (!subRegion) { + Map allSubRegionElements = new HashMap(); + findSubregionElements(element,getRegionNameFromElement(element),allSubRegionElements); + if (!CollectionUtils.isEmpty(allSubRegionElements)) { + for (Map.Entry entry: allSubRegionElements.entrySet()) { + parseSubRegion(entry.getValue(),parserContext,entry.getKey()); + } + } + } + } private void parseCollectionOfCustomSubElements(ParserContext parserContext, Element element, @@ -200,14 +169,48 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser { } } - private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element, - builder.getBeanDefinition()); - return beanDefinition; + private BeanDefinition parseSubRegion(Element element, ParserContext parserContext, String regionPath) { + element.setAttribute("id", regionPath); + String regionName = getRegionNameFromElement(element); + element.setAttribute("name", regionPath); + BeanDefinition beanDefinition = parserContext.getDelegate().parseCustomElement(element); + String parentBeanName = getParentPathForSubRegion(regionPath); + beanDefinition.getPropertyValues().add("parent",new RuntimeBeanReference(parentBeanName)); + beanDefinition.getPropertyValues().add("regionName",regionName); + return beanDefinition; } private String getRegionNameFromElement(Element element) { String name = element.getAttribute(NAME_ATTRIBUTE); return StringUtils.hasText(name) ? name : element.getAttribute(ID_ATTRIBUTE); } + + private String buildPathForSubRegion(String parentName, String regionName) { + String regionPath = StringUtils.arrayToDelimitedString(new String[] { parentName, + regionName }, "/"); + if (!regionPath.startsWith("/")) { + regionPath = "/" + regionPath; + } + return regionPath; + } + + private String getParentPathForSubRegion(String regionPath) { + int index = regionPath.lastIndexOf("/"); + String parentPath = regionPath.substring(0,index); + if (parentPath.lastIndexOf("/") == 0) { + parentPath = parentPath.substring(1); + } + return parentPath; + } + + + private void findSubregionElements(Element parent, String parentPath, Map allSubregionElements) { + for (Element element : DomUtils.getChildElements(parent)) { + if (element.getLocalName().endsWith("region")) { + String regionPath = buildPathForSubRegion(parentPath, getRegionNameFromElement(element)); + allSubregionElements.put(regionPath,element); + findSubregionElements(element,regionPath,allSubregionElements); + } + } + } } diff --git a/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java index 832cfb91..867a3d9c 100644 --- a/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java +++ b/src/main/java/org/springframework/data/gemfire/config/LookupRegionParser.java @@ -27,7 +27,7 @@ import org.w3c.dom.Element; /** * Parser for <lookup-region;gt; definitions. - * + * * @author Costin Leau * @author David Turanski */ @@ -48,15 +48,6 @@ class LookupRegionParser extends AbstractRegionParser { else { builder.addPropertyValue("lookupOnly", true); } - - // parse nested elements - List subElements = DomUtils.getChildElements(element); - for (Element subElement : subElements) { - String name = subElement.getLocalName(); - if (name.endsWith("region")) { - doParseSubRegion(element, subElement, parserContext, builder, subRegion); - } - } } @Override diff --git a/src/test/java/org/springframework/data/gemfire/config/SubRegionNamespaceTest.java b/src/test/java/org/springframework/data/gemfire/config/SubRegionNamespaceTest.java index db530dc0..45054a45 100644 --- a/src/test/java/org/springframework/data/gemfire/config/SubRegionNamespaceTest.java +++ b/src/test/java/org/springframework/data/gemfire/config/SubRegionNamespaceTest.java @@ -47,12 +47,21 @@ public class SubRegionNamespaceTest { @Autowired private ApplicationContext context; - + @SuppressWarnings("rawtypes") + @Test + public void testNestedRegionsCreated() { + Cache cache = context.getBean(Cache.class); + assertNotNull(cache.getRegion("parent")); + assertNotNull(cache.getRegion("/parent/child")); + assertNotNull(cache.getRegion("/parent/child/grandchild")); + } @SuppressWarnings("rawtypes") @Test public void testNestedReplicatedRegions() { - Region parent = context.getBean("parent", Region.class); + Region parent = null; + parent = context.getBean("parent", Region.class); + Cache cache = context.getBean(Cache.class); Region child = context.getBean("/parent/child", Region.class); Region grandchild = context.getBean("/parent/child/grandchild", Region.class); assertNotNull(child); @@ -70,15 +79,13 @@ public class SubRegionNamespaceTest { Cache cache = context.getBean(Cache.class); Region parent = context.getBean("replicatedParent", Region.class); - parent.createSubregion("lookupChild", new AttributesFactory().create()); - Region child = context.getBean("/replicatedParent/lookupChild", Region.class); - Region grandchild = context.getBean("/replicatedParent/lookupChild/partitionedGrandchild", Region.class); + Region child = context.getBean("/replicatedParent/replicatedChild", Region.class); + Region grandchild = context.getBean("/replicatedParent/replicatedChild/partitionedGrandchild", Region.class); assertNotNull(child); - assertEquals("/replicatedParent/lookupChild", child.getFullPath()); - assertSame(child, parent.getSubregion("lookupChild")); + assertEquals("/replicatedParent/replicatedChild", child.getFullPath()); - assertEquals("/replicatedParent/lookupChild/partitionedGrandchild", grandchild.getFullPath()); + assertEquals("/replicatedParent/replicatedChild/partitionedGrandchild", grandchild.getFullPath()); assertSame(grandchild, child.getSubregion("partitionedGrandchild")); } diff --git a/src/test/resources/org/springframework/data/gemfire/config/subregion-ns.xml b/src/test/resources/org/springframework/data/gemfire/config/subregion-ns.xml index d0803639..96e4d9a5 100644 --- a/src/test/resources/org/springframework/data/gemfire/config/subregion-ns.xml +++ b/src/test/resources/org/springframework/data/gemfire/config/subregion-ns.xml @@ -6,22 +6,22 @@ xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd - http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" default-lazy-init="true"> + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd" > - + - + - - + + - + - + - + @@ -29,7 +29,7 @@ - + @@ -42,9 +42,9 @@ - + - + \ No newline at end of file