DATAREDIS-543 - Polishing.

Move BucketPropertyPath to Bucket.

Original Pull Request: #299
This commit is contained in:
Christoph Strobl
2018-03-13 14:01:26 +01:00
parent 9969a559ea
commit 452feb9420
7 changed files with 104 additions and 102 deletions

View File

@@ -15,6 +15,11 @@
*/
package org.springframework.data.redis.core.convert;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
@@ -203,6 +208,27 @@ public class Bucket {
return raw;
}
/**
* Get the {@link BucketPropertyPath} leading to the current {@link Bucket}.
*
* @return new instance of {@link BucketPropertyPath}.
* @since 2.1
*/
public BucketPropertyPath getPath() {
return BucketPropertyPath.from(this);
}
/**
* Get the {@link BucketPropertyPath} for a given property within the current {@link Bucket}.
*
* @param property the property to look up.
* @return new instance of {@link BucketPropertyPath}.
* @since 2.1
*/
public BucketPropertyPath getPropertyPath(String property) {
return BucketPropertyPath.from(this, property);
}
/**
* Creates a new Bucket from a given raw map.
*
@@ -256,7 +282,6 @@ public class Bucket {
}
}
return serialized.toString();
}
@Nullable
@@ -270,4 +295,65 @@ public class Bucket {
return null;
}
/**
* Value object representing a path within a {@link Bucket}. Paths can be either top-level (if the {@code prefix} is
* {@literal null} or empty) or nested with a given {@code prefix}.
*
* @author Mark Paluch
* @since 2.1
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public static class BucketPropertyPath {
private final @NonNull Bucket bucket;
private final @Nullable String prefix;
/**
* Creates a top-level {@link BucketPropertyPath} given {@link Bucket}.
*
* @param bucket the bucket, must not be {@literal null}.
* @return {@link BucketPropertyPath} within the given {@link Bucket}.
*/
public static BucketPropertyPath from(Bucket bucket) {
return new BucketPropertyPath(bucket, null);
}
/**
* Creates a {@link BucketPropertyPath} given {@link Bucket} and {@code prefix}. The resulting path is top-level if
* {@code prefix} is empty or nested, if {@code prefix} is not empty.
*
* @param bucket the bucket, must not be {@literal null}.
* @param prefix the prefix. Property path is top-level if {@code prefix} is {@literal null} or empty.
* @return {@link BucketPropertyPath} within the given {@link Bucket} using {@code prefix}.
*/
public static BucketPropertyPath from(Bucket bucket, @Nullable String prefix) {
return new BucketPropertyPath(bucket, prefix);
}
/**
* Retrieve a value at {@code key} considering top-level/nesting.
*
* @param key must not be {@literal null} or empty.
* @return the resulting value, may be {@literal null}.
*/
@Nullable
public byte[] get(String key) {
return bucket.get(getPath(key));
}
/**
* Write a {@code value} at {@code key} considering top-level/nesting.
*
* @param key must not be {@literal null} or empty.
* @param value the value.
*/
public void put(String key, byte[] value) {
bucket.put(getPath(key), value);
}
private String getPath(String key) {
return StringUtils.hasText(prefix) ? prefix + "." + key : key;
}
}
}

View File

@@ -1,86 +0,0 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core.convert;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
/**
* Value object representing a path within a {@link Bucket}. Paths can be either top-level (if the {@code prefix} is
* {@literal null} or empty) or nested with a given {@code prefix}.
*
* @author Mark Paluch
* @since 2.1
*/
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
public class BucketPropertyPath {
private final @NonNull Bucket bucket;
private final @Nullable String prefix;
/**
* Creates a top-level {@link BucketPropertyPath} given {@link Bucket}.
*
* @param bucket the bucket, must not be {@literal null}.
* @return {@link BucketPropertyPath} within the given {@link Bucket}.
*/
public static BucketPropertyPath from(Bucket bucket) {
return new BucketPropertyPath(bucket, null);
}
/**
* Creates a {@link BucketPropertyPath} given {@link Bucket} and {@code prefix}. The resulting path is top-level if
* {@code prefix} is empty or nested, if {@code prefix} is not empty.
*
* @param bucket the bucket, must not be {@literal null}.
* @param prefix the prefix. Property path is top-level if {@code prefix} is {@literal null} or empty.
* @return {@link BucketPropertyPath} within the given {@link Bucket} using {@code prefix}.
*/
public static BucketPropertyPath from(Bucket bucket, @Nullable String prefix) {
return new BucketPropertyPath(bucket, prefix);
}
/**
* Retrieve a value at {@code key} considering top-level/nesting.
*
* @param key must not be {@literal null} or empty.
* @return the resulting value, may be {@literal null}.
*/
@Nullable
public byte[] get(String key) {
return bucket.get(getPath(key));
}
/**
* Write a {@code value} at {@code key} considering top-level/nesting.
*
* @param key must not be {@literal null} or empty.
* @param value the value.
*/
public void put(String key, byte[] value) {
bucket.put(getPath(key), value);
}
private String getPath(String key) {
return StringUtils.hasText(prefix) ? prefix + "." + key : key;
}
}

View File

@@ -27,6 +27,7 @@ import org.springframework.data.convert.TypeInformationMapper;
import org.springframework.data.mapping.Alias;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.redis.core.convert.Bucket.BucketPropertyPath;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

View File

@@ -192,8 +192,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
return null;
}
TypeInformation<?> readType = typeMapper.readType(BucketPropertyPath.from(source.getBucket()),
ClassTypeInformation.from(type));
TypeInformation<?> readType = typeMapper.readType(source.getBucket().getPath(), ClassTypeInformation.from(type));
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(readType);
@@ -278,7 +277,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
Bucket bucket = source.getBucket().extract(currentPath + ".");
RedisData newBucket = new RedisData(bucket);
TypeInformation<?> typeInformation = typeMapper.readType(BucketPropertyPath.from(bucket, currentPath),
TypeInformation<?> typeInformation = typeMapper.readType(bucket.getPropertyPath(currentPath),
persistentProperty.getTypeInformation().getActualType());
Class<R> targetType = (Class<R>) typeInformation.getType();
@@ -386,12 +385,12 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
RedisPersistentEntity<?> entity = mappingContext.getPersistentEntity(source.getClass());
if (!customConversions.hasCustomWriteTarget(source.getClass())) {
typeMapper.writeType(ClassUtils.getUserClass(source), BucketPropertyPath.from(sink.getBucket()));
typeMapper.writeType(ClassUtils.getUserClass(source), sink.getBucket().getPath());
}
if (entity == null) {
typeMapper.writeType(ClassUtils.getUserClass(source), BucketPropertyPath.from(sink.getBucket()));
typeMapper.writeType(ClassUtils.getUserClass(source), sink.getBucket().getPath());
sink.getBucket().put("_raw", conversionService.convert(source, byte[].class));
return;
}
@@ -583,7 +582,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
}
if (value.getClass() != typeHint.getType()) {
typeMapper.writeType(value.getClass(), BucketPropertyPath.from(sink.getBucket(), path));
typeMapper.writeType(value.getClass(), sink.getBucket().getPropertyPath(path));
}
RedisPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(value.getClass());
@@ -743,7 +742,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
if (!targetType.filter(it -> ClassUtils.isAssignable(Map.class, it)).isPresent()
&& customConversions.isSimpleType(value.getClass()) && value.getClass() != propertyType) {
typeMapper.writeType(value.getClass(), BucketPropertyPath.from(sink.getBucket(), path));
typeMapper.writeType(value.getClass(), sink.getBucket().getPropertyPath(path));
}
if (targetType.filter(it -> ClassUtils.isAssignable(Map.class, it)).isPresent()) {
@@ -779,7 +778,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
Bucket elementData = bucket.extract(key);
TypeInformation<?> typeInformation = typeMapper.readType(BucketPropertyPath.from(elementData, key),
TypeInformation<?> typeInformation = typeMapper.readType(elementData.getPropertyPath(key),
ClassTypeInformation.from(valueType));
Class<?> typeToUse = typeInformation.getType();
@@ -885,10 +884,10 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
for (String key : keys) {
Bucket partial = source.getBucket().extract(key);
Object mapKey = extractMapKeyForPath(path, key, keyType);
TypeInformation<?> typeInformation = typeMapper.readType(BucketPropertyPath.from(source.getBucket(), key),
TypeInformation<?> typeInformation = typeMapper.readType(source.getBucket().getPropertyPath(key),
ClassTypeInformation.from(valueType));
Object o = readInternal(key, typeInformation.getType(), new RedisData(partial));
@@ -920,7 +919,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
private Class<?> getTypeHint(String path, Bucket bucket, Class<?> fallback) {
TypeInformation<?> typeInformation = typeMapper.readType(BucketPropertyPath.from(bucket, path),
TypeInformation<?> typeInformation = typeMapper.readType(bucket.getPropertyPath(path),
ClassTypeInformation.from(fallback));
return typeInformation.getType();
}

View File

@@ -16,13 +16,14 @@
package org.springframework.data.redis.core.convert;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.redis.core.convert.Bucket.BucketPropertyPath;
/**
* Redis-specific {@link TypeMapper} exposing that {@link BucketPropertyPath}s might contain a type key.
*
* @author Mark Paluch
* @since 2.1
* @see BucketPropertyPath
* @see Bucket.BucketPropertyPath
*/
public interface RedisTypeMapper extends TypeMapper<BucketPropertyPath> {