SGF-289 - Enumeration restrictions (xsd:enumeration) should be avoided in the XML schema.

Removed the XSD enumeration restriction on the 'action' attribute of the 'expirationType' XSD complex-type definition used by the 'region-ttl', 'region-tti', 'entry-ttl', and 'entry-tti' elements in the 'baseReadOnlyRegionType' inside the Spring GemFire XML Schema (XSD).
This commit is contained in:
John Blum
2014-12-09 16:27:25 -08:00
parent 4a1a3bf64d
commit 844c630614
6 changed files with 334 additions and 49 deletions

View File

@@ -0,0 +1,94 @@
/*
* 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;
import com.gemstone.gemfire.cache.ExpirationAction;
/**
* The ExpirationActionType enum is a enumeration of GemFire Expiration Actions on expired Cache Region entries.
*
* @author John Blum
* @see com.gemstone.gemfire.cache.ExpirationAction
* @since 1.6.0
*/
@SuppressWarnings("unused")
public enum ExpirationActionType {
DESTROY(ExpirationAction.DESTROY),
INVALIDATE(ExpirationAction.INVALIDATE),
LOCAL_DESTROY(ExpirationAction.LOCAL_DESTROY),
LOCAL_INVALIDATE(ExpirationAction.LOCAL_INVALIDATE);
private final ExpirationAction expirationAction;
/**
* Constructs an instance of the ExpirationActionType enum initialized with the corresponding GemFire
* ExpirationAction value.
*
* @param expirationAction the GemFire ExpirationAction value.
* @see com.gemstone.gemfire.cache.ExpirationAction
*/
ExpirationActionType(final ExpirationAction expirationAction) {
this.expirationAction = expirationAction;
}
/**
* Returns the corresponding SDG ExpirationActionType enumerated value given a GemFire ExpirationAction.
*
* @param expirationAction the GemFire ExpirationAction instance used to determine the ExpirationActionType.
* @return a ExpirationActionType enumerated value given a GemFire ExpirationAction.
* @see com.gemstone.gemfire.cache.ExpirationAction
* @see #getExpirationAction()
*/
public static ExpirationActionType valueOf(final ExpirationAction expirationAction) {
for (ExpirationActionType expirationActionType : values()) {
if (expirationActionType.getExpirationAction().equals(expirationAction)) {
return expirationActionType;
}
}
return null;
}
/**
* Returns an ExpirationActionType for the given String value describing the enumerated value.
*
* @param value a String value describing the desired ExpirationActionType that is returned.
* @return an ExpirationActionType for the given String.
* @see java.lang.Enum#name()
* @see java.lang.String#equalsIgnoreCase(String)
*/
public static ExpirationActionType valueOfIgnoreCase(final String value) {
for (ExpirationActionType expirationActionType : values()) {
if (expirationActionType.name().equalsIgnoreCase(value)) {
return expirationActionType;
}
}
return null;
}
/**
* Gets the corresponding GemFire ExpirationAction for this enumerated value.
*
* @return a GemFire ExpirationAction instance corresponding to this enumerated value.
* @see com.gemstone.gemfire.cache.ExpirationAction
*/
public ExpirationAction getExpirationAction() {
return expirationAction;
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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;
import java.beans.PropertyEditorSupport;
import org.springframework.core.convert.converter.Converter;
/**
* The ExpirationActionTypeConverter class is a Spring Converter used to convert a String value into
* a corresponding ExpirationActionType enumerated value.
*
* @author John Blum
* @see java.beans.PropertyEditorSupport
* @see org.springframework.core.convert.converter.Converter
* @see org.springframework.data.gemfire.ExpirationActionType
* @since 1.6.0
*/
public class ExpirationActionTypeConverter extends PropertyEditorSupport implements Converter<String, ExpirationActionType> {
/* non-Javadoc */
private ExpirationActionType assertConverted(final String source, final ExpirationActionType expirationActionType) {
if (expirationActionType == null) {
throw new IllegalArgumentException(String.format("Source (%1$s) is not a valid ExpirationActionType!",
source));
}
return expirationActionType;
}
/**
* Sets the ExpirationActionType by parsing a given String. May raise a java.lang.IllegalArgumentException
* if either the String is badly formatted or the text cannot be expressed as a ExpirationActionType.
*
* @param text the String value to express as (convert to) a ExpirationActionType.
* @throws java.lang.IllegalArgumentException if the String value does not represent a valid ExpirationActionType.
* @see #convert(String)
* @see #setValue(Object)
*/
@Override
public void setAsText(final String text) throws IllegalArgumentException {
setValue(convert(text));
}
/**
* Converts the given String value into an appropriate ExpirationActionType.
*
* @param source the String value to convert into an ExpirationActionType.
* @return an ExpirationActionType for the given String value.
* @throws java.lang.IllegalArgumentException if the String value does not represent a valid ExpirationActionType.
* @see org.springframework.data.gemfire.ExpirationActionType#valueOfIgnoreCase(String)
*/
@Override
public ExpirationActionType convert(final String source) {
return assertConverted(source, ExpirationActionType.valueOfIgnoreCase(source));
}
}

View File

@@ -27,6 +27,8 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.Conventions;
import org.springframework.data.gemfire.EvictionAttributesFactoryBean;
import org.springframework.data.gemfire.EvictionType;
import org.springframework.data.gemfire.ExpirationActionType;
import org.springframework.data.gemfire.ExpirationActionTypeConverter;
import org.springframework.data.gemfire.GemfireUtils;
import org.springframework.data.gemfire.SubscriptionAttributesFactoryBean;
import org.springframework.data.gemfire.SubscriptionType;
@@ -290,6 +292,7 @@ abstract class ParsingUtils {
// turn on statistics
regionAttributesBuilder.addPropertyValue("statisticsEnabled", Boolean.TRUE);
}
return result;
}
@@ -380,24 +383,13 @@ abstract class ParsingUtils {
if (expirationElement != null) {
String timeoutAttribute = expirationElement.getAttribute("timeout");
String expirationTimeout = (StringUtils.hasText(timeoutAttribute) ? timeoutAttribute : null);
String expirationTimeout = (StringUtils.hasText(timeoutAttribute) ? timeoutAttribute : "0");
String actionAttribute = StringUtils.trimAllWhitespace(expirationElement.getAttribute("action"));
ExpirationAction expirationAction;
// TODO refactor this using an Enum and ExpirationActionConverter!
if ("DESTROY".equalsIgnoreCase(actionAttribute)) {
expirationAction = ExpirationAction.DESTROY;
}
else if ("LOCAL_DESTROY".equalsIgnoreCase(actionAttribute)) {
expirationAction = ExpirationAction.LOCAL_DESTROY;
}
else if ("LOCAL_INVALIDATE".equalsIgnoreCase(actionAttribute)) {
expirationAction = ExpirationAction.LOCAL_INVALIDATE;
}
else {
expirationAction = ExpirationAction.INVALIDATE;
}
ExpirationActionType expirationActionType = new ExpirationActionTypeConverter().convert(actionAttribute);
ExpirationAction expirationAction = (expirationActionType != null
? expirationActionType.getExpirationAction() : ExpirationAction.INVALIDATE);
BeanDefinitionBuilder expirationAttributes = BeanDefinitionBuilder.genericBeanDefinition(
ExpirationAttributes.class);

View File

@@ -1553,43 +1553,18 @@ Defines a template for creating multiple GemFire Local Regions that all share a
<xsd:attribute name="timeout" type="xsd:string" default="0">
<xsd:annotation>
<xsd:documentation><![CDATA[
The amount of time before the expiration action takes place. Defaults to zero (which means never timeout).
Number of seconds before a region or an entry expires. If timeout is not specified, it defaults to zero
(which means no expiration).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="action" default="INVALIDATE">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="INVALIDATE">
<xsd:annotation>
<xsd:documentation><![CDATA[
When the region or cached object expires, it is invalidated.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="DESTROY">
<xsd:annotation>
<xsd:documentation><![CDATA[
When the region or cached object expires, it is destroyed.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="LOCAL_INVALIDATE">
<xsd:annotation>
<xsd:documentation><![CDATA[
When the region or cached object expires, it is invalidated locally only. Not supported on partitioned regions.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="LOCAL_DESTROY">
<xsd:annotation>
<xsd:documentation><![CDATA[
When the region or cached object expires, it is destroyed locally only. Not supported on partitioned regions.
]]></xsd:documentation>
</xsd:annotation>
</xsd:enumeration>
</xsd:restriction>
</xsd:simpleType>
<xsd:attribute name="action" type="xsd:string" default="INVALIDATE">
<xsd:annotation>
<xsd:documentation><![CDATA[
Action that should take place when a Region or an Entry expires. Valid values include: DESTROY, INVALIDATE,
LOCAL_DESTROY, LOCAL_INVALIDATE. Note, the default GemFire Expiration Action is INVALIDATE.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<!-- -->

View File

@@ -0,0 +1,80 @@
/*
* 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;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Test;
/**
* The ExpirationActionTypeConverterTest class is a test suite of test cases testing the contract and functionality
* of the ExpirationActionTypeConverter class.
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.ExpirationActionTypeConverter
* @since 1.6.0
*/
public class ExpirationActionTypeConverterTest {
private final ExpirationActionTypeConverter converter = new ExpirationActionTypeConverter();
@After
public void tearDown() {
converter.setValue(null);
}
@Test
public void testConvert() {
assertEquals(ExpirationActionType.DESTROY, converter.convert("destroy"));
assertEquals(ExpirationActionType.INVALIDATE, converter.convert("InvalidAte"));
assertEquals(ExpirationActionType.LOCAL_DESTROY, converter.convert("LOCAL_dEsTrOy"));
assertEquals(ExpirationActionType.LOCAL_INVALIDATE, converter.convert("Local_Invalidate"));
}
@Test(expected = IllegalArgumentException.class)
public void testConvertThrowsIllegalArgumentException() {
try {
converter.convert("blow_up");
}
catch (IllegalArgumentException expected) {
assertEquals("Source (blow_up) is not a valid ExpirationActionType!", expected.getMessage());
throw expected;
}
}
@Test
public void testSetAsText() {
converter.setAsText("InValidAte");
assertEquals(ExpirationActionType.INVALIDATE, converter.getValue());
converter.setAsText("Local_Destroy");
assertEquals(ExpirationActionType.LOCAL_DESTROY, converter.getValue());
}
@Test(expected = IllegalArgumentException.class)
public void testSetAsTextThrowsIllegalArgumentException() {
try {
converter.setAsText("destruction");
}
catch (IllegalArgumentException expected) {
assertEquals("Source (destruction) is not a valid ExpirationActionType!", expected.getMessage());
throw expected;
}
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.junit.Test;
import com.gemstone.gemfire.cache.ExpirationAction;
/**
* The ExpirationActionTypeTest class is a test suite of test cases testing the contract and functionality
* of the ExpirationActionType enum.
*
* @author John Blum
* @see org.junit.Test
* @see org.springframework.data.gemfire.ExpirationActionType
* @since 1.6.0
*/
public class ExpirationActionTypeTest {
@Test
public void testValueOf() {
assertEquals(ExpirationActionType.DESTROY, ExpirationActionType.valueOf(ExpirationAction.DESTROY));
assertEquals(ExpirationActionType.INVALIDATE, ExpirationActionType.valueOf(ExpirationAction.INVALIDATE));
assertEquals(ExpirationActionType.LOCAL_DESTROY, ExpirationActionType.valueOf(ExpirationAction.LOCAL_DESTROY));
assertEquals(ExpirationActionType.LOCAL_INVALIDATE, ExpirationActionType.valueOf(ExpirationAction.LOCAL_INVALIDATE));
}
@Test
public void testValueOfExpirationActionOrdinalValues() {
try {
for (int ordinal = 0; ordinal < Integer.MAX_VALUE; ordinal++) {
assertNotNull(ExpirationActionType.valueOf(ExpirationAction.fromOrdinal(ordinal)));
}
}
catch (ArrayIndexOutOfBoundsException ignore) {
}
}
@Test
public void testValueOfIgnoreCase() {
assertEquals(ExpirationActionType.DESTROY, ExpirationActionType.valueOfIgnoreCase("destroy"));
assertEquals(ExpirationActionType.INVALIDATE, ExpirationActionType.valueOfIgnoreCase("Invalidate"));
assertEquals(ExpirationActionType.LOCAL_DESTROY, ExpirationActionType.valueOfIgnoreCase("LOCAL_DESTROY"));
assertEquals(ExpirationActionType.LOCAL_INVALIDATE, ExpirationActionType.valueOfIgnoreCase("Local_Invalidate"));
}
@Test
public void testValueOfIgnoreCaseWithInvalidStringValues() {
assertNull(ExpirationActionType.valueOfIgnoreCase("Invalid"));
assertNull(ExpirationActionType.valueOfIgnoreCase("local destroy"));
}
}