DATAREDIS-471 - Polishing.

Update reference documentation. Enhance JavaDoc. Remove destroy of managed bean. Refactor property update of writePartialUpdate into own method. Remove trailing whitespaces in JavaDoc.

Original pull request: #191.
This commit is contained in:
Mark Paluch
2016-05-24 16:30:23 +02:00
parent 76229c10a4
commit d88d992f6d
16 changed files with 152 additions and 150 deletions

View File

@@ -150,6 +150,7 @@ class IndexWriter {
protected void removeKeyFromExistingIndexes(byte[] key, IndexedData indexedData) {
Assert.notNull(indexedData, "IndexedData must not be null!");
Set<byte[]> existingKeys = connection
.keys(toBytes(indexedData.getKeyspace() + ":" + indexedData.getIndexName() + ":*"));
@@ -217,7 +218,8 @@ class IndexWriter {
}
throw new InvalidDataAccessApiUsageException(String.format(
"Cannot convert %s to binary representation for index key generation. Are you missing a Converter? Did you register a non PathBasedRedisIndexDefinition that might apply to a complex type?",
"Cannot convert %s to binary representation for index key generation. "
+ "Are you missing a Converter? Did you register a non PathBasedRedisIndexDefinition that might apply to a complex type?",
source.getClass()));
}

View File

@@ -114,6 +114,7 @@ public class PartialUpdate<T> {
PartialUpdate<T> update = new PartialUpdate<T>(this.id, this.target, this.value, this.refreshTtl,
this.propertyUpdates);
update.propertyUpdates.add(new PropertyUpdate(UpdateCommand.SET, path, value));
return update;
}
@@ -130,6 +131,7 @@ public class PartialUpdate<T> {
PartialUpdate<T> update = new PartialUpdate<T>(this.id, this.target, this.value, this.refreshTtl,
this.propertyUpdates);
update.propertyUpdates.add(new PropertyUpdate(UpdateCommand.DEL, path));
return update;
}

View File

@@ -140,29 +140,6 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
super.update(objectToUpdate);
}
/*
* (non-Javadoc)
* @see org.springframework.data.keyvalue.core.KeyValueTemplate#destroy()
*/
@Override
public void destroy() throws Exception {
execute(new RedisKeyValueCallback<Void>() {
@Override
public Void doInRedis(RedisKeyValueAdapter adapter) {
try {
adapter.destroy();
} catch (Exception e) {
throw new RedisSystemException(e.getMessage(), e);
}
return null;
}
});
}
protected void doPartialUpdate(final PartialUpdate<?> update) {
execute(new RedisKeyValueCallback<Void>() {

View File

@@ -72,6 +72,9 @@ public class CompositeIndexResolver implements IndexResolver {
return data;
}
/* (non-Javadoc)
* @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(java.lang.String, java.lang.String, org.springframework.data.util.TypeInformation, java.lang.Object)
*/
@Override
public Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation,
Object value) {

View File

@@ -23,7 +23,7 @@ import org.springframework.data.util.TypeInformation;
/**
* {@link IndexResolver} extracts secondary index structures to be applied on a given path, {@link PersistentProperty}
* and value.
*
*
* @author Christoph Strobl
* @since 1.7
*/
@@ -31,13 +31,22 @@ public interface IndexResolver {
/**
* Resolves all indexes for given type information / value combination.
*
*
* @param typeInformation must not be {@literal null}.
* @param value the actual value. Can be {@literal null}.
* @return never {@literal null}.
*/
Set<IndexedData> resolveIndexesFor(TypeInformation<?> typeInformation, Object value);
/**
* Resolves all indexes for given type information / value combination.
*
* @param keyspace must not be {@literal null}.
* @param path must not be {@literal null}.
* @param typeInformation must not be {@literal null}.
* @param value the actual value. Can be {@literal null}.
* @return never {@literal null}.
*/
Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation, Object value);
}

View File

@@ -72,18 +72,18 @@ import org.springframework.util.comparator.NullSafeComparator;
* <br />
* <strong>NOTE</strong> {@link MappingRedisConverter} is an {@link InitializingBean} and requires
* {@link MappingRedisConverter#afterPropertiesSet()} to be called.
*
*
* <pre>
* <code>
* &#64;RedisHash("persons")
* class Person {
*
*
* &#64;Id String id;
* String firstname;
*
*
* List<String> nicknames;
* List<Person> coworkers;
*
*
* Address address;
* &#64;Reference Country nationality;
* }
@@ -105,9 +105,10 @@ import org.springframework.util.comparator.NullSafeComparator;
* nationality=nationality:andora
* </code>
* </pre>
*
*
* @author Christoph Strobl
* @author Greg Turnquist
* @author Mark Paluch
* @since 1.7
*/
public class MappingRedisConverter implements RedisConverter, InitializingBean {
@@ -128,7 +129,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* Creates new {@link MappingRedisConverter}.
*
*
* @param context can be {@literal null}.
*/
MappingRedisConverter(RedisMappingContext context) {
@@ -137,7 +138,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* Creates new {@link MappingRedisConverter} and defaults {@link RedisMappingContext} when {@literal null}.
*
*
* @param mappingContext can be {@literal null}.
* @param indexResolver can be {@literal null}.
* @param referenceResolver must not be {@literal null}.
@@ -394,8 +395,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(update.getTarget());
write(update.getValue(), sink);
if (sink.getBucket().keySet().contains("_class")) {
sink.getBucket().put("_class", null); // overwrite stuff in here
if (sink.getBucket().keySet().contains(TYPE_HINT_ALIAS)) {
sink.getBucket().put(TYPE_HINT_ALIAS, null); // overwrite stuff in here
}
if (update.isRefreshTtl() && !update.getPropertyUpdates().isEmpty()) {
@@ -411,89 +412,98 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
String path = pUpdate.getPropertyPath();
if (UpdateCommand.SET.equals(pUpdate.getCmd())) {
KeyValuePersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
if (targetProperty == null) {
targetProperty = getTargetPropertyOrNullForPath(path.replaceAll("\\.\\[.*\\]", ""), update.getTarget());
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
: (targetProperty.isMap()
? (targetProperty.getTypeInformation().getMapValueType() != null
? targetProperty.getTypeInformation().getMapValueType() : ClassTypeInformation.OBJECT)
: targetProperty.getTypeInformation().getActualType());
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
continue;
}
if (targetProperty.isAssociation()) {
if (targetProperty.isCollectionLike()) {
KeyValuePersistentEntity<?> ref = mappingContext.getPersistentEntity(
targetProperty.getAssociation().getInverse().getTypeInformation().getComponentType().getActualType());
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++;
}
} else {
KeyValuePersistentEntity<?> ref = mappingContext
.getPersistentEntity(targetProperty.getAssociation().getInverse().getTypeInformation());
Object refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty());
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId));
}
}
else if (targetProperty.isCollectionLike()) {
Collection<?> collection = pUpdate.getValue() instanceof Collection ? (Collection<?>) pUpdate.getValue()
: Collections.<Object> singleton(pUpdate.getValue());
writeCollection(entity.getKeySpace(), pUpdate.getPropertyPath(), collection,
targetProperty.getTypeInformation().getActualType(), sink);
} else if (targetProperty.isMap()) {
Map<Object, Object> map = new HashMap<Object, Object>();
if (pUpdate.getValue() instanceof Map) {
map.putAll((Map<?, ?>) pUpdate.getValue());
} else if (pUpdate.getValue() instanceof Map.Entry) {
map.put(((Map.Entry<?, ?>) pUpdate.getValue()).getKey(), ((Map.Entry<?, ?>) pUpdate.getValue()).getValue());
} else {
throw new MappingException(
String.format("Cannot set update value for map property '%s' to '%s'. Please use a Map or Map.Entry.",
pUpdate.getPropertyPath(), pUpdate.getValue()));
}
writeMap(entity.getKeySpace(), pUpdate.getPropertyPath(), targetProperty.getMapValueType(), map, sink);
} else {
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(),
targetProperty.getTypeInformation(), sink);
Set<IndexedData> data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
targetProperty.getTypeInformation(), pUpdate.getValue());
if (data.isEmpty()) {
data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
targetProperty.getOwner().getTypeInformation(), pUpdate.getValue());
}
sink.addIndexedData(data);
}
writePartialPropertyUpdate(update, pUpdate, sink, entity, path);
}
}
}
/**
* @param update
* @param pUpdate
* @param sink
* @param entity
* @param path
*/
private void writePartialPropertyUpdate(PartialUpdate<?> update, PropertyUpdate pUpdate, RedisData sink,
RedisPersistentEntity<?> entity, String path) {
KeyValuePersistentProperty targetProperty = getTargetPropertyOrNullForPath(path, update.getTarget());
if (targetProperty == null) {
targetProperty = getTargetPropertyOrNullForPath(path.replaceAll("\\.\\[.*\\]", ""), update.getTarget());
TypeInformation<?> ti = targetProperty == null ? ClassTypeInformation.OBJECT
: (targetProperty.isMap()
? (targetProperty.getTypeInformation().getMapValueType() != null
? targetProperty.getTypeInformation().getMapValueType() : ClassTypeInformation.OBJECT)
: targetProperty.getTypeInformation().getActualType());
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(), ti, sink);
return;
}
if (targetProperty.isAssociation()) {
if (targetProperty.isCollectionLike()) {
KeyValuePersistentEntity<?> ref = mappingContext.getPersistentEntity(
targetProperty.getAssociation().getInverse().getTypeInformation().getComponentType().getActualType());
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++;
}
} else {
KeyValuePersistentEntity<?> ref = mappingContext
.getPersistentEntity(targetProperty.getAssociation().getInverse().getTypeInformation());
Object refId = ref.getPropertyAccessor(pUpdate.getValue()).getProperty(ref.getIdProperty());
sink.getBucket().put(pUpdate.getPropertyPath(), toBytes(ref.getKeySpace() + ":" + refId));
}
} else if (targetProperty.isCollectionLike()) {
Collection<?> collection = pUpdate.getValue() instanceof Collection ? (Collection<?>) pUpdate.getValue()
: Collections.<Object> singleton(pUpdate.getValue());
writeCollection(entity.getKeySpace(), pUpdate.getPropertyPath(), collection,
targetProperty.getTypeInformation().getActualType(), sink);
} else if (targetProperty.isMap()) {
Map<Object, Object> map = new HashMap<Object, Object>();
if (pUpdate.getValue() instanceof Map) {
map.putAll((Map<?, ?>) pUpdate.getValue());
} else if (pUpdate.getValue() instanceof Entry) {
map.put(((Entry<?, ?>) pUpdate.getValue()).getKey(), ((Entry<?, ?>) pUpdate.getValue()).getValue());
} else {
throw new MappingException(
String.format("Cannot set update value for map property '%s' to '%s'. Please use a Map or Map.Entry.",
pUpdate.getPropertyPath(), pUpdate.getValue()));
}
writeMap(entity.getKeySpace(), pUpdate.getPropertyPath(), targetProperty.getMapValueType(), map, sink);
} else {
writeInternal(entity.getKeySpace(), pUpdate.getPropertyPath(), pUpdate.getValue(),
targetProperty.getTypeInformation(), sink);
Set<IndexedData> data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
targetProperty.getTypeInformation(), pUpdate.getValue());
if (data.isEmpty()) {
data = indexResolver.resolveIndexesFor(entity.getKeySpace(), pUpdate.getPropertyPath(),
targetProperty.getOwner().getTypeInformation(), pUpdate.getValue());
}
sink.addIndexedData(data);
}
}
KeyValuePersistentProperty getTargetPropertyOrNullForPath(String path, Class<?> type) {
try {
@@ -589,10 +599,10 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
});
writeAssiciation(keyspace, path, entity, value, sink);
writeAssociation(path, entity, value, sink);
}
private void writeAssiciation(final String keyspace, final String path, final KeyValuePersistentEntity<?> entity,
private void writeAssociation(final String path, final KeyValuePersistentEntity<?> entity,
final Object value, final RedisData sink) {
if (value == null) {
@@ -878,7 +888,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* Convert given source to binary representation using the underlying {@link ConversionService}.
*
*
* @param source
* @return
* @throws ConverterNotFoundException
@@ -894,7 +904,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* Convert given binary representation to desired target type using the underlying {@link ConversionService}.
*
*
* @param source
* @param type
* @return
@@ -934,7 +944,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
/**
* Set {@link CustomConversions} to be applied.
*
*
* @param customConversions
*/
public void setCustomConversions(CustomConversions customConversions) {

View File

@@ -62,7 +62,7 @@ public class PathIndexResolver implements IndexResolver {
/**
* Creates new {@link PathIndexResolver} with given {@link IndexConfiguration}.
*
* @param mapppingContext must not be {@literal null}.
* @param mappingContext must not be {@literal null}.
*/
public PathIndexResolver(RedisMappingContext mappingContext) {
@@ -80,6 +80,9 @@ public class PathIndexResolver implements IndexResolver {
null, value);
}
/* (non-Javadoc)
* @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(java.lang.String, java.lang.String, org.springframework.data.util.TypeInformation, java.lang.Object)
*/
@Override
public Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation,
Object value) {
@@ -134,7 +137,7 @@ public class PathIndexResolver implements IndexResolver {
final Iterable<?> iterable;
if (Iterable.class.isAssignableFrom(propertyValue.getClass())) {
iterable = (Iterable) propertyValue;
iterable = (Iterable<?>) propertyValue;
} else if (propertyValue.getClass().isArray()) {
iterable = CollectionUtils.arrayToList(propertyValue);
} else {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.
@@ -22,7 +22,7 @@ import org.springframework.data.redis.core.mapping.RedisMappingContext;
/**
* Redis specific {@link EntityConverter}.
*
*
* @author Christoph Strobl
* @since 1.7
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2015 the original author or authors.
* Copyright 2015-2016 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.
@@ -27,7 +27,7 @@ import org.springframework.util.Assert;
/**
* Data object holding {@link Bucket} representing the domain object to be stored in a Redis hash. Index information
* points to additional structures holding the objects is for searching.
*
*
* @author Christoph Strobl
* @since 1.7
*/
@@ -50,7 +50,7 @@ public class RedisData {
/**
* Creates new {@link RedisData} with {@link Bucket} holding provided values.
*
*
* @param raw should not be {@literal null}.
*/
public RedisData(Map<byte[], byte[]> raw) {
@@ -59,7 +59,7 @@ public class RedisData {
/**
* Creates new {@link RedisData} with {@link Bucket}
*
*
* @param bucket must not be {@literal null}.
*/
public RedisData(Bucket bucket) {
@@ -71,7 +71,7 @@ public class RedisData {
/**
* Set the id to be used as part of the key.
*
*
* @param id
*/
public void setId(String id) {
@@ -87,7 +87,7 @@ public class RedisData {
/**
* Get the time before expiration in seconds.
*
*
* @return {@literal null} if not set.
*/
public Long getTimeToLive() {
@@ -142,7 +142,7 @@ public class RedisData {
/**
* Set the time before expiration in {@link TimeUnit#SECONDS}.
*
*
* @param timeToLive can be {@literal null}.
*/
public void setTimeToLive(Long timeToLive) {
@@ -151,7 +151,7 @@ public class RedisData {
/**
* Set the time before expiration converting the given arguments to {@link TimeUnit#SECONDS}.
*
*
* @param timeToLive must not be {@literal null}
* @param timeUnit must not be {@literal null}
*/

View File

@@ -16,7 +16,10 @@
package org.springframework.data.redis.core.convert;
/**
* {@link RemoveIndexedData} represents a removed index entry from a secondary index for a property path in a given keyspace.
*
* @author Christoph Strobl
* @author Mark Paluch
*/
public class RemoveIndexedData implements IndexedData {

View File

@@ -119,6 +119,9 @@ public class SpelIndexResolver implements IndexResolver {
return indexes;
}
/* (non-Javadoc)
* @see org.springframework.data.redis.core.convert.IndexResolver#resolveIndexesFor(java.lang.String, java.lang.String, org.springframework.data.util.TypeInformation, java.lang.Object)
*/
@Override
public Set<IndexedData> resolveIndexesFor(String keyspace, String path, TypeInformation<?> typeInformation,
Object value) {