Additional work and changes for JIRA feature requests SGF-207 and SGF-254 to enable developers with the ability to create Region templates to model attributes and configuration meta-data common to multiple, strongly-typed GemFire Region types (e.g. REPLICATE, PARTITION, etc).

This commit is contained in:
John Blum
2014-08-22 13:11:30 -07:00
committed by John Blum
parent 5d27c19ef5
commit 2f66eca99b
5 changed files with 209 additions and 32 deletions

View File

@@ -22,6 +22,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -29,6 +30,7 @@ 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;
import org.springframework.util.xml.DomUtils;
@@ -81,6 +83,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
protected void doParseCommonRegionConfiguration(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, BeanDefinitionBuilder regionAttributesBuilder, boolean subRegion) {
mergeTemplateRegionAttributes(element, parserContext, builder, regionAttributesBuilder);
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
if (!subRegion) {
@@ -159,6 +163,45 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
}
}
void mergeTemplateRegionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder regionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
// NOTE we only need to merge the parent RegionAttributes with this since the parent will have
// already merged it's parent's RegionAttributes and so on...
regionAttributesBuilder.getRawBeanDefinition().overrideFrom(regionTemplateAttributesDefinition);
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
BeanDefinition getRegionAttributesBeanDefinition(final BeanDefinition region) {
Assert.notNull(region, "The 'Region' BeanDefinition must not be null!");
Object regionAttributesDefinition = null;
if (region.getPropertyValues().contains("attributes")) {
PropertyValue regionAttributes = region.getPropertyValues().getPropertyValue("attributes");
regionAttributesDefinition = regionAttributes.getValue();
}
return (regionAttributesDefinition instanceof BeanDefinition ? (BeanDefinition) regionAttributesDefinition : null);
}
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,

View File

@@ -18,6 +18,8 @@ package org.springframework.data.gemfire.config;
import java.util.List;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.ParserContext;
@@ -53,8 +55,6 @@ class PartitionedRegionParser extends AbstractRegionParser {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
super.doParse(element, regionBuilder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
@@ -65,6 +65,8 @@ class PartitionedRegionParser extends AbstractRegionParser {
BeanDefinitionBuilder partitionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
PartitionAttributesFactoryBean.class);
mergeTemplateRegionPartitionAttributes(element, parserContext, regionBuilder, partitionAttributesBuilder);
parseColocatedWith(element, regionBuilder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
@@ -108,6 +110,40 @@ class PartitionedRegionParser extends AbstractRegionParser {
regionAttributesBuilder.addPropertyValue("partitionAttributes", partitionAttributesBuilder.getBeanDefinition());
}
void mergeTemplateRegionPartitionAttributes(Element element, ParserContext parserContext,
BeanDefinitionBuilder regionBuilder, BeanDefinitionBuilder partitionAttributesBuilder) {
String regionTemplate = getParentName(element);
if (StringUtils.hasText(regionTemplate)) {
if (parserContext.getRegistry().containsBeanDefinition(regionTemplate)) {
BeanDefinition regionTemplateDefinition = parserContext.getRegistry()
.getBeanDefinition(regionTemplate);
BeanDefinition regionTemplateAttributesDefinition = getRegionAttributesBeanDefinition(
regionTemplateDefinition);
if (regionTemplateAttributesDefinition != null) {
if (regionTemplateAttributesDefinition.getPropertyValues().contains("partitionAttributes")) {
PropertyValue partitionAttributes = regionTemplateAttributesDefinition.getPropertyValues()
.getPropertyValue("partitionAttributes");
Object partitionAttributesDefinition = partitionAttributes.getValue();
if (partitionAttributesDefinition instanceof BeanDefinition) {
partitionAttributesBuilder.getRawBeanDefinition().overrideFrom(
(BeanDefinition) partitionAttributesDefinition);
}
}
}
}
else {
parserContext.getReaderContext().error(String.format(
"The Region template [%1$s] must be defined in the Spring context configuration meta-data 'before' the Region [%2$s] using the template!",
regionTemplate, resolveId(element, regionBuilder.getRawBeanDefinition(), parserContext)), element);
}
}
}
private void parseColocatedWith(Element element, BeanDefinitionBuilder regionBuilder,
BeanDefinitionBuilder partitionAttributesBuilder, String attributeName) {
// NOTE rather than using a dependency (with depends-on) we could also set the colocatedWith property of the