DATAREDIS-1175 - Polishing.
Reformat code. Add missing nullability annotations and enforce non-null values to prevent potential null dereference. Original pull request: #546.
This commit is contained in:
@@ -56,7 +56,7 @@ public class Bucket {
|
||||
|
||||
Bucket(Map<String, byte[]> data) {
|
||||
|
||||
Assert.notNull(data, "Inital data must not be null!");
|
||||
Assert.notNull(data, "Initial data must not be null!");
|
||||
this.data = new LinkedHashMap<>(data.size());
|
||||
this.data.putAll(data);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class Bucket {
|
||||
* @param path must not be {@literal null} or {@link String#isEmpty()}.
|
||||
* @param value can be {@literal null}.
|
||||
*/
|
||||
public void put(String path, byte[] value) {
|
||||
public void put(String path, @Nullable byte[] value) {
|
||||
|
||||
Assert.hasText(path, "Path to property must not be null or empty.");
|
||||
data.put(path, value);
|
||||
|
||||
@@ -175,27 +175,27 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @see org.springframework.data.convert.EntityReader#read(java.lang.Class, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> R read(Class<R> type, RedisData source) {
|
||||
|
||||
TypeInformation<?> readType = typeMapper.readType(source.getBucket().getPath(), ClassTypeInformation.from(type));
|
||||
if(readType.isCollectionLike()) {
|
||||
return (R) readCollectionOrArray("", ArrayList.class, Object.class, source.getBucket());
|
||||
}
|
||||
return readInternal("", type, source);
|
||||
|
||||
return readType.isCollectionLike()
|
||||
? (R) readCollectionOrArray("", ArrayList.class, Object.class, source.getBucket())
|
||||
: doReadInternal("", type, source);
|
||||
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <R> R readInternal(String path, Class<R> type, RedisData source) {
|
||||
return source.getBucket().isEmpty() ? null : doReadInternal(path, type, source);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nullable
|
||||
private <R> R readInternal(String path, Class<R> type, RedisData source) {
|
||||
|
||||
if (source.getBucket() == null || source.getBucket().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
private <R> R doReadInternal(String path, Class<R> type, RedisData source) {
|
||||
|
||||
TypeInformation<?> readType = typeMapper.readType(source.getBucket().getPath(), ClassTypeInformation.from(type));
|
||||
|
||||
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(readType);
|
||||
|
||||
if (customConversions.hasCustomReadTarget(Map.class, readType.getType())) {
|
||||
|
||||
Map<String, byte[]> partial = new HashMap<>();
|
||||
@@ -211,6 +211,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
}
|
||||
R instance = (R) conversionService.convert(partial, readType.getType());
|
||||
|
||||
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(readType);
|
||||
if (entity != null && entity.hasIdProperty()) {
|
||||
|
||||
PersistentPropertyAccessor<R> propertyAccessor = entity.getPropertyAccessor(instance);
|
||||
@@ -226,19 +227,20 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
readType.getType());
|
||||
}
|
||||
|
||||
RedisPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(readType);
|
||||
EntityInstantiator instantiator = entityInstantiators.getInstantiatorFor(entity);
|
||||
|
||||
Object instance = instantiator.createInstance((RedisPersistentEntity<RedisPersistentProperty>) entity,
|
||||
new PersistentEntityParameterValueProvider<>(entity,
|
||||
new ConverterAwareParameterValueProvider(path, source, conversionService), this.conversionService));
|
||||
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance);
|
||||
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(instance);
|
||||
|
||||
entity.doWithProperties((PropertyHandler<RedisPersistentProperty>) persistentProperty -> {
|
||||
|
||||
PreferredConstructor<?, RedisPersistentProperty> constructor = entity.getPersistenceConstructor();
|
||||
|
||||
if (constructor.isConstructorParameter(persistentProperty)) {
|
||||
if (constructor != null && constructor.isConstructorParameter(persistentProperty)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -311,7 +313,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
}
|
||||
|
||||
private void readAssociation(String path, RedisData source, RedisPersistentEntity<?> entity,
|
||||
PersistentPropertyAccessor accessor) {
|
||||
PersistentPropertyAccessor<?> accessor) {
|
||||
|
||||
entity.doWithAssociations((AssociationHandler<RedisPersistentProperty>) association -> {
|
||||
|
||||
@@ -400,8 +402,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
sink.setKeyspace(entity.getKeySpace());
|
||||
|
||||
if(entity.getTypeInformation().isCollectionLike()) {
|
||||
writeCollection(entity.getKeySpace(), "", (List) source, entity.getTypeInformation().getComponentType(), sink);
|
||||
if (entity.getTypeInformation().isCollectionLike()) {
|
||||
writeCollection(entity.getKeySpace(), "", (List) source, entity.getTypeInformation().getRequiredComponentType(),
|
||||
sink);
|
||||
} else {
|
||||
writeInternal(entity.getKeySpace(), "", source, entity.getTypeInformation(), sink);
|
||||
}
|
||||
@@ -483,7 +486,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
if (targetProperty.isCollectionLike()) {
|
||||
|
||||
RedisPersistentEntity<?> ref = mappingContext.getPersistentEntity(targetProperty.getRequiredAssociation()
|
||||
.getInverse().getTypeInformation().getRequiredComponentType().getActualType());
|
||||
.getInverse().getTypeInformation().getRequiredComponentType().getRequiredActualType());
|
||||
|
||||
int i = 0;
|
||||
for (Object o : (Collection<?>) pUpdate.getValue()) {
|
||||
@@ -507,9 +510,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
} else if (targetProperty.isCollectionLike()) {
|
||||
|
||||
Collection<?> collection = pUpdate.getValue() instanceof Collection ? (Collection<?>) pUpdate.getValue()
|
||||
: Collections.<Object> singleton(pUpdate.getValue());
|
||||
: Collections.singleton(pUpdate.getValue());
|
||||
writeCollection(entity.getKeySpace(), pUpdate.getPropertyPath(), collection,
|
||||
targetProperty.getTypeInformation().getActualType(), sink);
|
||||
targetProperty.getTypeInformation().getRequiredActualType(), sink);
|
||||
} else if (targetProperty.isMap()) {
|
||||
|
||||
Map<Object, Object> map = new HashMap<>();
|
||||
@@ -565,7 +568,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @param typeHint
|
||||
* @param sink
|
||||
*/
|
||||
private void writeInternal(String keyspace, String path, @Nullable Object value, TypeInformation<?> typeHint,
|
||||
private void writeInternal(@Nullable String keyspace, String path, @Nullable Object value,
|
||||
TypeInformation<?> typeHint,
|
||||
RedisData sink) {
|
||||
|
||||
if (value == null) {
|
||||
@@ -576,8 +580,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
Optional<Class<?>> targetType = customConversions.getCustomWriteTarget(value.getClass());
|
||||
|
||||
if (!StringUtils.hasText(path) && targetType.isPresent() && ClassUtils.isAssignable(byte[].class, targetType.get())) {
|
||||
sink.getBucket().put(StringUtils.hasText(path) ? path : "_raw", conversionService.convert(value, byte[].class));
|
||||
if (!StringUtils.hasText(path) && targetType.isPresent()
|
||||
&& ClassUtils.isAssignable(byte[].class, targetType.get())) {
|
||||
sink.getBucket().put(StringUtils.hasText(path) ? path : "_raw", conversionService.convert(value, byte[].class));
|
||||
} else {
|
||||
|
||||
if (!ClassUtils.isAssignable(typeHint.getType(), value.getClass())) {
|
||||
@@ -594,7 +599,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
}
|
||||
|
||||
RedisPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(value.getClass());
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
|
||||
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(value);
|
||||
|
||||
entity.doWithProperties((PropertyHandler<RedisPersistentProperty>) persistentProperty -> {
|
||||
|
||||
@@ -639,7 +644,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
|
||||
if (propertyValue != null) {
|
||||
writeInternal(keyspace, propertyStringPath, propertyValue,
|
||||
persistentProperty.getTypeInformation().getActualType(), sink);
|
||||
persistentProperty.getTypeInformation().getRequiredActualType(), sink);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -652,13 +657,13 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
writeAssociation(path, entity, value, sink);
|
||||
}
|
||||
|
||||
private void writeAssociation(String path, RedisPersistentEntity<?> entity, Object value, RedisData sink) {
|
||||
private void writeAssociation(String path, RedisPersistentEntity<?> entity, @Nullable Object value, RedisData sink) {
|
||||
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(value);
|
||||
PersistentPropertyAccessor<Object> accessor = entity.getPropertyAccessor(value);
|
||||
|
||||
entity.doWithAssociations((AssociationHandler<RedisPersistentProperty>) association -> {
|
||||
|
||||
@@ -670,7 +675,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
if (association.getInverse().isCollectionLike()) {
|
||||
|
||||
RedisPersistentEntity<?> ref = mappingContext.getRequiredPersistentEntity(
|
||||
association.getInverse().getTypeInformation().getRequiredComponentType().getActualType());
|
||||
association.getInverse().getTypeInformation().getRequiredComponentType().getRequiredActualType());
|
||||
|
||||
String keyspace = ref.getKeySpace();
|
||||
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
|
||||
@@ -691,11 +696,13 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
.getRequiredPersistentEntity(association.getInverse().getTypeInformation());
|
||||
String keyspace = ref.getKeySpace();
|
||||
|
||||
Object refId = ref.getPropertyAccessor(refObject).getProperty(ref.getIdProperty());
|
||||
if (keyspace != null) {
|
||||
Object refId = ref.getPropertyAccessor(refObject).getProperty(ref.getRequiredIdProperty());
|
||||
|
||||
if (refId != null) {
|
||||
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
|
||||
sink.getBucket().put(propertyStringPath, toBytes(keyspace + ":" + refId));
|
||||
if (refId != null) {
|
||||
String propertyStringPath = (!path.isEmpty() ? path + "." : "") + association.getInverse().getName();
|
||||
sink.getBucket().put(propertyStringPath, toBytes(keyspace + ":" + refId));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -708,7 +715,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @param typeHint
|
||||
* @param sink
|
||||
*/
|
||||
private void writeCollection(String keyspace, String path, @Nullable Iterable<?> values, TypeInformation<?> typeHint,
|
||||
private void writeCollection(@Nullable String keyspace, String path, @Nullable Iterable<?> values,
|
||||
TypeInformation<?> typeHint,
|
||||
RedisData sink) {
|
||||
|
||||
if (values == null) {
|
||||
@@ -769,6 +777,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object readCollectionOrArray(String path, Class<?> collectionType, Class<?> valueType, Bucket bucket) {
|
||||
|
||||
List<String> keys = new ArrayList<>(bucket.extractAllKeysFor(path));
|
||||
@@ -807,7 +816,8 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @param source
|
||||
* @param sink
|
||||
*/
|
||||
private void writeMap(String keyspace, String path, Class<?> mapValueType, Map<?, ?> source, RedisData sink) {
|
||||
private void writeMap(@Nullable String keyspace, String path, Class<?> mapValueType, Map<?, ?> source,
|
||||
RedisData sink) {
|
||||
|
||||
if (CollectionUtils.isEmpty(source)) {
|
||||
return;
|
||||
@@ -905,6 +915,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
return target.isEmpty() ? null : target;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Object extractMapKeyForPath(String path, String key, Class<?> targetType) {
|
||||
|
||||
String regex = "^(" + Pattern.quote(path) + "\\.\\[)(.*?)(\\])";
|
||||
@@ -1173,9 +1184,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
public static final String DELIMITTER = ":";
|
||||
public static final String PHANTOM_SUFFIX = DELIMITTER + PHANTOM;
|
||||
|
||||
private String keyspace;
|
||||
private String id;
|
||||
private boolean phantomKey;
|
||||
private final String keyspace;
|
||||
private final String id;
|
||||
private final boolean phantomKey;
|
||||
|
||||
private KeyspaceIdentifier(String keyspace, String id, boolean phantomKey) {
|
||||
|
||||
@@ -1215,7 +1226,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
* @param key the key.
|
||||
* @return {@literal true} if the key is valid.
|
||||
*/
|
||||
public static boolean isValid(String key) {
|
||||
public static boolean isValid(@Nullable String key) {
|
||||
|
||||
if (key == null) {
|
||||
return false;
|
||||
@@ -1252,9 +1263,9 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
|
||||
public static final byte DELIMITTER = ':';
|
||||
public static final byte[] PHANTOM_SUFFIX = ByteUtils.concat(new byte[] { DELIMITTER }, PHANTOM);
|
||||
|
||||
private byte[] keyspace;
|
||||
private byte[] id;
|
||||
private boolean phantomKey;
|
||||
private final byte[] keyspace;
|
||||
private final byte[] id;
|
||||
private final boolean phantomKey;
|
||||
|
||||
private BinaryKeyspaceIdentifier(byte[] keyspace, byte[] id, boolean phantomKey) {
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public class RedisData {
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
public void setId(String id) {
|
||||
public void setId(@Nullable String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class RedisData {
|
||||
/**
|
||||
* @param keyspace
|
||||
*/
|
||||
public void setKeyspace(String keyspace) {
|
||||
public void setKeyspace(@Nullable String keyspace) {
|
||||
this.keyspace = keyspace;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user