Implements SGF-88 - Region Shortcuts; Implements SGF-257 - Strict types in the SDG XSD for Region data-policy and shortcut attributes; Fixes SGF-258 - missing data-policy attribute for Partitioned Regions; Fixes SGF-263 - ineffective application of disk-synchronous attribute setting on Region bean definitions defined with SDG XML namespace.

This commit is contained in:
John Blum
2014-03-21 00:32:45 -07:00
parent 942c5ca7be
commit 1594c5f062
30 changed files with 2747 additions and 402 deletions

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.data.gemfire;
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.RegionFactory;
@@ -39,6 +39,28 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
super.afterPropertiesSet();
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy == null || DataPolicy.NORMAL.equals(dataPolicy)) {
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
}
else if (DataPolicy.PRELOADED.equals(dataPolicy)) {
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
}
else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy)
&& RegionShortcutWrapper.valueOf(getShortcut()).isPersistent()) {
regionFactory.setDataPolicy(dataPolicy);
}
else {
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported for Local Regions.",
dataPolicy));
}
}
/**
* Resolves the Data Policy used by this "local" GemFire Region (i.e. locally Scoped; Scope.LOCAL) based on the
* enumerated value from com.gemstone.gemfire.cache.RegionShortcuts (LOCAL, LOCAL_PERSISTENT, LOCAL_HEAP_LRU,
@@ -53,25 +75,14 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
*/
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
DataPolicy resolvedDataPolicy = null;
Assert.isTrue(resolvedDataPolicy != null || !StringUtils.hasText(dataPolicy),
String.format("Data Policy '%1$s' is invalid.", dataPolicy));
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
if (resolvedDataPolicy == null || DataPolicy.NORMAL.equals(resolvedDataPolicy)) {
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
}
else if (DataPolicy.PRELOADED.equals(resolvedDataPolicy)) {
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
}
else {
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported in Local Regions.",
dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -28,32 +28,38 @@ import com.gemstone.gemfire.cache.RegionFactory;
public class PartitionedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
if (dataPolicy != null) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
// First, verify the GemFire version is 6.5 or Higher when Persistence is specified...
Assert.isTrue(!DataPolicy.PERSISTENT_PARTITION.equals(dataPolicy) || GemfireUtils.isGemfireVersion65OrAbove(),
String.format("Persistent PARTITION Regions can only be used from GemFire 6.5 onwards; current version is [%1$s].",
CacheFactory.getVersion()));
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
Assert.isTrue(resolvedDataPolicy.withPartitioning(), String.format(
"Data Policy '%1$s' is not supported in Partitioned Regions.", resolvedDataPolicy));
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
regionFactory.setDataPolicy(resolvedDataPolicy);
}
else if (isPersistent()) {
// first, check the presence of GemFire 6.5 or Higher
Assert.isTrue(GemfireUtils.isGemfireVersion65OrAbove(), String.format(
"Can define Persistent Partitioned Regions only from GemFire 6.5 onwards; current version is [%1$s]",
CacheFactory.getVersion()));
regionFactory.setDataPolicy(DataPolicy.PERSISTENT_PARTITION);
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION);
}
else {
regionFactory.setDataPolicy(DataPolicy.PARTITION);
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
Assert.isTrue(dataPolicy.withPartitioning(), String.format(
"Data Policy '%1$s' is not supported in Partitioned Regions.", dataPolicy));
}
// Validate the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = null;
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.io.Resource;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -35,12 +36,16 @@ import com.gemstone.gemfire.cache.CacheLoader;
import com.gemstone.gemfire.cache.CacheWriter;
import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.PartitionAttributes;
import com.gemstone.gemfire.cache.PartitionAttributesFactory;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
import com.gemstone.gemfire.cache.wan.GatewaySender;
import com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes;
/**
* Base class for FactoryBeans used to create GemFire {@link Region}s. Will try
@@ -56,6 +61,7 @@ import com.gemstone.gemfire.cache.wan.GatewaySender;
* @author David Turanski
* @author John Blum
*/
@SuppressWarnings("unused")
public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean, SmartLifecycle {
protected final Log log = LogFactory.getLog(getClass());
@@ -74,16 +80,19 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
private CacheWriter<K, V> cacheWriter;
private DataPolicy dataPolicy;
private Object[] asyncEventQueues;
private Object[] gatewaySenders;
private RegionAttributes<K, V> attributes;
private RegionShortcut shortcut;
private Resource snapshot;
private Scope scope;
private String dataPolicy;
private String diskStoreName;
private String hubId;
@@ -94,27 +103,17 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
@Override
@SuppressWarnings("deprecation")
protected Region<K, V> lookupFallback(GemFireCache gemfireCache, String regionName) throws Exception {
Assert.isTrue(gemfireCache instanceof Cache, "Unable to create Regions from " + gemfireCache);
Cache cache = (Cache) gemfireCache;
RegionFactory<K, V> regionFactory;
if (attributes != null) {
// TODO refactor... AttributesFactory extended by the SDG RegionAttributesFactoryBean and used by all
// RegionFactoryBeans subclasses calls AttributesFactory.validateAttributes(..) before the RegionAttributes
// are created in the AttributesFactory.create() method, which is called by
// RegionAttributesFactoryBean.afterPropertiesSet() method.
AttributesFactory.validateAttributes(attributes);
regionFactory = cache.createRegionFactory(attributes);
}
else {
regionFactory = cache.createRegionFactory();
}
RegionFactory<K, V> regionFactory = createRegionFactory(cache);
if (hubId != null) {
enableGateway = (enableGateway == null || enableGateway);
Assert.isTrue(enableGateway, "hubId requires the enableGateway property to be true");
Assert.isTrue(enableGateway, "The 'hubId' requires the 'enableGateway' property to be true");
regionFactory.setGatewayHubId(hubId);
}
@@ -154,12 +153,12 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
regionFactory.setCacheWriter(cacheWriter);
}
resolveDataPolicy(regionFactory, persistent, dataPolicy);
if (diskStoreName != null) {
regionFactory.setDiskStoreName(diskStoreName);
}
resolveDataPolicy(regionFactory, persistent, dataPolicy);
if (scope != null) {
regionFactory.setScope(scope);
}
@@ -169,8 +168,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
"Lock Grantor only applies to a global scoped region.");
}
// get underlying AttributesFactory
postProcess(findAttributesFactory(regionFactory));
postProcess(regionFactory);
Region<K, V> region = (getParent() != null ? regionFactory.createSubregion(getParent(), regionName)
: regionFactory.create(regionName));
@@ -196,12 +194,279 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return region;
}
/**
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
* are compatible.
* <p/>
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
* meta-data.
* @see #isPersistent()
* @see #isNotPersistent()
* @see com.gemstone.gemfire.cache.DataPolicy
*/
protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) {
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
}
else {
// NOTE otherwise, the Data Policy is not persistent, so...
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
}
}
/**
* Determines whether the user explicitly set the 'persistent' attribute or not.
* <p/>
* @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false.
* @see #isPersistent()
* @see #isNotPersistent()
*/
protected boolean isPersistentUnspecified() {
return (persistent == null);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is true;
* false otherwise.
* @see #isNotPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isPersistent() {
return Boolean.TRUE.equals(persistent);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is false;
* false otherwise.
* @see #isPersistent()
* @see #isPersistentUnspecified()
*/
protected boolean isNotPersistent() {
return Boolean.FALSE.equals(persistent);
}
/**
* Creates an instance of RegionFactory using the given Cache instance used to configure and construct the Region
* created by this FactoryBean.
* <p/>
* @param cache the GemFire Cache instance.
* @return a RegionFactory used to configure and construct the Region created by this FactoryBean.
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory()
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionAttributes)
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionShortcut)
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected RegionFactory<K, V> createRegionFactory(final Cache cache) {
if (shortcut != null) {
RegionFactory<K, V> regionFactory = mergeRegionAttributes(
cache.<K, V>createRegionFactory(shortcut), attributes);
setDataPolicy(getDataPolicy(regionFactory));
return regionFactory;
}
else if (attributes != null) {
return cache.createRegionFactory(attributes);
}
else {
return cache.createRegionFactory();
}
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* @see com.gemstone.gemfire.cache.RegionFactory#attrsFactory
* @see com.gemstone.gemfire.cache.AttributesFactory#regionAttributes
* @see com.gemstone.gemfire.cache.RegionAttributes#getDataPolicy
* @see com.gemstone.gemfire.cache.DataPolicy
*/
@SuppressWarnings({ "deprecation", "unchecked"})
DataPolicy getDataPolicy(final RegionFactory regionFactory) {
// NOTE cannot pass RegionAttributes.class as the "targetType" on the second invocation of getFieldValue(..)
// since the "regionAttributes" field is naively of the implementation class type rather than the interface
// type... so much for programming to interfaces.
return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", AttributesFactory.class),
"regionAttributes", null)).getDataPolicy();
}
/*
* (non-Javadoc)
*/
@SuppressWarnings("unchecked")
private <T> T getFieldValue(final Object source, final String fieldName, final Class<T> targetType) {
Field field = ReflectionUtils.findField(source.getClass(), fieldName, targetType);
ReflectionUtils.makeAccessible(field);
return (T) ReflectionUtils.getField(field, source);
}
/**
* Intelligently merges the given RegionAttributes with the configuration setting of the RegionFactory. This method
* is used to merge the RegionAttributes and PartitionAttributes with the RegionFactory that is created when the
* user specified a RegionShortcut. This method gets called by the createRegionFactory method depending upon
* the value passed to the Cache.createRegionFactory() method (i.e. whether there was a RegionShortcut specified
* or not).
* <p/>
* @param <K> the Class type fo the Region key.
* @param <V> the Class type of the Region value.
* @param regionFactory the GemFire RegionFactory used to configure and create the Region that is the product
* of this RegionFactoryBean.
* @param regionAttributes the RegionAttributes containing the Region configuration settings to merge to the
* RegionFactory.
* @return the RegionFactory with the configuration settings of the RegionAttributes merged.
* @see #hasUserSpecifiedEvictionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
* @see #validateRegionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
* @see com.gemstone.gemfire.cache.RegionAttributes
* @see com.gemstone.gemfire.cache.RegionFactory
*/
@SuppressWarnings("unchecked")
protected <K, V> RegionFactory<K, V> mergeRegionAttributes(final RegionFactory<K, V> regionFactory,
final RegionAttributes<K, V> regionAttributes) {
if (regionAttributes != null) {
// NOTE this validation may not be strictly required depending on how the RegionAttributes were "created",
// but...
validateRegionAttributes(regionAttributes);
regionFactory.setCloningEnabled(regionAttributes.getCloningEnabled());
regionFactory.setConcurrencyChecksEnabled(regionAttributes.getConcurrencyChecksEnabled());
regionFactory.setConcurrencyLevel(regionAttributes.getConcurrencyLevel());
regionFactory.setCustomEntryIdleTimeout(regionAttributes.getCustomEntryIdleTimeout());
regionFactory.setCustomEntryTimeToLive(regionAttributes.getCustomEntryTimeToLive());
regionFactory.setDiskSynchronous(regionAttributes.isDiskSynchronous());
regionFactory.setEnableAsyncConflation(regionAttributes.getEnableAsyncConflation());
regionFactory.setEnableSubscriptionConflation(regionAttributes.getEnableSubscriptionConflation());
regionFactory.setEntryIdleTimeout(regionAttributes.getEntryIdleTimeout());
regionFactory.setEntryTimeToLive(regionAttributes.getEntryTimeToLive());
// NOTE EvictionAttributes are created by certain RegionShortcuts; need the null check!
if (hasUserSpecifiedEvictionAttributes(regionAttributes)) {
regionFactory.setEvictionAttributes(regionAttributes.getEvictionAttributes());
}
regionFactory.setIgnoreJTA(regionAttributes.getIgnoreJTA());
regionFactory.setIndexMaintenanceSynchronous(regionAttributes.getIndexMaintenanceSynchronous());
regionFactory.setInitialCapacity(regionAttributes.getInitialCapacity());
regionFactory.setKeyConstraint(regionAttributes.getKeyConstraint());
regionFactory.setLoadFactor(regionAttributes.getLoadFactor());
regionFactory.setLockGrantor(regionAttributes.isLockGrantor());
regionFactory.setMembershipAttributes(regionAttributes.getMembershipAttributes());
regionFactory.setMulticastEnabled(regionAttributes.getMulticastEnabled());
mergePartitionAttributes(regionFactory, regionAttributes);
regionFactory.setPoolName(regionAttributes.getPoolName());
regionFactory.setRegionIdleTimeout(regionAttributes.getRegionIdleTimeout());
regionFactory.setRegionTimeToLive(regionAttributes.getRegionTimeToLive());
regionFactory.setStatisticsEnabled(regionAttributes.getStatisticsEnabled());
regionFactory.setSubscriptionAttributes(regionAttributes.getSubscriptionAttributes());
regionFactory.setValueConstraint(regionAttributes.getValueConstraint());
}
return regionFactory;
}
protected <K, V> void mergePartitionAttributes(final RegionFactory<K, V> regionFactory, final RegionAttributes<K, V> regionAttributes) {
// NOTE PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes
// can technically return null!
// NOTE most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always
// sets a PartitionAttributesFactoryBean BeanBuilder on the RegionAttributesFactoryBean "partitionAttributes"
// property.
if (regionAttributes.getPartitionAttributes() != null) {
PartitionAttributes partitionAttributes = regionAttributes.getPartitionAttributes();
PartitionAttributesFactory partitionAttributesFactory = new PartitionAttributesFactory(partitionAttributes);
RegionShortcutWrapper shortcutWrapper = RegionShortcutWrapper.valueOf(shortcut);
// NOTE however, since the default value of redundancy is 0, we need to account for 'redundant'
// RegionShortcut types, which specify a redundancy of 1.
if (shortcutWrapper.isRedundant() && partitionAttributes.getRedundantCopies() == 0) {
partitionAttributesFactory.setRedundantCopies(1);
}
// NOTE and, since the default value of localMaxMemory is based on the system memory, we need to account for
// 'proxy' RegionShortcut types, which specify a local max memory of 0.
if (shortcutWrapper.isProxy()) {
partitionAttributesFactory.setLocalMaxMemory(0);
}
// NOTE internally, RegionFactory.setPartitionAttributes handles merging the PartitionAttributes, hooray!
regionFactory.setPartitionAttributes(partitionAttributesFactory.create());
}
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* NOTE unfortunately, must resort to using a GemFire internal class, ugh!
* @see com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes
*/
boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) {
return (regionAttributes instanceof UserSpecifiedRegionAttributes
&& ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes());
}
/*
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
* @see com.gemstone.gemfire.cache.AttributesFactory#validateAttributes(:RegionAttributes)
*/
@SuppressWarnings("deprecation")
void validateRegionAttributes(final RegionAttributes regionAttributes) {
AttributesFactory.validateAttributes(regionAttributes);
}
/**
* Post-process the RegionFactory used to create the GemFire Region for this factory bean during the initialization
* process. The RegionFactory is already configured and initialized by the factory bean before this method
* is invoked.
* <p/>
* @param regionFactory the GemFire RegionFactory used to create the Region for post-processing.
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected void postProcess(RegionFactory<K, V> regionFactory) {
}
/**
* Post-process the Region for this factory bean during the initialization process. The Region is
* already configured and initialized by the factory bean before this method is invoked.
* <p/>
* @param region the GemFire Region to post-process.
* @see com.gemstone.gemfire.cache.Region
*/
protected void postProcess(Region<K, V> region) {
}
/**
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
* FactoryBean.
* <p/>
* @param regionFactory the RegionFactory used by this FactoryBean to create and configure the Region.
* @param persistent a boolean value indicating whether the Region should be persistent and persist it's
* data to disk.
* @param dataPolicy the configured Data Policy for the Region.
* @see #resolveDataPolicy(com.gemstone.gemfire.cache.RegionFactory, Boolean, String)
* @see com.gemstone.gemfire.cache.DataPolicy
* @see com.gemstone.gemfire.cache.RegionFactory
*/
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy != null) {
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
else {
resolveDataPolicy(regionFactory, persistent, (String) null);
}
}
/**
* Validates the configured Data Policy and may override it, taking into account the 'persistent' attribute
* and constraints for the Region type.
* <p/>
* @param regionFactory the GemFire RegionFactory used to created the Local Region.
* @param persistent a boolean value indicating whether the Local Region should persist it's data.
* @param regionFactory the GemFire RegionFactory used to create the desired Region.
* @param persistent a boolean value indicating whether the Region should persist it's data to disk.
* @param dataPolicy requested Data Policy as set by the user in the Spring GemFire configuration meta-data.
* @see com.gemstone.gemfire.cache.DataPolicy
* @see com.gemstone.gemfire.cache.RegionFactory
@@ -220,40 +485,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
}
@SuppressWarnings("unchecked")
private AttributesFactory<K, V> findAttributesFactory(RegionFactory<K, V> regionFactory) {
Field attrsFactoryField = ReflectionUtils.findField(RegionFactory.class, "attrsFactory",
AttributesFactory.class);
ReflectionUtils.makeAccessible(attrsFactoryField);
return (AttributesFactory<K, V>) ReflectionUtils.getField(attrsFactoryField, regionFactory);
}
/**
* Post-process the attribute factory object used for configuring the region
* of this factory bean during the initialization process. The object is
* already initialized and configured by the factory bean before this method
* is invoked.
*
* @param attributesFactory attribute factory
* @deprecated as of GemFire 6.5, the use of {@link AttributesFactory} has
* been deprecated
*/
@Deprecated
@SuppressWarnings("unused")
protected void postProcess(AttributesFactory<K, V> attributesFactory) {
}
/**
* Post-process the region object for this factory bean during the
* initialization process. The object is already initialized and configured
* by the factory bean before this method is invoked.
*
* @param region
*/
@SuppressWarnings("unused")
protected void postProcess(Region<K, V> region) {
}
@Override
public void destroy() throws Exception {
if (getRegion() != null) {
@@ -274,9 +505,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
/**
*
* @param asyncEventQueues defined as Object for backward compatibility with
* Gemfire 6
* The list of AsyncEventQueues to use with this Region.
* <p/>
* @param asyncEventQueues defined as Object for backwards compatibility with Gemfire 6.
*/
public void setAsyncEventQueues(Object[] asyncEventQueues) {
this.asyncEventQueues = asyncEventQueues;
@@ -293,14 +524,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.attributes = attributes;
}
/**
* Indicates whether the region referred by this factory bean, will be
* closed on shutdown (default true).
*/
public void setClose(boolean close) {
this.close = close;
}
/**
* Sets the cache listeners used for the region used by this factory. Used
* only when a new region is created.Overrides the settings specified
@@ -334,6 +557,14 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.cacheWriter = cacheWriter;
}
/**
* Indicates whether the region referred by this factory bean, will be
* closed on shutdown (default true).
*/
public void setClose(boolean close) {
this.close = close;
}
/**
* Indicates whether the region referred by this factory bean, will be
* destroyed on shutdown (default false).
@@ -343,17 +574,30 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
}
/**
* Sets the dataPolicy as a String. Required to support property
* placeholders
* @param dataPolicyName the dataPolicy name (NORMAL, PRELOADED, etc)
* Sets the DataPolicy of the Region.
* <p/>
* @param dataPolicy the GemFire DataPolicy to use when configuring the Region.
* @since 1.4.0
*/
public void setDataPolicy(String dataPolicyName) {
this.dataPolicy = dataPolicyName;
public void setDataPolicy(DataPolicy dataPolicy) {
this.dataPolicy = dataPolicy;
}
/**
* Sets the name of disk store to use for overflow and persistence
* @param diskStoreName
* Sets the DataPolicy of the Region as a String.
* <p/>
* @param dataPolicyName the name of the DataPolicy (e.g. REPLICATE, PARTITION)
* @see #setDataPolicy(com.gemstone.gemfire.cache.DataPolicy)
* @deprecated as of 1.4.0, use setDataPolicy(:DataPolicy) instead.
*/
public void setDataPolicy(String dataPolicyName) {
this.dataPolicy = new DataPolicyConverter().convert(dataPolicyName);
}
/**
* Sets the name of Disk Store used for either overflow or persistence, or both.
* <p/>
* @param diskStoreName the name of the Disk Store bean in context used for overflow/persistence.
*/
public void setDiskStoreName(String diskStoreName) {
this.diskStoreName = diskStoreName;
@@ -376,7 +620,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.hubId = hubId;
}
public void setPersistent(boolean persistent) {
public void setPersistent(Boolean persistent) {
this.persistent = persistent;
}
@@ -391,6 +635,24 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.scope = scope;
}
/*
* (non-Javadoc)
*/
protected final RegionShortcut getShortcut() {
return shortcut;
}
/**
* Configures the Region with a RegionShortcut.
* <p/>
* @param shortcut the RegionShortcut used to configure pre-defined default for the Region created
* by this FactoryBean.
* @see com.gemstone.gemfire.cache.RegionShortcut
*/
public void setShortcut(RegionShortcut shortcut) {
this.shortcut = shortcut;
}
/**
* Sets the snapshots used for loading a newly <i>created</i> region. That
* is, the snapshot will be used <i>only</i> when a new region is created -
@@ -403,57 +665,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.snapshot = snapshot;
}
/**
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
* are compatible.
* <p/>
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
* meta-data.
* @see #isPersistent()
* @see #isNotPersistent()
* @see com.gemstone.gemfire.cache.DataPolicy
*/
protected void assertDataPolicyAndPersistentAttributesAreCompatible(final DataPolicy resolvedDataPolicy) {
final boolean persistentNotSpecified = (this.persistent == null);
if (resolvedDataPolicy.withPersistence()) {
Assert.isTrue(persistentNotSpecified || isPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
}
else {
// NOTE otherwise, the Data Policy is with persistence, so...
Assert.isTrue(persistentNotSpecified || isNotPersistent(), String.format(
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
}
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is true;
* false otherwise.
* @see #isNotPersistent()
*/
protected boolean isPersistent() {
return Boolean.TRUE.equals(persistent);
}
/**
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
* and will be determined by the Data Policy.
* <p/>
* @return true when the user specified an explicit value for the persistent attribute and it is false;
* false otherwise.
* @see #isPersistent()
*/
protected boolean isNotPersistent() {
return Boolean.FALSE.equals(persistent);
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#start()
*/
@Override
@@ -461,9 +674,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
GatewaySender gws = (GatewaySender) obj;
if (!(gws.isManualStart() || gws.isRunning())) {
gws.start();
GatewaySender gatewaySender = (GatewaySender) obj;
if (!(gatewaySender.isManualStart() || gatewaySender.isRunning())) {
gatewaySender.start();
}
}
}
@@ -471,22 +684,25 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
this.running = true;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#stop()
*/
@Override
public void stop() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
((GatewaySender) obj).stop();
for (Object gatewaySender : gatewaySenders) {
((GatewaySender) gatewaySender).stop();
}
}
}
this.running = false;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Lifecycle#isRunning()
*/
@Override
@@ -494,7 +710,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return this.running;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.Phased#getPhase()
*/
@Override
@@ -502,7 +719,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return Integer.MAX_VALUE;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
*/
@Override
@@ -510,7 +728,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
return this.autoStartup;
}
/* (non-Javadoc)
/*
* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
*/
@Override

View File

@@ -27,30 +27,36 @@ import com.gemstone.gemfire.cache.RegionFactory;
public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
if (dataPolicy != null) {
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
if (DataPolicy.EMPTY.equals(resolvedDataPolicy)) {
resolvedDataPolicy = DataPolicy.EMPTY;
}
else {
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for Region (i.e. <gfe:replicated-region .../>)!
Assert.isTrue(resolvedDataPolicy.withReplication(), String.format(
"Data Policy '%1$s' is not supported in Replicated Regions.", resolvedDataPolicy));
}
// Validate that the data-policy and persistent attributes are compatible when specified!
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
regionFactory.setDataPolicy(resolvedDataPolicy);
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
if (dataPolicy == null) {
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
}
else if (DataPolicy.EMPTY.equals(dataPolicy)) {
dataPolicy = DataPolicy.EMPTY;
}
else {
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
// configuration meta-data element for the Region (i.e. <gfe:replicated-region .../>)!
Assert.isTrue(dataPolicy.withReplication(), String.format(
"Data Policy '%1$s' is not supported in Replicated Regions.", dataPolicy));
}
// Validate that the data-policy and persistent attributes are compatible when both are specified!
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
regionFactory.setDataPolicy(dataPolicy);
}
@Override
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
DataPolicy resolvedDataPolicy = null;
if (dataPolicy != null) {
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
}
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
}
}

View File

@@ -80,7 +80,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "name");
ParsingUtils.setPropertyValue(element, builder, "data-policy");
ParsingUtils.setPropertyValue(element, builder, "persistent");
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "publisher");
ParsingUtils.setPropertyValue(element, builder, "shortcut");
if (StringUtils.hasText(element.getAttribute("disk-store-ref"))) {
ParsingUtils.setPropertyValue(element, builder, "disk-store-ref", "diskStoreName");
@@ -147,8 +147,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
List<Element> subElements = DomUtils.getChildElementsByTagName(element,
new String[] { subElementName, subElementName + "-ref" });
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,
subElementName + "-ref");
if (!CollectionUtils.isEmpty(subElements)) {
ManagedArray array = new ManagedArray(className, subElements.size());
@@ -224,4 +224,13 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
return parentPath;
}
protected void validateDataPolicyShortcutAttributesMutualExclusion(final Element element,
final ParserContext parserContext) {
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
parserContext.getReaderContext().error(String.format(
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
element);
}
}
}

View File

@@ -49,7 +49,7 @@ class ClientRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutMutualExclusion(element, parserContext);
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
@@ -114,14 +114,6 @@ class ClientRegionParser extends AbstractRegionParser {
}
}
private void validateDataPolicyShortcutMutualExclusion(final Element element, final ParserContext parserContext) {
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
parserContext.getReaderContext().error(String.format(
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
element);
}
}
private void parseDiskStoreAttribute(final Element element, final BeanDefinitionBuilder builder) {
String diskStoreRefAttribute = element.getAttribute("disk-store-ref");

View File

@@ -39,6 +39,8 @@ class LocalRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);

View File

@@ -303,6 +303,7 @@ abstract class ParsingUtils {
setPropertyValue(element, regionAttributesBuilder, "cloning-enabled");
setPropertyValue(element, regionAttributesBuilder, "concurrency-level");
setPropertyValue(element, regionAttributesBuilder, "disk-synchronous");
setPropertyValue(element, regionAttributesBuilder, "enable-async-conflation");
setPropertyValue(element, regionAttributesBuilder, "enable-subscription-conflation");
setPropertyValue(element, regionAttributesBuilder, "ignore-jta", "ignoreJTA");
@@ -311,6 +312,7 @@ abstract class ParsingUtils {
setPropertyValue(element, regionAttributesBuilder, "key-constraint");
setPropertyValue(element, regionAttributesBuilder, "load-factor");
setPropertyValue(element, regionAttributesBuilder, "multicast-enabled");
setPropertyValue(element, regionAttributesBuilder, "publisher");
setPropertyValue(element, regionAttributesBuilder, "value-constraint");
String indexUpdateType = element.getAttribute("index-update-type");

View File

@@ -46,10 +46,13 @@ class PartitionedRegionParser extends AbstractRegionParser {
return PartitionedRegionFactoryBean.class;
}
@SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
super.doParse(element, builder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
@@ -63,11 +66,11 @@ class PartitionedRegionParser extends AbstractRegionParser {
PartitionAttributesFactoryBean.class);
parseColocatedWith(element, builder, partitionAttributesBuilder, "colocated-with");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies","redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "startup-recovery-delay");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets","totalNumBuckets");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets", "totalNumBuckets");
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-max-memory");
Element partitionResolverSubElement = DomUtils.getChildElementByTagName(element, "partition-resolver");

View File

@@ -40,13 +40,14 @@ class ReplicatedRegionParser extends AbstractRegionParser {
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
boolean subRegion) {
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
ParsingUtils.parseScope(element, builder);
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
RegionAttributesFactoryBean.class);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder,
subRegion);
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder, subRegion);
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
}

View File

@@ -129,8 +129,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
Object instance = instantiator.createInstance(entity, provider);
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper
.create(instance, conversionService);
final BeanWrapper<Object> wrapper = BeanWrapper.create(instance, conversionService);
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
@Override
@@ -168,7 +167,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
@Override
public boolean toData(Object value, final PdxWriter writer) {
GemfirePersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(value, conversionService);
final BeanWrapper<Object> wrapper = BeanWrapper.create(value, conversionService);
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
@SuppressWarnings({ "unchecked", "rawtypes" })

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2010-2013 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.support;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
/**
* The ClientRegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's ClientRegionShortcuts
* with Spring Data GemFire ClientRegionShortcutWrapper enumerated values.
* <p/>
* @author John Blum
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
* @since 1.4.0
*/
@SuppressWarnings("unused")
public enum ClientRegionShortcutWrapper {
CACHING_PROXY(ClientRegionShortcut.CACHING_PROXY),
CACHING_PROXY_HEAP_LRU(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU),
CACHING_PROXY_OVERFLOW(ClientRegionShortcut.CACHING_PROXY_OVERFLOW),
LOCAL(ClientRegionShortcut.LOCAL),
LOCAL_HEAP_LRU(ClientRegionShortcut.LOCAL_HEAP_LRU),
LOCAL_OVERFLOW(ClientRegionShortcut.LOCAL_OVERFLOW),
LOCAL_PERSISTENT(ClientRegionShortcut.LOCAL_PERSISTENT),
LOCAL_PERSISTENT_OVERFLOW(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
PROXY(ClientRegionShortcut.PROXY),
UNSPECIFIED(null);
private final ClientRegionShortcut clientRegionShortcut;
ClientRegionShortcutWrapper(final ClientRegionShortcut clientRegionShortcut) {
this.clientRegionShortcut = clientRegionShortcut;
}
public static ClientRegionShortcutWrapper valueOf(final ClientRegionShortcut clientRegionShortcut) {
for (ClientRegionShortcutWrapper wrapper : values()) {
if (ObjectUtils.nullSafeEquals(wrapper.getClientRegionShortcut(), clientRegionShortcut)) {
return wrapper;
}
}
return ClientRegionShortcutWrapper.UNSPECIFIED;
}
public ClientRegionShortcut getClientRegionShortcut() {
return clientRegionShortcut;
}
public boolean isCaching() {
return name().contains("CACHING");
}
public boolean isHeapLru() {
return name().contains("HEAP_LRU");
}
public boolean isLocal() {
return name().contains("LOCAL");
}
public boolean isOverflow() {
return name().contains("OVERFLOW");
}
public boolean isPersistent() {
return name().contains("PERSISTENT");
}
public boolean isPersistentOverflow() {
return name().contains("PERSISTENT_OVERFLOW");
}
public boolean isProxy() {
return name().contains("PROXY");
}
}

View File

@@ -0,0 +1,115 @@
/*
* Copyright 2010-2013 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.support;
import org.springframework.util.ObjectUtils;
import com.gemstone.gemfire.cache.RegionShortcut;
/**
* The RegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's RegionShortcuts
* with Spring Data GemFire RegionShortcutWrapper enumerated values.
* <p/>
*
* @author John Blum
* @see com.gemstone.gemfire.cache.RegionShortcut
* @since 1.4.0
*/
@SuppressWarnings("unused")
public enum RegionShortcutWrapper {
LOCAL(RegionShortcut.LOCAL),
LOCAL_HEAP_LRU(RegionShortcut.LOCAL_HEAP_LRU),
LOCAL_OVERFLOW(RegionShortcut.LOCAL_OVERFLOW),
LOCAL_PERSISTENT(RegionShortcut.LOCAL_PERSISTENT),
LOCAL_PERSISTENT_OVERFLOW(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
PARTITION(RegionShortcut.PARTITION),
PARTITION_HEAP_LRU(RegionShortcut.PARTITION_HEAP_LRU),
PARTITION_OVERFLOW(RegionShortcut.PARTITION_OVERFLOW),
PARTITION_PERSISTENT(RegionShortcut.PARTITION_PERSISTENT),
PARTITION_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW),
PARTITION_PROXY(RegionShortcut.PARTITION_PROXY),
PARTITION_PROXY_REDUNDANT(RegionShortcut.PARTITION_PROXY_REDUNDANT),
PARTITION_REDUNDANT(RegionShortcut.PARTITION_REDUNDANT),
PARTITION_REDUNDANT_HEAP_LRU(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU),
PARTITION_REDUNDANT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW),
PARTITION_REDUNDANT_PERSISTENT(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT),
PARTITION_REDUNDANT_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW),
REPLICATE(RegionShortcut.REPLICATE),
REPLICATE_HEAP_LRU(RegionShortcut.REPLICATE_HEAP_LRU),
REPLICATE_OVERFLOW(RegionShortcut.REPLICATE_OVERFLOW),
REPLICATE_PERSISTENT(RegionShortcut.REPLICATE_PERSISTENT),
REPLICATE_PERSISTENT_OVERFLOW(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW),
REPLICATE_PROXY(RegionShortcut.REPLICATE_PROXY),
UNSPECIFIED(null);
private final RegionShortcut regionShortcut;
RegionShortcutWrapper(final RegionShortcut regionShortcut) {
this.regionShortcut = regionShortcut;
}
public static RegionShortcutWrapper valueOf(final RegionShortcut regionShortcut) {
for (RegionShortcutWrapper wrapper : values()) {
if (ObjectUtils.nullSafeEquals(wrapper.getRegionShortcut(), regionShortcut)) {
return wrapper;
}
}
return RegionShortcutWrapper.UNSPECIFIED;
}
public boolean isHeapLru() {
return name().contains("HEAP_LRU");
}
public boolean isLocal() {
return name().contains("LOCAL");
}
public boolean isOverflow() {
return name().contains("OVERFLOW");
}
public boolean isPartition() {
return name().contains("PARTITION");
}
public boolean isPersistent() {
return name().contains("PERSISTENT");
}
public boolean isPersistentOverflow() {
return (isOverflow() && isPersistent());
}
public boolean isProxy() {
return name().contains("PROXY");
}
public boolean isRedundant() {
return name().contains("REDUNDANT");
}
public boolean isReplicate() {
return name().contains("REPLICATE");
}
public RegionShortcut getRegionShortcut() {
return regionShortcut;
}
}