DATAREDIS-595 - Integrate DATACMNS Java 8 upgrade.

Integrate DATACMNS-867 and DATAKV-159 branches.
This commit is contained in:
Christoph Strobl
2017-01-24 13:16:50 +01:00
parent d0e52dd9f0
commit 00b4009553
21 changed files with 316 additions and 330 deletions

View File

@@ -23,6 +23,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -58,6 +59,7 @@ import org.springframework.data.redis.core.convert.RedisData;
import org.springframework.data.redis.core.convert.ReferenceResolverImpl;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.redis.core.mapping.RedisPersistentProperty;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.util.ByteUtils;
@@ -204,10 +206,10 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
rdo.setId(converter.getConversionService().convert(id, String.class));
if (!(item instanceof RedisData)) {
KeyValuePersistentProperty idProperty = converter.getMappingContext().getPersistentEntity(item.getClass())
.getIdProperty();
converter.getMappingContext().getPersistentEntity(item.getClass()).getPropertyAccessor(item)
.setProperty(idProperty, id);
KeyValuePersistentProperty idProperty = converter.getMappingContext().getPersistentEntity(item.getClass()).get()
.getIdProperty().get();
converter.getMappingContext().getPersistentEntity(item.getClass()).get().getPropertyAccessor(item)
.setProperty(idProperty, Optional.ofNullable(id));
}
}
@@ -350,7 +352,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
return getAllOf(keyspace, -1, -1);
}
public List<?> getAllOf(final Serializable keyspace, int offset, int rows) {
public List<?> getAllOf(final Serializable keyspace, long offset, int rows) {
final byte[] binKeyspace = toBytes(keyspace);
@@ -372,7 +374,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
offset = Math.max(0, offset);
if (offset >= 0 && rows > 0) {
keys = keys.subList(offset, Math.min(offset + rows, keys.size()));
keys = keys.subList((int)offset, Math.min((int)offset + rows, keys.size()));
}
for (byte[] key : keys) {
@@ -426,7 +428,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
public void update(final PartialUpdate<?> update) {
final RedisPersistentEntity<?> entity = this.converter.getMappingContext().getPersistentEntity(update.getTarget());
final RedisPersistentEntity<?> entity = this.converter.getMappingContext().getPersistentEntity(update.getTarget()).get();
final String keyspace = entity.getKeySpace();
final Object id = update.getId();
@@ -616,29 +618,33 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
return target;
}
RedisPersistentEntity<?> entity = this.converter.getMappingContext().getPersistentEntity(target.getClass());
RedisPersistentEntity<?> entity = this.converter.getMappingContext().getPersistentEntity(target.getClass()).get();
if (entity.hasExplictTimeToLiveProperty()) {
PersistentProperty<?> ttlProperty = entity.getExplicitTimeToLiveProperty();
Optional<RedisPersistentProperty> ttlProperty = entity.getExplicitTimeToLiveProperty();
if(!ttlProperty.isPresent()) {
return target;
}
final TimeToLive ttl = ttlProperty.findAnnotation(TimeToLive.class);
final Optional<TimeToLive> ttl = ttlProperty.get().findAnnotation(TimeToLive.class);
Long timeout = redisOps.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
if (ObjectUtils.nullSafeEquals(TimeUnit.SECONDS, ttl.unit())) {
if (ObjectUtils.nullSafeEquals(TimeUnit.SECONDS, ttl.get().unit())) {
return connection.ttl(key);
}
return connection.pTtl(key, ttl.unit());
return connection.pTtl(key, ttl.get().unit());
}
});
if (timeout != null || !ttlProperty.getType().isPrimitive()) {
entity.getPropertyAccessor(target).setProperty(ttlProperty,
converter.getConversionService().convert(timeout, ttlProperty.getType()));
if (timeout != null || !ttlProperty.get().getType().isPrimitive()) {
entity.getPropertyAccessor(target).setProperty(ttlProperty.get(),
Optional.ofNullable(converter.getConversionService().convert(timeout, ttlProperty.get().getType())));
}
}

View File

@@ -19,6 +19,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.springframework.data.keyvalue.core.KeyValueAdapter;
import org.springframework.data.keyvalue.core.KeyValueCallback;
@@ -100,9 +101,9 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
String idToUse = adapter.getConverter().getConversionService().canConvert(id.getClass(), String.class)
? adapter.getConverter().getConversionService().convert(id, String.class) : id.toString();
T candidate = findById(idToUse, type);
if (candidate != null) {
result.add(candidate);
Optional<T> candidate = findById(idToUse, type);
if (candidate.isPresent()) {
result.add(candidate.get());
}
}

View File

@@ -76,7 +76,7 @@ class RedisQueryEngine extends QueryEngine<RedisKeyValueAdapter, RedisOperationC
*/
@Override
@SuppressWarnings("unchecked")
public <T> Collection<T> execute(final RedisOperationChain criteria, final Comparator<?> sort, final int offset,
public <T> Collection<T> execute(final RedisOperationChain criteria, final Comparator<?> sort, final long offset,
final int rows, final Serializable keyspace, Class<T> type) {
if (criteria == null
@@ -116,7 +116,7 @@ class RedisQueryEngine extends QueryEngine<RedisKeyValueAdapter, RedisOperationC
return Collections.emptyMap();
}
int offsetToUse = Math.max(0, offset);
int offsetToUse = Math.max(0, (int) offset);
if (rows > 0) {
allKeys = allKeys.subList(Math.max(0, offsetToUse), Math.min(offsetToUse + rows, allKeys.size()));
}
@@ -154,7 +154,7 @@ class RedisQueryEngine extends QueryEngine<RedisKeyValueAdapter, RedisOperationC
* @see org.springframework.data.keyvalue.core.QueryEngine#execute(java.lang.Object, java.lang.Object, int, int, java.io.Serializable)
*/
@Override
public Collection<?> execute(final RedisOperationChain criteria, Comparator<?> sort, int offset, int rows,
public Collection<?> execute(final RedisOperationChain criteria, Comparator<?> sort, long offset, int rows,
final Serializable keyspace) {
return execute(criteria, sort, offset, rows, keyspace, Object.class);
}

View File

@@ -22,8 +22,10 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -36,14 +38,13 @@ import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.util.CacheValue;
import org.springframework.util.Assert;
/**
* Value object to capture custom conversion. That is essentially a {@link List} of converters and some additional logic
* around them.
*
* @author Oliver Gierke
* @author Olivyer Gierke
* @author Thomas Darimont
* @author Christoph Strobl
* @since 1.7
@@ -61,9 +62,9 @@ public class CustomConversions {
private final List<Object> converters;
private final Map<ConvertiblePair, CacheValue<Class<?>>> customReadTargetTypes;
private final Map<ConvertiblePair, CacheValue<Class<?>>> customWriteTargetTypes;
private final Map<Class<?>, CacheValue<Class<?>>> rawWriteTargetTypes;
private final Map<ConvertiblePair, Optional<Class<?>>> customReadTargetTypes;
private final Map<ConvertiblePair, Optional<Class<?>>> customWriteTargetTypes;
private final Map<Class<?>, Optional<Class<?>>> rawWriteTargetTypes;
/**
* Creates an empty {@link CustomConversions} object.
@@ -84,9 +85,9 @@ public class CustomConversions {
this.readingPairs = new LinkedHashSet<ConvertiblePair>();
this.writingPairs = new LinkedHashSet<ConvertiblePair>();
this.customSimpleTypes = new HashSet<Class<?>>();
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, CacheValue<Class<?>>>();
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, CacheValue<Class<?>>>();
this.customReadTargetTypes = new ConcurrentHashMap<ConvertiblePair, Optional<Class<?>>>();
this.customWriteTargetTypes = new ConcurrentHashMap<ConvertiblePair, Optional<Class<?>>>();
this.rawWriteTargetTypes = new ConcurrentHashMap<Class<?>, Optional<Class<?>>>();
List<Object> toRegister = new ArrayList<Object>();
@@ -204,7 +205,7 @@ public class CustomConversions {
* Registers the given {@link ConvertiblePair} as reading or writing pair depending on the type sides being basic
* Redis types.
*
* @param pair
* @param converterRegistration
*/
private void register(ConverterRegistration converterRegistration) {
@@ -239,13 +240,8 @@ public class CustomConversions {
*/
public Class<?> getCustomWriteTarget(final Class<?> sourceType) {
return getOrCreateAndCache(sourceType, rawWriteTargetTypes, new Producer() {
@Override
public Class<?> get() {
return getCustomTarget(sourceType, null, writingPairs);
}
});
return getOrCreateAndCache(sourceType, rawWriteTargetTypes,
() -> getCustomTarget(sourceType, null, writingPairs).isPresent() ? (Class) getCustomTarget(sourceType, null, writingPairs).get() : null);
}
/**
@@ -264,13 +260,7 @@ public class CustomConversions {
}
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customWriteTargetTypes,
new Producer() {
@Override
public Class<?> get() {
return getCustomTarget(sourceType, requestedTargetType, writingPairs);
}
});
() -> (Class) getCustomTarget(sourceType, requestedTargetType, writingPairs).get());
}
/**
@@ -323,13 +313,7 @@ public class CustomConversions {
}
return getOrCreateAndCache(new ConvertiblePair(sourceType, requestedTargetType), customReadTargetTypes,
new Producer() {
@Override
public Class<?> get() {
return getCustomTarget(sourceType, requestedTargetType, readingPairs);
}
});
() -> getCustomTarget(sourceType, requestedTargetType, readingPairs).isPresent() ? ((Class) getCustomTarget(sourceType, requestedTargetType, readingPairs).get()) : null);
}
/**
@@ -341,54 +325,41 @@ public class CustomConversions {
* @param pairs must not be {@literal null}.
* @return
*/
private static Class<?> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
private static Optional<Class<?>> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
Collection<ConvertiblePair> pairs) {
Assert.notNull(sourceType, "SourceType must not be null!");
Assert.notNull(pairs, "Convertible pairs must not be null!");
if (requestedTargetType != null && pairs.contains(new ConvertiblePair(sourceType, requestedTargetType))) {
return requestedTargetType;
return Optional.of(requestedTargetType);
}
for (ConvertiblePair typePair : pairs) {
if (typePair.getSourceType().isAssignableFrom(sourceType)) {
Class<?> targetType = typePair.getTargetType();
if (requestedTargetType == null || targetType.isAssignableFrom(requestedTargetType)) {
return targetType;
return Optional.of(targetType);
}
}
}
return null;
return Optional.empty();
}
/**
* Will try to find a value for the given key in the given cache or produce one using the given {@link Producer} and
* Will try to find a value for the given key in the given cache or produce one using the given {@link Supplier} and
* store it in the cache.
*
* @param key the key to lookup a potentially existing value, must not be {@literal null}.
* @param cache the cache to find the value in, must not be {@literal null}.
* @param producer the {@link Producer} to create values to cache, must not be {@literal null}.
* @param producer the {@link Supplier} to create values to cache, must not be {@literal null}.
* @return
*/
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, CacheValue<Class<?>>> cache, Producer producer) {
CacheValue<Class<?>> cacheValue = cache.get(key);
if (cacheValue != null) {
return cacheValue.getValue();
}
Class<?> type = producer.get();
cache.put(key, CacheValue.<Class<?>> ofNullable(type));
return type;
}
private interface Producer {
Class<?> get();
private static <T> Class<?> getOrCreateAndCache(T key, Map<T, Optional<Class<?>>> cache,
Supplier<Class<T>> producer) {
Optional<Class<?>> foo = cache.computeIfAbsent(key, t -> Optional.ofNullable(producer.get()));
return foo.isPresent() ? foo.get() : null;
}
/**
@@ -407,7 +378,7 @@ public class CustomConversions {
*
* @param convertiblePair must not be {@literal null}.
* @param isReading whether to force to consider the converter for reading.
* @param isWritingwhether to force to consider the converter for reading.
* @param isWriting whether to force to consider the converter for reading.
*/
public ConverterRegistration(ConvertiblePair convertiblePair, boolean isReading, boolean isWriting) {

View File

@@ -25,6 +25,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -41,8 +42,7 @@ import org.springframework.data.convert.EntityInstantiators;
import org.springframework.data.convert.TypeAliasAccessor;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PersistentPropertyAccessor;
@@ -58,6 +58,7 @@ import org.springframework.data.redis.core.PartialUpdate.UpdateCommand;
import org.springframework.data.redis.core.index.Indexed;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.redis.core.mapping.RedisPersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -176,11 +177,10 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
return null;
}
TypeInformation<?> readType = typeMapper.readType(source);
TypeInformation<?> typeToUse = readType != null ? readType : ClassTypeInformation.from(type);
final RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(typeToUse);
TypeInformation<?> readType = typeMapper.readType(source).orElse(ClassTypeInformation.from(type));
final Optional<RedisPersistentEntity<?>> entity = mappingContext.getPersistentEntity(readType);
if (customConversions.hasCustomReadTarget(Map.class, typeToUse.getType())) {
if (customConversions.hasCustomReadTarget(Map.class, readType.getType())) {
Map<String, byte[]> partial = new HashMap<String, byte[]>();
@@ -193,35 +193,37 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
} else {
partial.putAll(source.getBucket().asMap());
}
R instance = (R) conversionService.convert(partial, typeToUse.getType());
R instance = (R) conversionService.convert(partial, readType.getType());
if (entity.hasIdProperty()) {
entity.getPropertyAccessor(instance).setProperty(entity.getIdProperty(), source.getId());
if (entity.isPresent() && entity.get().hasIdProperty()) {
entity.get().getPropertyAccessor(instance).setProperty(entity.get().getIdProperty().get(),
Optional.ofNullable(source.getId()));
}
return instance;
}
if (conversionService.canConvert(byte[].class, typeToUse.getType())) {
if (conversionService.canConvert(byte[].class, readType.getType())) {
return (R) conversionService.convert(source.getBucket().get(StringUtils.hasText(path) ? path : "_raw"),
typeToUse.getType());
readType.getType());
}
EntityInstantiator instantiator = entityInstantiators.getInstantiatorFor(entity);
EntityInstantiator instantiator = entityInstantiators.getInstantiatorFor(entity.get());
Object instance = instantiator.createInstance((RedisPersistentEntity<?>) entity,
new PersistentEntityParameterValueProvider<KeyValuePersistentProperty>(entity,
new ConverterAwareParameterValueProvider(path, source, conversionService), this.conversionService));
Object instance = instantiator.createInstance((RedisPersistentEntity<RedisPersistentProperty>) entity.get(),
new PersistentEntityParameterValueProvider<RedisPersistentProperty>(entity.get(),
new ConverterAwareParameterValueProvider(path, source, conversionService),
Optional.of(this.conversionService)));
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance);
final PersistentPropertyAccessor accessor = entity.get().getPropertyAccessor(instance);
entity.doWithProperties(new PropertyHandler<KeyValuePersistentProperty>() {
entity.get().doWithProperties(new PropertyHandler<RedisPersistentProperty>() {
@Override
public void doWithPersistentProperty(KeyValuePersistentProperty persistentProperty) {
public void doWithPersistentProperty(RedisPersistentProperty persistentProperty) {
String currentPath = !path.isEmpty() ? path + "." + persistentProperty.getName() : persistentProperty.getName();
PreferredConstructor<?, KeyValuePersistentProperty> constructor = entity.getPersistenceConstructor();
PreferredConstructor<?, RedisPersistentProperty> constructor = entity.get().getPersistenceConstructor().get();
if (constructor.isConstructorParameter(persistentProperty)) {
return;
@@ -240,22 +242,23 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
if (targetValue != null) {
accessor.setProperty(persistentProperty, targetValue);
accessor.setProperty(persistentProperty, Optional.ofNullable(targetValue));
}
}
else if (persistentProperty.isCollectionLike()) {
Object targetValue = readCollectionOrArray(currentPath, persistentProperty.getType(),
persistentProperty.getTypeInformation().getComponentType().getActualType().getType(), source.getBucket());
persistentProperty.getTypeInformation().getComponentType().get().getActualType().getType(),
source.getBucket());
if (targetValue != null) {
accessor.setProperty(persistentProperty, targetValue);
accessor.setProperty(persistentProperty, Optional.ofNullable(targetValue));
}
} else if (persistentProperty.isEntity() && !conversionService.canConvert(byte[].class,
persistentProperty.getTypeInformation().getActualType().getType())) {
Class<?> targetType = persistentProperty.getTypeInformation().getActualType().getType();
Class<R> targetType = (Class<R>) persistentProperty.getTypeInformation().getActualType().getType();
Bucket bucket = source.getBucket().extract(currentPath + ".");
@@ -266,38 +269,41 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
newBucket.getBucket().put(TYPE_HINT_ALIAS, type);
}
accessor.setProperty(persistentProperty, readInternal(currentPath, targetType, newBucket));
R val = readInternal(currentPath, targetType, newBucket);
accessor.setProperty(persistentProperty, Optional.ofNullable(val));
} else {
if (persistentProperty.isIdProperty() && StringUtils.isEmpty(path.isEmpty())) {
if (source.getBucket().get(currentPath) == null) {
accessor.setProperty(persistentProperty,
fromBytes(source.getBucket().get(currentPath), persistentProperty.getActualType()));
Optional.of(fromBytes(source.getBucket().get(currentPath), persistentProperty.getActualType())));
} else {
accessor.setProperty(persistentProperty, source.getId());
accessor.setProperty(persistentProperty, Optional.ofNullable(source.getId()));
}
}
Class<?> typeToUse = getTypeHint(currentPath, source.getBucket(), persistentProperty.getActualType());
accessor.setProperty(persistentProperty, fromBytes(source.getBucket().get(currentPath), typeToUse));
accessor.setProperty(persistentProperty,
Optional.ofNullable(fromBytes(source.getBucket().get(currentPath), typeToUse)));
}
}
});
readAssociation(path, source, entity, accessor);
readAssociation(path, source, entity.get(), accessor);
return (R) instance;
}
private void readAssociation(final String path, final RedisData source, final KeyValuePersistentEntity<?> entity,
private void readAssociation(final String path, final RedisData source, final RedisPersistentEntity<?> entity,
final PersistentPropertyAccessor accessor) {
entity.doWithAssociations(new AssociationHandler<KeyValuePersistentProperty>() {
entity.doWithAssociations(new AssociationHandler<RedisPersistentProperty>() {
@Override
public void doWithAssociation(Association<KeyValuePersistentProperty> association) {
public void doWithAssociation(Association<RedisPersistentProperty> association) {
String currentPath = !path.isEmpty() ? path + "." + association.getInverse().getName()
: association.getInverse().getName();
@@ -321,7 +327,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
}
accessor.setProperty(association.getInverse(), target);
accessor.setProperty(association.getInverse(), Optional.ofNullable(target));
} else {
@@ -338,7 +344,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
if (!CollectionUtils.isEmpty(rawHash)) {
accessor.setProperty(association.getInverse(),
read(association.getInverse().getActualType(), new RedisData(rawHash)));
Optional.ofNullable(read(association.getInverse().getActualType(), new RedisData(rawHash))));
}
}
}
@@ -362,37 +368,42 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
return;
}
final RedisPersistentEntity entity = mappingContext.getPersistentEntity(source.getClass());
final Optional<RedisPersistentEntity<?>> entity = mappingContext.getPersistentEntity(source.getClass());
if (!customConversions.hasCustomWriteTarget(source.getClass())) {
typeMapper.writeType(ClassUtils.getUserClass(source), sink);
}
if (entity == null) {
if (!entity.isPresent()) {
typeMapper.writeType(ClassUtils.getUserClass(source), sink);
sink.getBucket().put("_raw", conversionService.convert(source, byte[].class));
return;
}
sink.setKeyspace(entity.getKeySpace());
sink.setKeyspace(entity.get().getKeySpace());
writeInternal(entity.getKeySpace(), "", source, entity.getTypeInformation(), sink);
sink.setId(getConversionService().convert(entity.getIdentifierAccessor(source).getIdentifier(), String.class));
writeInternal(entity.get().getKeySpace(), "", source, entity.get().getTypeInformation(), sink);
Long ttl = entity.getTimeToLiveAccessor().getTimeToLive(source);
Optional<Object> identifyer = entity.get().getIdentifierAccessor(source).getIdentifier();
if (identifyer.isPresent()) {
sink.setId(getConversionService().convert(identifyer.get(), String.class));
}
Long ttl = entity.get().getTimeToLiveAccessor().getTimeToLive(source);
if (ttl != null && ttl > 0) {
sink.setTimeToLive(ttl);
}
for (IndexedData indexedData : indexResolver.resolveIndexesFor(entity.getTypeInformation(), source)) {
for (IndexedData indexedData : indexResolver.resolveIndexesFor(entity.get().getTypeInformation(), source)) {
sink.addIndexedData(indexedData);
}
}
protected void writePartialUpdate(PartialUpdate<?> update, RedisData sink) {
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(update.getTarget());
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(update.getTarget()).get();
write(update.getValue(), sink);
if (sink.getBucket().keySet().contains(TYPE_HINT_ALIAS)) {
@@ -427,7 +438,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
private void writePartialPropertyUpdate(PartialUpdate<?> update, PropertyUpdate pUpdate, RedisData sink,
RedisPersistentEntity<?> entity, String path) {
KeyValuePersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
RedisPersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
if (targetProperty == null) {
@@ -436,7 +447,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
: (targetProperty.isMap()
? (targetProperty.getTypeInformation().getMapValueType() != null
? targetProperty.getTypeInformation().getMapValueType() : ClassTypeInformation.OBJECT)
? targetProperty.getTypeInformation().getMapValueType().get() : ClassTypeInformation.OBJECT)
: targetProperty.getTypeInformation().getActualType());
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
@@ -447,23 +458,28 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
if (targetProperty.isCollectionLike()) {
KeyValuePersistentEntity<?> ref = mappingContext.getPersistentEntity(
targetProperty.getAssociation().getInverse().getTypeInformation().getComponentType().getActualType());
RedisPersistentEntity<?> ref = mappingContext.getPersistentEntity(targetProperty.getAssociation().get()
.getInverse().getTypeInformation().getComponentType().get().getActualType()).get();
int i = 0;
for (Object o : (Collection<?>) pUpdate.getValue()) {
Object refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty());
sink.getBucket().put(pUpdate.getPropertyPath() + ".[" + i + "]", toBytes(ref.getKeySpace() + ":" + refId));
i++;
Optional<Object> refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty().get());
if (refId.isPresent()) {
sink.getBucket().put(pUpdate.getPropertyPath() + ".[" + i + "]",
toBytes(ref.getKeySpace() + ":" + refId.get()));
i++;
}
}
} else {
KeyValuePersistentEntity<?> ref = mappingContext
.getPersistentEntity(targetProperty.getAssociation().getInverse().getTypeInformation());
RedisPersistentEntity<?> ref = mappingContext
.getPersistentEntity(targetProperty.getAssociation().get().getInverse().getTypeInformation()).get();
Object refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty());
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId));
Optional<Object> refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty().get());
if (refId.isPresent()) {
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId.get()));
}
}
} else if (targetProperty.isCollectionLike()) {
@@ -504,11 +520,11 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
}
KeyValuePersistentProperty getTargetPropertyOrNullForPath(String path, Class<?> type) {
RedisPersistentProperty getTargetPropertyOrNullForPath(String path, Class<?> type) {
try {
PersistentPropertyPath<KeyValuePersistentProperty> persistentPropertyPath = mappingContext
PersistentPropertyPath<RedisPersistentProperty> persistentPropertyPath = mappingContext
.getPersistentPropertyPath(path, type);
return persistentPropertyPath.getLeafProperty();
} catch (Exception e) {
@@ -552,49 +568,66 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
toBytes(value.getClass().getName()));
}
final KeyValuePersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
final RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass()).get();
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
entity.doWithProperties(new PropertyHandler<KeyValuePersistentProperty>() {
entity.doWithProperties(new PropertyHandler<RedisPersistentProperty>() {
@Override
public void doWithPersistentProperty(KeyValuePersistentProperty persistentProperty) {
public void doWithPersistentProperty(RedisPersistentProperty persistentProperty) {
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + persistentProperty.getName();
if (persistentProperty.isIdProperty()) {
sink.getBucket().put(propertyStringPath, toBytes(accessor.getProperty(persistentProperty)));
if (accessor.getProperty(persistentProperty).isPresent()) {
sink.getBucket().put(propertyStringPath, toBytes(accessor.getProperty(persistentProperty).get()));
}
return;
}
if (persistentProperty.isMap()) {
writeMap(keyspace, propertyStringPath, persistentProperty.getMapValueType(),
(Map<?, ?>) accessor.getProperty(persistentProperty), sink);
if (accessor.getProperty(persistentProperty).isPresent()) {
writeMap(keyspace, propertyStringPath, persistentProperty.getMapValueType(),
(Map<?, ?>) accessor.getProperty(persistentProperty).get(), sink);
}
} else if (persistentProperty.isCollectionLike()) {
final Object property = accessor.getProperty(persistentProperty);
final Optional<Object> propertyValue = accessor.getProperty(persistentProperty);
if (property == null || Iterable.class.isAssignableFrom(property.getClass())) {
writeCollection(keyspace, propertyStringPath, (Iterable<?>) property,
persistentProperty.getTypeInformation().getComponentType(), sink);
} else if (property.getClass().isArray()) {
writeCollection(keyspace, propertyStringPath, CollectionUtils.arrayToList(property),
persistentProperty.getTypeInformation().getComponentType(), sink);
if (!propertyValue.isPresent()) {
writeCollection(keyspace, propertyStringPath, (Iterable<?>) null,
persistentProperty.getTypeInformation().getComponentType().get(), sink);
} else {
throw new RuntimeException("Don't know how to handle " + property.getClass() + " type collection");
if (Iterable.class.isAssignableFrom(propertyValue.get().getClass())) {
writeCollection(keyspace, propertyStringPath, (Iterable<?>) propertyValue.get(),
persistentProperty.getTypeInformation().getComponentType().get(), sink);
} else if (propertyValue.isPresent() && propertyValue.get().getClass().isArray()) {
writeCollection(keyspace, propertyStringPath, CollectionUtils.arrayToList(propertyValue.get()),
persistentProperty.getTypeInformation().getComponentType().get(), sink);
} else {
throw new RuntimeException("Don't know how to handle " + propertyValue.getClass() + " type collection");
}
}
} else if (persistentProperty.isEntity()) {
writeInternal(keyspace, propertyStringPath, accessor.getProperty(persistentProperty),
persistentProperty.getTypeInformation().getActualType(), sink);
Optional<Object> propertyValue = accessor.getProperty(persistentProperty);
if (propertyValue.isPresent()) {
writeInternal(keyspace, propertyStringPath, propertyValue.get(),
persistentProperty.getTypeInformation().getActualType(), sink);
}
} else {
Object propertyValue = accessor.getProperty(persistentProperty);
writeToBucket(propertyStringPath, propertyValue, sink, persistentProperty.getType());
Optional<Object> propertyValue = accessor.getProperty(persistentProperty);
if (propertyValue.isPresent()) {
writeToBucket(propertyStringPath, propertyValue.get(), sink, persistentProperty.getType());
}
}
}
});
@@ -602,7 +635,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
writeAssociation(path, entity, value, sink);
}
private void writeAssociation(final String path, final KeyValuePersistentEntity<?> entity, final Object value,
private void writeAssociation(final String path, final RedisPersistentEntity<?> entity, final Object value,
final RedisData sink) {
if (value == null) {
@@ -611,42 +644,46 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
entity.doWithAssociations(new AssociationHandler<KeyValuePersistentProperty>() {
entity.doWithAssociations(new AssociationHandler<RedisPersistentProperty>() {
@Override
public void doWithAssociation(Association<KeyValuePersistentProperty> association) {
public void doWithAssociation(Association<RedisPersistentProperty> association) {
Object refObject = accessor.getProperty(association.getInverse());
if (refObject == null) {
Optional<Object> refObject = accessor.getProperty(association.getInverse());
if (!refObject.isPresent()) {
return;
}
if (association.getInverse().isCollectionLike()) {
KeyValuePersistentEntity<?> ref = mappingContext
.getPersistentEntity(association.getInverse().getTypeInformation().getComponentType().getActualType());
RedisPersistentEntity<?> ref = mappingContext.getPersistentEntity(
association.getInverse().getTypeInformation().getComponentType().get().getActualType()).get();
String keyspace = ref.getKeySpace();
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
int i = 0;
for (Object o : (Collection<?>) refObject) {
for (Object o : (Collection<?>) refObject.get()) {
Object refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty());
sink.getBucket().put(propertyStringPath + ".[" + i + "]", toBytes(keyspace + ":" + refId));
i++;
Optional<Object> refId = ref.getPropertyAccessor(o).getProperty(ref.getIdProperty().get());
if (refId.isPresent()) {
sink.getBucket().put(propertyStringPath + ".[" + i + "]", toBytes(keyspace + ":" + refId.get()));
i++;
}
}
} else {
KeyValuePersistentEntity<?> ref = mappingContext
.getPersistentEntity(association.getInverse().getTypeInformation());
RedisPersistentEntity<?> ref = mappingContext
.getPersistentEntity(association.getInverse().getTypeInformation()).get();
String keyspace = ref.getKeySpace();
Object refId = ref.getPropertyAccessor(refObject).getProperty(ref.getIdProperty());
Optional<Object> refId = ref.getPropertyAccessor(refObject.get()).getProperty(ref.getIdProperty().get());
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
sink.getBucket().put(propertyStringPath, toBytes(keyspace + ":" + refId));
if (refId.isPresent()) {
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
sink.getBucket().put(propertyStringPath, toBytes(keyspace + ":" + refId.get()));
}
}
}
});
@@ -691,7 +728,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
private void writeToBucket(String path, Object value, RedisData sink, Class<?> propertyType) {
if (value == null) {
if (value == null || (value instanceof Optional && !((Optional<?>) value).isPresent())) {
return;
}
@@ -989,8 +1026,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* @author Christoph Strobl
*/
private static class ConverterAwareParameterValueProvider
implements PropertyValueProvider<KeyValuePersistentProperty> {
private static class ConverterAwareParameterValueProvider implements PropertyValueProvider<RedisPersistentProperty> {
private final String path;
private final RedisData source;
@@ -1005,10 +1041,10 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
@Override
@SuppressWarnings("unchecked")
public <T> T getPropertyValue(KeyValuePersistentProperty property) {
public <T> Optional<T> getPropertyValue(RedisPersistentProperty property) {
String name = StringUtils.hasText(path) ? path + "." + property.getName() : property.getName();
return (T) conversionService.convert(source.getBucket().get(name), property.getActualType());
return Optional.ofNullable((T) conversionService.convert(source.getBucket().get(name), property.getActualType()));
}
}
@@ -1032,8 +1068,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
@Override
public Object readAliasFrom(RedisData source) {
return conversionService.convert(source.getBucket().get(typeKey), String.class);
public Alias readAliasFrom(RedisData source) {
return Alias
.ofOptional(Optional.ofNullable(conversionService.convert(source.getBucket().get(typeKey), String.class)));
}
@Override

View File

@@ -20,10 +20,10 @@ import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.geo.Point;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.mapping.PropertyHandler;
@@ -39,6 +39,7 @@ import org.springframework.data.redis.core.index.Indexed;
import org.springframework.data.redis.core.index.SimpleIndexDefinition;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.redis.core.mapping.RedisPersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
@@ -87,8 +88,8 @@ public class PathIndexResolver implements IndexResolver {
* @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(org.springframework.data.util.TypeInformation, java.lang.Object)
*/
public Set<IndexedData> resolveIndexesFor(TypeInformation<?> typeInformation, Object value) {
return doResolveIndexesFor(mappingContext.getPersistentEntity(typeInformation).getKeySpace(), "", typeInformation,
null, value);
return doResolveIndexesFor(mappingContext.getPersistentEntity(typeInformation).get().getKeySpace(), "",
typeInformation, null, value);
}
/* (non-Javadoc)
@@ -103,40 +104,40 @@ public class PathIndexResolver implements IndexResolver {
private Set<IndexedData> doResolveIndexesFor(final String keyspace, final String path,
TypeInformation<?> typeInformation, PersistentProperty<?> fallback, Object value) {
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(typeInformation);
Optional<RedisPersistentEntity<?>> entity = mappingContext.getPersistentEntity(typeInformation);
if (entity == null || (value != null && VALUE_TYPES.contains(value.getClass()))) {
if (!entity.isPresent() || (value != null && VALUE_TYPES.contains(value.getClass()))) {
return resolveIndex(keyspace, path, fallback, value);
}
// this might happen on update where we address a property within an entity directly
if (!ClassUtils.isAssignable(entity.getType(), value.getClass())) {
if (!ClassUtils.isAssignable(entity.get().getType(), value.getClass())) {
String propertyName = path.lastIndexOf('.') > 0 ? path.substring(path.lastIndexOf('.') + 1, path.length()) : path;
return resolveIndex(keyspace, path, entity.getPersistentProperty(propertyName), value);
return resolveIndex(keyspace, path, entity.get().getPersistentProperty(propertyName).get(), value);
}
final PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
final PersistentPropertyAccessor accessor = entity.get().getPropertyAccessor(value);
final Set<IndexedData> indexes = new LinkedHashSet<IndexedData>();
entity.doWithProperties(new PropertyHandler<KeyValuePersistentProperty>() {
entity.get().doWithProperties(new PropertyHandler<RedisPersistentProperty>() {
@Override
public void doWithPersistentProperty(KeyValuePersistentProperty persistentProperty) {
public void doWithPersistentProperty(RedisPersistentProperty persistentProperty) {
String currentPath = !path.isEmpty() ? path + "." + persistentProperty.getName() : persistentProperty.getName();
Object propertyValue = accessor.getProperty(persistentProperty);
Optional<Object> propertyValue = accessor.getProperty(persistentProperty);
if (propertyValue != null) {
if (propertyValue.isPresent()) {
TypeInformation<?> typeHint = persistentProperty.isMap()
? persistentProperty.getTypeInformation().getMapValueType()
? persistentProperty.getTypeInformation().getMapValueType().get()
: persistentProperty.getTypeInformation().getActualType();
if (persistentProperty.isMap()) {
for (Entry<?, ?> entry : ((Map<?, ?>) propertyValue).entrySet()) {
for (Entry<?, ?> entry : ((Map<?, ?>) propertyValue.get()).entrySet()) {
TypeInformation<?> typeToUse = updateTypeHintForActualValue(typeHint, entry.getValue());
indexes.addAll(doResolveIndexesFor(keyspace, currentPath + "." + entry.getKey(),
@@ -147,13 +148,13 @@ public class PathIndexResolver implements IndexResolver {
final Iterable<?> iterable;
if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
iterable = (Iterable<?>) propertyValue;
} else if (propertyValue.getClass().isArray()) {
iterable = CollectionUtils.arrayToList(propertyValue);
if (Iterable.class.isAssignableFrom(propertyValue.get().getClass())) {
iterable = (Iterable<?>) propertyValue.get();
} else if (propertyValue.get().getClass().isArray()) {
iterable = CollectionUtils.arrayToList(propertyValue.get());
} else {
throw new RuntimeException(
"Don't know how to handle " + propertyValue.getClass() + " type of collection");
"Don't know how to handle " + propertyValue.get().getClass() + " type of collection");
}
for (Object listValue : iterable) {
@@ -169,11 +170,11 @@ public class PathIndexResolver implements IndexResolver {
else if (persistentProperty.isEntity()
|| persistentProperty.getTypeInformation().getActualType().equals(ClassTypeInformation.OBJECT)) {
typeHint = updateTypeHintForActualValue(typeHint, propertyValue);
typeHint = updateTypeHintForActualValue(typeHint, propertyValue.get());
indexes.addAll(doResolveIndexesFor(keyspace, currentPath, typeHint.getActualType(), persistentProperty,
propertyValue));
propertyValue.get()));
} else {
indexes.addAll(resolveIndex(keyspace, currentPath, persistentProperty, propertyValue));
indexes.addAll(resolveIndex(keyspace, currentPath, persistentProperty, propertyValue.get()));
}
}
@@ -183,7 +184,7 @@ public class PathIndexResolver implements IndexResolver {
if (typeHint.equals(ClassTypeInformation.OBJECT) || typeHint.getClass().isInterface()) {
try {
typeHint = mappingContext.getPersistentEntity(propertyValue.getClass()).getTypeInformation();
typeHint = mappingContext.getPersistentEntity(propertyValue.getClass()).get().getTypeInformation();
} catch (Exception e) {
// ignore for cases where property value cannot be resolved as an entity, in that case the provided type
// hint has to be sufficient

View File

@@ -16,9 +16,9 @@
package org.springframework.data.redis.core.convert;
import org.springframework.data.convert.EntityConverter;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.redis.core.mapping.RedisPersistentProperty;
/**
* Redis specific {@link EntityConverter}.
@@ -27,7 +27,7 @@ import org.springframework.data.redis.core.mapping.RedisMappingContext;
* @since 1.7
*/
public interface RedisConverter
extends EntityConverter<KeyValuePersistentEntity<?>, KeyValuePersistentProperty, Object, RedisData> {
extends EntityConverter<RedisPersistentEntity<?>, RedisPersistentProperty, Object, RedisData> {
/*
* (non-Javadoc)

View File

@@ -19,14 +19,15 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
import org.springframework.data.redis.core.index.ConfigurableIndexDefinitionProvider;
import org.springframework.data.redis.core.index.IndexDefinition;
import org.springframework.data.redis.core.index.SpelIndexDefinition;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.Expression;
@@ -85,13 +86,13 @@ public class SpelIndexResolver implements IndexResolver {
return Collections.emptySet();
}
KeyValuePersistentEntity<?> entity = mappingContext.getPersistentEntity(typeInformation);
Optional<RedisPersistentEntity<?>> entity = mappingContext.getPersistentEntity(typeInformation);
if (entity == null) {
if (!entity.isPresent()) {
return Collections.emptySet();
}
String keyspace = entity.getKeySpace();
String keyspace = entity.get().getKeySpace();
Set<IndexedData> indexes = new HashSet<IndexedData>();

View File

@@ -15,10 +15,11 @@
*/
package org.springframework.data.redis.core.mapping;
import java.util.Optional;
import org.springframework.data.annotation.Id;
import org.springframework.data.keyvalue.core.mapping.BasicKeyValuePersistentEntity;
import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.redis.core.TimeToLive;
import org.springframework.data.redis.core.TimeToLiveAccessor;
@@ -31,7 +32,7 @@ import org.springframework.util.Assert;
* @author Christoph Strobl
* @param <T>
*/
public class BasicRedisPersistentEntity<T> extends BasicKeyValuePersistentEntity<T>
public class BasicRedisPersistentEntity<T> extends BasicKeyValuePersistentEntity<T, RedisPersistentProperty>
implements RedisPersistentEntity<T> {
private TimeToLiveAccessor timeToLiveAccessor;
@@ -74,17 +75,16 @@ public class BasicRedisPersistentEntity<T> extends BasicKeyValuePersistentEntity
* @see org.springframework.data.redis.core.mapping.RedisPersistentEntity#getExplicitTimeToLiveProperty()
*/
@Override
public RedisPersistentProperty getExplicitTimeToLiveProperty() {
return (RedisPersistentProperty) this.getPersistentProperty(TimeToLive.class);
public Optional<RedisPersistentProperty> getExplicitTimeToLiveProperty() {
return this.getPersistentProperty(TimeToLive.class);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.model.BasicPersistentEntity#returnPropertyIfBetterIdPropertyCandidateOrNull(org.springframework.data.mapping.PersistentProperty)
*/
* (non-Javadoc)
* @see org.springframework.data.mapping.model.BasicPersistentEntity#returnPropertyIfBetterIdPropertyCandidateOrNull(org.springframework.data.mapping.PersistentProperty)
*/
@Override
protected KeyValuePersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(
KeyValuePersistentProperty property) {
protected RedisPersistentProperty returnPropertyIfBetterIdPropertyCandidateOrNull(RedisPersistentProperty property) {
Assert.notNull(property, "Property must not be null!");
@@ -92,27 +92,29 @@ public class BasicRedisPersistentEntity<T> extends BasicKeyValuePersistentEntity
return null;
}
KeyValuePersistentProperty currentIdProperty = getIdProperty();
boolean currentIdPropertyIsSet = currentIdProperty != null;
Optional<RedisPersistentProperty> currentIdProperty = getIdProperty();
boolean currentIdPropertyIsSet = currentIdProperty.isPresent();
if (!currentIdPropertyIsSet) {
return property;
}
boolean currentIdPropertyIsExplicit = currentIdProperty.isAnnotationPresent(Id.class);
boolean currentIdPropertyIsExplicit = currentIdProperty.get().isAnnotationPresent(Id.class);
boolean newIdPropertyIsExplicit = property.isAnnotationPresent(Id.class);
if (currentIdPropertyIsExplicit && newIdPropertyIsExplicit) {
throw new MappingException(String.format(
"Attempt to add explicit id property %s but already have an property %s registered "
+ "as explicit id. Check your mapping configuration!",
property.getField(), currentIdProperty.getField()));
property.getField(), currentIdProperty.get().getField()));
}
if (!currentIdPropertyIsExplicit && !newIdPropertyIsExplicit) {
throw new MappingException(
String.format("Attempt to add id property %s but already have an property %s registered "
+ "as id. Check your mapping configuration!", property.getField(), currentIdProperty.getField()));
String.format(
"Attempt to add id property %s but already have an property %s registered "
+ "as id. Check your mapping configuration!",
property.getField(), currentIdProperty.get().getField()));
}
if (newIdPropertyIsExplicit) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2017 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.
@@ -15,22 +15,20 @@
*/
package org.springframework.data.redis.core.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.keyvalue.annotation.KeySpace;
import org.springframework.data.keyvalue.core.mapping.KeySpaceResolver;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.redis.core.PartialUpdate;
import org.springframework.data.redis.core.PartialUpdate.PropertyUpdate;
@@ -58,7 +56,7 @@ import org.springframework.util.StringUtils;
* @author Oliver Gierke
* @since 1.7
*/
public class RedisMappingContext extends KeyValueMappingContext {
public class RedisMappingContext extends KeyValueMappingContext<RedisPersistentEntity<?>, RedisPersistentProperty> {
private final MappingConfiguration mappingConfiguration;
private final TimeToLiveAccessor timeToLiveAccessor;
@@ -96,50 +94,15 @@ public class RedisMappingContext extends KeyValueMappingContext {
this.fallbackKeySpaceResolver = fallbackKeySpaceResolver;
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.AbstractMappingContext#createPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
protected <T> RedisPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
return new BasicRedisPersistentEntity<T>(typeInformation, fallbackKeySpaceResolver, timeToLiveAccessor);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.AbstractMappingContext#getPersistentEntity(java.lang.Class)
*/
@Override
public RedisPersistentEntity<?> getPersistentEntity(Class<?> type) {
return (RedisPersistentEntity<?>) super.getPersistentEntity(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.AbstractMappingContext#getPersistentEntity(org.springframework.data.mapping.PersistentProperty)
*/
@Override
public RedisPersistentEntity<?> getPersistentEntity(KeyValuePersistentProperty persistentProperty) {
return (RedisPersistentEntity<?>) super.getPersistentEntity(persistentProperty);
}
/*
* (non-Javadoc)
* @see org.springframework.data.mapping.context.AbstractMappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation)
*/
@Override
public RedisPersistentEntity<?> getPersistentEntity(TypeInformation<?> type) {
return (RedisPersistentEntity<?>) super.getPersistentEntity(type);
}
/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.mapping.context.KeyValueMappingContext#createPersistentProperty(java.lang.reflect.Field, java.beans.PropertyDescriptor, org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity, org.springframework.data.mapping.model.SimpleTypeHolder)
*/
@Override
protected KeyValuePersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
KeyValuePersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
return new RedisPersistentProperty(field, descriptor, owner, simpleTypeHolder);
protected RedisPersistentProperty createPersistentProperty(Property property, RedisPersistentEntity<?> owner,
SimpleTypeHolder simpleTypeHolder) {
return new RedisPersistentProperty(property, owner, simpleTypeHolder);
}
/**
@@ -259,8 +222,8 @@ public class RedisMappingContext extends KeyValueMappingContext {
if (ttlProperty != null) {
if (ttlProperty.findAnnotation(TimeToLive.class) != null) {
unit = ttlProperty.findAnnotation(TimeToLive.class).unit();
if (ttlProperty.findAnnotation(TimeToLive.class).isPresent()) {
unit = ttlProperty.findAnnotation(TimeToLive.class).get().unit();
}
}
@@ -281,10 +244,11 @@ public class RedisMappingContext extends KeyValueMappingContext {
} else if (ttlProperty != null) {
RedisPersistentEntity entity = mappingContext.getPersistentEntity(type);
Number timeout = (Number) entity.getPropertyAccessor(source).getProperty(ttlProperty);
if (timeout != null) {
return TimeUnit.SECONDS.convert(timeout.longValue(), unit);
RedisPersistentEntity entity = mappingContext.getPersistentEntity(type).get();
Optional<Object> ttlPropertyValue = entity.getPropertyAccessor(source).getProperty(ttlProperty);
if (ttlPropertyValue.isPresent()) {
return TimeUnit.SECONDS.convert(((Number) ttlPropertyValue.get()).longValue(), unit);
}
} else {
@@ -326,9 +290,9 @@ public class RedisMappingContext extends KeyValueMappingContext {
defaultTimeout = keyspaceConfig.getKeyspaceSettings(type).getTimeToLive();
}
RedisHash hash = mappingContext.getPersistentEntity(type).findAnnotation(RedisHash.class);
if (hash != null && hash.timeToLive() > 0) {
defaultTimeout = hash.timeToLive();
Optional<RedisHash> hash = mappingContext.getPersistentEntity(type).get().findAnnotation(RedisHash.class);
if (hash.isPresent() && hash.get().timeToLive() > 0) {
defaultTimeout = hash.get().timeToLive();
}
defaultTimeouts.put(type, defaultTimeout);
@@ -342,13 +306,13 @@ public class RedisMappingContext extends KeyValueMappingContext {
return timeoutProperties.get(type);
}
RedisPersistentEntity entity = mappingContext.getPersistentEntity(type);
PersistentProperty<?> ttlProperty = entity.getPersistentProperty(TimeToLive.class);
RedisPersistentEntity entity = mappingContext.getPersistentEntity(type).get();
Optional<PersistentProperty<?>> ttlProperty = entity.getPersistentProperty(TimeToLive.class);
if (ttlProperty != null) {
if (ttlProperty.isPresent()) {
timeoutProperties.put(type, ttlProperty);
return ttlProperty;
timeoutProperties.put(type, ttlProperty.get());
return ttlProperty.get();
}
if (keyspaceConfig.hasSettingsFor(type)) {
@@ -357,8 +321,10 @@ public class RedisMappingContext extends KeyValueMappingContext {
if (StringUtils.hasText(settings.getTimeToLivePropertyName())) {
ttlProperty = entity.getPersistentProperty(settings.getTimeToLivePropertyName());
timeoutProperties.put(type, ttlProperty);
return ttlProperty;
if (ttlProperty.isPresent()) {
timeoutProperties.put(type, ttlProperty.get());
return ttlProperty.get();
}
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.core.mapping;
import java.util.Optional;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentEntity;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
@@ -27,7 +29,7 @@ import org.springframework.data.redis.core.TimeToLiveAccessor;
* @param <T>
* @since 1.7
*/
public interface RedisPersistentEntity<T> extends KeyValuePersistentEntity<T> {
public interface RedisPersistentEntity<T> extends KeyValuePersistentEntity<T, RedisPersistentProperty> {
/**
* Get the {@link TimeToLiveAccessor} associated with the entity.
@@ -48,6 +50,6 @@ public interface RedisPersistentEntity<T> extends KeyValuePersistentEntity<T> {
* @return can be {@null}.
* @since 1.8
*/
PersistentProperty<? extends PersistentProperty<?>> getExplicitTimeToLiveProperty();
Optional<RedisPersistentProperty> getExplicitTimeToLiveProperty();
}

View File

@@ -15,14 +15,13 @@
*/
package org.springframework.data.redis.core.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
/**
@@ -31,7 +30,7 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
* @author Christoph Strobl
* @since 1.7
*/
public class RedisPersistentProperty extends KeyValuePersistentProperty {
public class RedisPersistentProperty extends KeyValuePersistentProperty<RedisPersistentProperty> {
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
@@ -42,14 +41,13 @@ public class RedisPersistentProperty extends KeyValuePersistentProperty {
/**
* Creates new {@link RedisPersistentProperty}.
*
* @param field
* @param propertyDescriptor
* @param property
* @param owner
* @param simpleTypeHolder
*/
public RedisPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
PersistentEntity<?, KeyValuePersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
public RedisPersistentProperty(Property property, PersistentEntity<?, RedisPersistentProperty> owner,
SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
}
/*

View File

@@ -17,6 +17,7 @@
package org.springframework.data.redis.repository.cdi;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
@@ -53,22 +54,18 @@ public class RedisRepositoryBean<T> extends CdiRepositoryBean<T> {
public RedisRepositoryBean(Bean<KeyValueOperations> keyValueTemplate, Set<Annotation> qualifiers,
Class<T> repositoryType, BeanManager beanManager, CustomRepositoryImplementationDetector detector) {
super(qualifiers, repositoryType, beanManager, detector);
super(qualifiers, repositoryType, beanManager, Optional.ofNullable(detector));
Assert.notNull(keyValueTemplate, "Bean holding keyvalue template must not be null!");
this.keyValueTemplate = keyValueTemplate;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class)
*/
@Override
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType, Object customImplementation) {
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType,
Optional<Object> customImplementation) {
KeyValueOperations keyValueTemplate = getDependencyInstance(this.keyValueTemplate, KeyValueOperations.class);
RedisRepositoryFactory factory = new RedisRepositoryFactory(keyValueTemplate, RedisQueryCreator.class);
return factory.getRepository(repositoryType, customImplementation);
return customImplementation.isPresent() ? factory.getRepository(repositoryType, customImplementation.get()) : factory.getRepository(repositoryType);
}
}

View File

@@ -84,7 +84,7 @@ public class RedisRepositoryConfigurationExtension extends KeyValueRepositoryCon
@Override
public void registerBeansForRoot(BeanDefinitionRegistry registry, RepositoryConfigurationSource configurationSource) {
String redisTemplateRef = configurationSource.getAttribute("redisTemplateRef");
String redisTemplateRef = configurationSource.getAttribute("redisTemplateRef").get();
RootBeanDefinition mappingContextDefinition = createRedisMappingContext(configurationSource);
mappingContextDefinition.setSource(configurationSource.getSource());

View File

@@ -80,7 +80,7 @@ public class RedisRepositoryFactory extends KeyValueRepositoryFactory {
public <T, ID extends Serializable> EntityInformation<T, ID> getEntityInformation(Class<T> domainClass) {
RedisPersistentEntity<T> entity = (RedisPersistentEntity<T>) operations.getMappingContext()
.getPersistentEntity(domainClass);
.getPersistentEntity(domainClass).get();
EntityInformation<T, ID> entityInformation = (EntityInformation<T, ID>) new MappingRedisEntityInformation<T, ID>(
entity);