SGF-582 - Polish.

This commit is contained in:
John Blum
2017-01-11 12:54:18 -08:00
parent 3bc7d2e711
commit c2ab0c22b1
9 changed files with 365 additions and 204 deletions

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.mapping;
import java.beans.PropertyDescriptor;
@@ -24,9 +25,12 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.TypeInformation;
/**
* Spring Data {@link AbstractMappingContext} implementation defining entity mapping meta-data
* for GemFire persistent entities.
*
* @author Oliver Gierke
* @author John Blum
* @see org.springframework.data.mapping.context.AbstractMappingContext
*/
public class GemfireMappingContext extends AbstractMappingContext<GemfirePersistentEntity<?>, GemfirePersistentProperty> {
@@ -42,23 +46,23 @@ public class GemfireMappingContext extends AbstractMappingContext<GemfirePersist
setSimpleTypeHolder(new GemfireSimpleTypeHolder());
}
/*
* (non-Javadoc)
/**
* @inheritDoc
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
protected <T> GemfirePersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new GemfirePersistentEntity<T>(typeInformation);
return new GemfirePersistentEntity<>(typeInformation);
}
/*
* (non-Javadoc)
/**
* @inheritDoc
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.mapping.model.MutablePersistentEntity, org.springframework.data.mapping.model.SimpleTypeHolder)
*/
@Override
protected GemfirePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
protected GemfirePersistentProperty createPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
GemfirePersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new GemfirePersistentProperty(field, descriptor, owner, simpleTypeHolder);
return new GemfirePersistentProperty(field, propertyDescriptor, owner, simpleTypeHolder);
}
}

View File

@@ -19,23 +19,16 @@ package org.springframework.data.gemfire.mapping;
import static org.springframework.data.gemfire.util.SpringUtils.defaultIfEmpty;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.gemfire.mapping.annotation.ClientRegion;
import org.springframework.data.gemfire.mapping.annotation.LocalRegion;
import org.springframework.data.gemfire.mapping.annotation.PartitionRegion;
import org.springframework.data.gemfire.mapping.annotation.Region;
import org.springframework.data.gemfire.mapping.annotation.ReplicateRegion;
import org.springframework.data.mapping.IdentifierAccessor;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.IdPropertyIdentifierAccessor;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
/**
* {@link PersistentEntity} implementation adding custom GemFire persistent entity related metadata, such as the
@@ -54,61 +47,12 @@ public class GemfirePersistentEntity<T> extends BasicPersistentEntity<T, Gemfire
private final String regionName;
/**
* GET_ID_METHOD_NAME = "getId" Used to support getting the region key when the @Id annotation does not exist.
*/
private static final String GET_ID_METHOD_NAME = "getId";
/**
* Get the identifier access strategy object that determines the region key to use
*
* @return implementation of the Identifier access strategy with support to use the getId bean method.
*/
@Override
public IdentifierAccessor getIdentifierAccessor(Object bean) {
Assert.notNull(bean, "Target bean must not be null!");
Assert.isTrue(getType().isInstance(bean), "Target bean is not of type of the persistent entity!");
// Check if @Id access
if (hasIdProperty()) {
return new IdPropertyIdentifierAccessor(this, bean);
}
// use getId() method via a lamba function implementation of IdentifierAccessor
IdentifierAccessor getIdAccessor = () -> {
try {
Method getMethod = bean.getClass().getMethod(GET_ID_METHOD_NAME);
if (getMethod == null)
return null; // getId method not found
return getMethod.invoke(bean);
} catch (NoSuchMethodException e) {
return null;
} catch (SecurityException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} catch (IllegalArgumentException e) {
return null;
} catch (InvocationTargetException e) {
return null;
}
};
return getIdAccessor;
}
/* (non-Javadoc) */
protected static Annotation resolveRegionAnnotation(Class<?> persistentEntityType) {
for (Class<? extends Annotation> regionAnnotationType : Region.REGION_ANNOTATION_TYPES) {
Annotation regionAnnotation = AnnotatedElementUtils.getMergedAnnotation(persistentEntityType,
regionAnnotationType);
Annotation regionAnnotation = AnnotatedElementUtils.getMergedAnnotation(
persistentEntityType, regionAnnotationType);
if (regionAnnotation != null) {
return regionAnnotation;
@@ -122,16 +66,24 @@ public class GemfirePersistentEntity<T> extends BasicPersistentEntity<T, Gemfire
protected static String resolveRegionName(Class<?> persistentEntityType, Annotation regionAnnotation) {
String regionName = (regionAnnotation != null
? AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes(regionAnnotation)).getString("value")
: null);
? getAnnotationAttributeStringValue(regionAnnotation, "value") : null);
return defaultIfEmpty(regionName, persistentEntityType.getSimpleName());
}
/* (non-Javadoc) */
protected static String getAnnotationAttributeStringValue(Annotation annotation, String attributeName) {
return AnnotationAttributes.fromMap(AnnotationUtils.getAnnotationAttributes(annotation))
.getString(attributeName);
}
/**
* Creates a new {@link GemfirePersistentEntity} for the given {@link TypeInformation}.
* Constructs a new instance of {@link GemfirePersistentEntity} initialized with the given {@link TypeInformation}
* describing the domain object (entity) {@link Class} type.
*
* @param information must not be {@literal null}.
* @param information {@link TypeInformation} meta-data describing the domain object (entity) {@link Class} type.
* @throws IllegalArgumentException if the given {@link TypeInformation} is {@literal null}.
* @see org.springframework.data.util.TypeInformation
*/
public GemfirePersistentEntity(TypeInformation<T> information) {
super(information);
@@ -143,17 +95,17 @@ public class GemfirePersistentEntity<T> extends BasicPersistentEntity<T, Gemfire
}
/**
* Returns the {@link Region} annotation used to annotate this {@link PersistentEntity} or {@literal null} if this
* {@link PersistentEntity} was not annotated with a {@link Region} annotation.
* Returns the {@link Region} {@link Annotation} used to annotate this {@link PersistentEntity} or {@literal null}
* if this {@link PersistentEntity} was not annotated with a {@link Region} {@link Annotation}.
*
* @param <T> concrete {@link Class} type of the Region {@link Annotation}.
* @return the {@link Region} annotation used to annotate this {@link PersistentEntity} or {@literal null} if this
* {@link PersistentEntity} was not annotated with a {@link Region} annotation.
* @see ClientRegion
* @see LocalRegion
* @see PartitionRegion
* @see ReplicateRegion
* @see Region
* @param <T> concrete {@link Class} type of the {@link Region} {@link Annotation}.
* @return the {@link Region} {@link Annotation} used to annotate this {@link PersistentEntity} or {@literal null}
* if this {@link PersistentEntity} was not annotated with a {@link Region} {@link Annotation}.
* @see org.springframework.data.gemfire.mapping.annotation.ClientRegion
* @see org.springframework.data.gemfire.mapping.annotation.LocalRegion
* @see org.springframework.data.gemfire.mapping.annotation.PartitionRegion
* @see org.springframework.data.gemfire.mapping.annotation.ReplicateRegion
* @see org.springframework.data.gemfire.mapping.annotation.Region
* @see java.lang.annotation.Annotation
*/
@SuppressWarnings("unchecked")
@@ -162,11 +114,11 @@ public class GemfirePersistentEntity<T> extends BasicPersistentEntity<T, Gemfire
}
/**
* Returns the {@link Class} type of the Region {@link Annotation} or {@literal null} if this {@link PersistentEntity}
* was not annotated with a Region {@link Annotation}.
* Returns the {@link Class} type of the {@link Region} {@link Annotation} used to annotate this entity
* or {@literal null} if this entity was not annotated with a {@link Region} {@link Annotation}.
*
* @return the {@link Class} type of the Region {@link Annotation} or {@literal null} if this {@link PersistentEntity}
* was not annotated with a Region {@link Annotation}.
* @return the {@link Class} type of the {@link Region} {@link Annotation} used to annotate this entity
* or {@literal null} if this entity was not annotated with a {@link Region} {@link Annotation}.
* @see java.lang.annotation.Annotation#annotationType()
* @see #getRegionAnnotation()
*/
@@ -176,12 +128,47 @@ public class GemfirePersistentEntity<T> extends BasicPersistentEntity<T, Gemfire
}
/**
* Returns the name of the {@link Region} in which this {@link PersistentEntity} will be stored.
* Returns the name of the {@link org.apache.geode.cache.Region} in which this {@link PersistentEntity}
* will be stored.
*
* @return the name of the {@link Region} in which this {@link PersistentEntity} will be stored.
* @return the name of the {@link org.apache.geode.cache.Region} in which this {@link PersistentEntity}
* will be stored.
* @see org.apache.geode.cache.Region#getName()
*/
public String getRegionName() {
return this.regionName;
}
/**
* @inheritDoc
* @see org.springframework.data.mapping.model.BasicPersistentEntity#returnPropertyIfBetterIdPropertyCandidateOrNull(PersistentProperty)
*/
@Override
protected GemfirePersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(
GemfirePersistentProperty property) {
if (property.isIdProperty()) {
if (hasIdProperty()) {
GemfirePersistentProperty currentIdProperty = getIdProperty();
if (currentIdProperty.isExplicitIdProperty()) {
if (property.isExplicitIdProperty()) {
throw new MappingException(String.format(
"Attempt to add explicit id property [%1$s] but already have id property [%2$s] registered as explicit;"
+ " Please check your object [%3$s] mapping configuration",
property.getName(), currentIdProperty.getName(), getType().getName()));
}
return null;
}
return (property.isExplicitIdProperty() ? property : null);
}
else {
return property;
}
}
return null;
}
}

View File

@@ -13,11 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.mapping;
import static org.springframework.data.gemfire.util.CollectionUtils.asSet;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.Set;
import org.springframework.data.annotation.Id;
import org.springframework.data.gemfire.mapping.model.GemfireSimpleTypeHolder;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PersistentEntity;
@@ -27,11 +32,13 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
* {@link PersistentProperty} implementation to for Gemfire related metadata.
*
*
* @author Oliver Gierke
*/
public class GemfirePersistentProperty extends AnnotationBasedPersistentProperty<GemfirePersistentProperty> {
protected static final Set<String> SUPPORTED_IDENTIFIER_NAMES = asSet("id");
/* (non-Javadoc) */
private static SimpleTypeHolder resolveSimpleTypeHolder(SimpleTypeHolder source) {
return (source instanceof GemfireSimpleTypeHolder ? source
@@ -39,26 +46,59 @@ public class GemfirePersistentProperty extends AnnotationBasedPersistentProperty
}
/**
* Constructs an instance of the GemfirePersistentProperty with entity information.
* Constructs an instance of the {@link GemfirePersistentProperty} initialized with entity
* persistent property information (meta-data).
*
* @param field the entity field corresponding to the persistent property.
* @param propertyDescriptor PropertyDescriptor for the entity's persistent property.
* @param owner the entity owning the persistent property.
* @param simpleTypeHolder type holder for primitive types.
* @param field entity {@link Field} corresponding to the persistent property.
* @param propertyDescriptor {@link PropertyDescriptor} for the entity's persistent property.
* @param owner entity owning the persistent property.
* @param simpleTypeHolder {@link SimpleTypeHolder} used to handle primitive types.
* @see org.springframework.data.mapping.model.SimpleTypeHolder
* @see org.springframework.data.mapping.PersistentEntity
* @see java.beans.PropertyDescriptor
* @see java.lang.reflect.Field
*/
public GemfirePersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, GemfirePersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, resolveSimpleTypeHolder(simpleTypeHolder));
}
/*
* (non-Javadoc)
*
* @see org.springframework.data.mapping.model.AbstractPersistentProperty#
* createAssociation()
/**
* @inheritDoc
*/
@Override
protected Association<GemfirePersistentProperty> createAssociation() {
return new Association<GemfirePersistentProperty>(this, null);
return new Association<>(this, null);
}
/**
* Determines whether this {@link GemfirePersistentProperty} explicitly identifies an entity property identifier,
* one in which the user explicitly annotated a entity class member (field or getter/setter).
*
* @return a boolean value indicating whether this {@link GemfirePersistentProperty} explicitly identifies
* an entity property identifier.
* @see org.springframework.data.annotation.Id
* @see #isAnnotationPresent(Class)
*/
public boolean isExplicitIdProperty() {
return isAnnotationPresent(Id.class);
}
/**
* @inheritDoc
* @see org.springframework.data.mapping.model.AnnotationBasedPersistentProperty#isIdProperty()
*/
@Override
public boolean isIdProperty() {
return (super.isIdProperty() || SUPPORTED_IDENTIFIER_NAMES.contains(getName()));
}
/**
* @inheritDoc
*/
@Override
public boolean usePropertyAccess() {
return (super.usePropertyAccess() || (getField() == null && this.propertyDescriptor != null));
}
}

View File

@@ -178,14 +178,14 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
*/
@Override
public Object fromData(final Class<?> type, final PdxReader reader) {
final GemfirePersistentEntity<?> entity = getPersistentEntity(type);
final Object instance = getInstantiatorFor(entity).createInstance(entity,
new PersistentEntityParameterValueProvider<GemfirePersistentProperty>(entity,
new GemfirePropertyValueProvider(reader), null));
new PersistentEntityParameterValueProvider<>(entity, new GemfirePropertyValueProvider(reader), null));
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance),
getConversionService());
final PersistentPropertyAccessor propertyAccessor =
new ConvertingPropertyAccessor(entity.getPropertyAccessor(instance), getConversionService());
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
public void doWithPersistentProperty(GemfirePersistentProperty persistentProperty) {
@@ -209,7 +209,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
log.debug(String.format("with value [%1$s]", value));
}
accessor.setProperty(persistentProperty, value);
propertyAccessor.setProperty(persistentProperty, value);
}
catch (Exception e) {
throw new MappingException(String.format(
@@ -221,7 +221,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
}
});
return accessor.getBean();
return propertyAccessor.getBean();
}
/**
@@ -229,39 +229,40 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
*/
@Override
public boolean toData(final Object value, final PdxWriter writer) {
GemfirePersistentEntity<?> entity = getPersistentEntity(value.getClass());
final PersistentPropertyAccessor accessor = new ConvertingPropertyAccessor(entity.getPropertyAccessor(value),
getConversionService());
GemfirePersistentEntity<?> entity = getPersistentEntity(value);
final PersistentPropertyAccessor propertyAccessor =
new ConvertingPropertyAccessor(entity.getPropertyAccessor(value), getConversionService());
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
@Override
@SuppressWarnings("unchecked")
@Override @SuppressWarnings("unchecked")
public void doWithPersistentProperty(GemfirePersistentProperty persistentProperty) {
PdxSerializer customSerializer = getCustomSerializer(persistentProperty.getType());
Object propertyValue = null;
try {
propertyValue = accessor.getProperty(persistentProperty);
propertyValue = propertyAccessor.getProperty(persistentProperty);
if (log.isDebugEnabled()) {
log.debug(String.format("serializing value [%1$s] of property [%2$s] for entity of type [%3$s] to PDX%4$s",
propertyValue, persistentProperty.getName(), value.getClass(), (customSerializer != null ?
String.format(" using custom PdxSerializer [%1$s]", customSerializer) : "")));
log.debug(String.format("Serializing entity property [%1$s] value [%2$s] of type [%3$s] to PDX%4$s",
persistentProperty.getName(), propertyValue, value.getClass(), (customSerializer != null ?
String.format(" using custom PdxSerializer [%s]", customSerializer) : "")));
}
if (customSerializer != null) {
customSerializer.toData(propertyValue, writer);
}
else {
writer.writeField(persistentProperty.getName(), propertyValue, (Class) persistentProperty.getType());
writer.writeField(persistentProperty.getName(), propertyValue,
(Class<Object>) persistentProperty.getType());
}
}
catch (Exception e) {
throw new MappingException(String.format(
"while serializing value [%1$s] of property [%2$s] for entity of type [%3$s] to PDX%4$s",
propertyValue, persistentProperty.getName(), value.getClass(),
"Error while serializing entity property [%1$s] value [%2$s] of type [%3$s] to PDX%4$s",
persistentProperty.getName(), propertyValue, value.getClass(),
(customSerializer != null ? String.format(" using custom PdxSerializer [%1$s].",
customSerializer.getClass().getName()) : ".")), e);
}
@@ -304,12 +305,24 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
}
/**
* Looks up and returns the PersistentEntity meta-data for the given entity class type.
* Looks up and returns the {@link PersistentEntity} meta-data for the given entity object.
*
* @param entityType the Class type of the actual persistent entity, application domain object class.
* @return the PersistentEntity meta-data for the given entity class type.
* @see #getMappingContext()
* @param entity actual persistent entity, application domain object.
* @return the {@link PersistentEntity} meta-data for the given entity object.
* @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
* @see #getPersistentEntity(Class)
*/
protected GemfirePersistentEntity<?> getPersistentEntity(Object entity) {
return getPersistentEntity(entity.getClass());
}
/**
* Looks up and returns the {@link PersistentEntity} meta-data for the given entity {@link Class} type.
*
* @param entityType {@link Class} type of the actual persistent entity, application domain object {@link Class}.
* @return the {@link PersistentEntity} meta-data for the given entity {@link Class} type.
* @see org.springframework.data.gemfire.mapping.GemfirePersistentEntity
* @see #getMappingContext()
*/
protected GemfirePersistentEntity<?> getPersistentEntity(Class<?> entityType) {
return getMappingContext().getPersistentEntity(entityType);

View File

@@ -16,6 +16,8 @@
package org.springframework.data.gemfire.util;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -82,6 +84,26 @@ public abstract class CollectionUtils extends org.springframework.util.Collectio
return Collections.unmodifiableSet(set);
}
/**
* Null-safe method to determines whether the given {@link Collection} contains any elements from the given array.
*
* @param collection {@link Collection} to evaluate
* @param elements array of elements to evaluate.
* @return a boolean value indicating whether the collection contains at least 1 element from the given array.
* @see java.util.Collection#contains(Object)
*/
public static boolean containsAny(Collection<?> collection, Object... elements) {
if (collection != null) {
for (Object element : nullSafeArray(elements, Object.class)) {
if (collection.contains(element)) {
return true;
}
}
}
return false;
}
/**
* Returns the given {@link Iterable} if not {@literal null} or empty, otherwise returns the {@code defaultIterable}.
*