SGF-194 Rewrote Subregion parsing in AbstractRegionParser

This commit is contained in:
David Turanski
2013-10-01 08:45:08 -04:00
parent 283b3723eb
commit 651f89662c
6 changed files with 91 additions and 89 deletions

3
.gitignore vendored
View File

@@ -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*
/BACKUP*

View File

@@ -60,7 +60,7 @@ public class SubRegionFactoryBean<K, V> extends AttributesFactory<K, V> 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<K, V> extends AttributesFactory<K, V> implemen
* @param name
*/
public void setName(String name) {
this.name = name;
this.name = name;
}
/**
@@ -102,7 +102,7 @@ public class SubRegionFactoryBean<K, V> extends AttributesFactory<K, V> implemen
* @param parent
*/
public void setParent(Region<?, ?> parent) {
this.parent = parent;
this.parent = parent;
}
/**

View File

@@ -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<String,Element> subRegionElements = new HashMap<String, Element>();
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<String,Element> allSubRegionElements = new HashMap<String, Element>();
findSubregionElements(element,getRegionNameFromElement(element),allSubRegionElements);
if (!CollectionUtils.isEmpty(allSubRegionElements)) {
for (Map.Entry<String,Element> 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<String,Element> 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);
}
}
}
}

View File

@@ -27,7 +27,7 @@ import org.w3c.dom.Element;
/**
* Parser for &lt;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<Element> subElements = DomUtils.getChildElements(element);
for (Element subElement : subElements) {
String name = subElement.getLocalName();
if (name.endsWith("region")) {
doParseSubRegion(element, subElement, parserContext, builder, subRegion);
}
}
}
@Override

View File

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

View File

@@ -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" >
<gfe:cache />
<gfe:replicated-region id="parent">
<gfe:replicated-region name="child">
<gfe:replicated-region name="grandchild"/>
<gfe:replicated-region name="grandchild"/>
</gfe:replicated-region>
</gfe:replicated-region>
<gfe:replicated-region id="replicatedParent">
<gfe:lookup-region name="lookupChild">
<gfe:replicated-region name="replicatedChild">
<gfe:partitioned-region name="partitionedGrandchild"/>
</gfe:lookup-region>
</gfe:replicated-region>
</gfe:replicated-region>
<gfe:replicated-region id="parentWithSiblings">
<gfe:replicated-region name="child1">
<gfe:replicated-region name="grandChild11"/>
@@ -29,7 +29,7 @@
</gfe:replicated-region>
<gfe:replicated-region name="child2"/>
</gfe:replicated-region>
<gfe:replicated-region id="complexNested">
<gfe:cache-listener ref="c-listener"/>
<gfe:replicated-region name="child1">
@@ -42,9 +42,9 @@
<gfe:cache-writer ref="c-writer"/>
</gfe:replicated-region>
</gfe:replicated-region>
<bean id="c-listener" class="org.springframework.data.gemfire.SimpleCacheListener"/>
<bean id="c-loader" class="org.springframework.data.gemfire.SimpleCacheLoader"/>
<bean id="c-writer" class="org.springframework.data.gemfire.SimpleCacheWriter"/>
</beans>