chore[orm]: support map of basic types

This commit is contained in:
godotg
2024-06-17 10:53:07 +08:00
committed by awake
parent 3978e6ef12
commit fadc870078
13 changed files with 298 additions and 89 deletions
@@ -0,0 +1,53 @@
package com.zfoo.orm.codec;
import com.zfoo.orm.codec.basetype.*;
/**
* 基础类型枚举
* @Authorlqh
* @Date2024/6/17 11:41
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public enum BaseTypeEnum {
Float(java.lang.Float.class, new FloatMapCodec()),
Integer(java.lang.Integer.class, new IntMapCodec()),
Double(java.lang.Double.class, new DoubleMapCodec()),
Character(java.lang.Character.class, new CharacterMapCodec()),
Byte(java.lang.Byte.class, new ByteMapCodec()),
Boolean(java.lang.Boolean.class, new BooleanMapCodec()),
Long(java.lang.Long.class, new LongMapCodec()),
Short(java.lang.Short.class, new ShortMapCodec()),
;
private final MapKeyCodec mapKeyCodec;
private final Class<?> clazz;
BaseTypeEnum(Class<?> clazz, MapKeyCodec mapKeyCodec) {
this.clazz = clazz;
this.mapKeyCodec = mapKeyCodec;
}
public MapKeyCodec getMapKeyCodec() {
return mapKeyCodec;
}
public Class<?> getClazz() {
return clazz;
}
public static boolean containsKeyType(Class<?> keyClass){
for (BaseTypeEnum typeEnum : values()) {
if (typeEnum.getClazz() == keyClass) {
return true;
}
}
return false;
}
public static MapKeyCodec getCodec(Class<?> clazz) {
for (BaseTypeEnum typeEnum : values()) {
if (typeEnum.getClazz() == clazz) {
return typeEnum.getMapKeyCodec();
}
}
return null;
}
}
@@ -11,45 +11,49 @@ import java.util.HashMap;
import java.util.Map;
/**
* map解析器
*
* 基础类型作为key的map解析器
* @Authorlqh
* @Date2024/6/14 10:32
* @Date2024/6/17 13:55
*/
public class IntMapCodec<V> implements Codec<Map<Integer, V>> {
public class BaseTypeKeyMapCodec<K,V> implements Codec<Map<K, V>> {
private final Class<Map<Integer, V>> encoderClass;
private final Codec<Integer> keyCodec;
private final Class<Map<K, V>> encoderClass;
private final Codec<K> keyCodec;
private final Codec<V> valueCodec;
IntMapCodec(final Class<Map<Integer, V>> encoderClass, final Codec<Integer> keyCodec, final Codec<V> valueCodec) {
BaseTypeKeyMapCodec(final Class<Map<K, V>> encoderClass, final Codec<K> keyCodec, final Codec<V> valueCodec) {
this.encoderClass = encoderClass;
this.keyCodec = keyCodec;
this.valueCodec = valueCodec;
}
@Override
public void encode(final BsonWriter writer, final Map<Integer, V> map, final EncoderContext encoderContext) {
@SuppressWarnings({"unchecked"})
public void encode(final BsonWriter writer, final Map<K, V> map, final EncoderContext encoderContext) {
writer.writeStartDocument();
for (var entry : map.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
writer.writeName(key.toString());
MapKeyCodec<K> codec = BaseTypeEnum.getCodec(keyCodec.getEncoderClass());
String keyValue = codec.encode(key);
writer.writeName(keyValue);
if (value == null) {
writer.writeNull();
} else {
valueCodec.encode(writer, entry.getValue(), encoderContext);
valueCodec.encode(writer, value, encoderContext);
}
}
writer.writeEndDocument();
}
@Override
public Map<Integer, V> decode(final BsonReader reader, final DecoderContext context) {
@SuppressWarnings({"unchecked"})
public Map<K, V> decode(final BsonReader reader, final DecoderContext context) {
reader.readStartDocument();
var map = new HashMap<Integer, V>();
var map = new HashMap<K, V>();
while (!BsonType.END_OF_DOCUMENT.equals(reader.readBsonType())) {
int key = Integer.parseInt(reader.readName());
MapKeyCodec<K> codec = BaseTypeEnum.getCodec(keyCodec.getEncoderClass());
K key = codec.decode(reader.readName());
V value = null;
if (BsonType.NULL.equals(reader.getCurrentBsonType())) {
reader.readNull();
@@ -63,8 +67,9 @@ public class IntMapCodec<V> implements Codec<Map<Integer, V>> {
}
@Override
public Class<Map<Integer, V>> getEncoderClass() {
public Class<Map<K, V>> getEncoderClass() {
return encoderClass;
}
}
@@ -1,70 +0,0 @@
package com.zfoo.orm.codec;
import org.bson.BsonReader;
import org.bson.BsonType;
import org.bson.BsonWriter;
import org.bson.codecs.Codec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import java.util.HashMap;
import java.util.Map;
/**
* map解析器
*
* @Authorlqh
* @Date2024/6/14 10:32
*/
public class LongMapCodec<V> implements Codec<Map<Long, V>> {
private final Class<Map<Long, V>> encoderClass;
private final Codec<Long> keyCodec;
private final Codec<V> valueCodec;
LongMapCodec(final Class<Map<Long, V>> encoderClass, final Codec<Long> keyCodec, final Codec<V> valueCodec) {
this.encoderClass = encoderClass;
this.keyCodec = keyCodec;
this.valueCodec = valueCodec;
}
@Override
public void encode(final BsonWriter writer, final Map<Long, V> map, final EncoderContext encoderContext) {
writer.writeStartDocument();
for (var entry : map.entrySet()) {
var key = entry.getKey();
var value = entry.getValue();
writer.writeName(key.toString());
if (value == null) {
writer.writeNull();
} else {
valueCodec.encode(writer, entry.getValue(), encoderContext);
}
}
writer.writeEndDocument();
}
@Override
public Map<Long, V> decode(final BsonReader reader, final DecoderContext context) {
reader.readStartDocument();
var map = new HashMap<Long, V>();
while (!BsonType.END_OF_DOCUMENT.equals(reader.readBsonType())) {
long key = Long.parseLong(reader.readName());
V value = null;
if (BsonType.NULL.equals(reader.getCurrentBsonType())) {
reader.readNull();
} else {
value = valueCodec.decode(reader, context);
}
map.put(key, value);
}
reader.readEndDocument();
return map;
}
@Override
public Class<Map<Long, V>> getEncoderClass() {
return encoderClass;
}
}
@@ -1,5 +1,6 @@
package com.zfoo.orm.codec;
import org.bson.codecs.Codec;
import org.bson.codecs.pojo.PropertyCodecProvider;
import org.bson.codecs.pojo.PropertyCodecRegistry;
@@ -24,11 +25,8 @@ public class MapCodecProvider implements PropertyCodecProvider {
}
var keyType = typeParameters.get(0);
var valueType = typeParameters.get(1);
if (keyType.getType() == Integer.class) {
return new IntMapCodec(type.getType(), registry.get(keyType), registry.get(valueType));
}
if (keyType.getType() == Long.class) {
return new LongMapCodec(type.getType(), registry.get(keyType), registry.get(valueType));
if (BaseTypeEnum.containsKeyType(keyType.getType())){
return new BaseTypeKeyMapCodec(type.getType(), registry.get(keyType), registry.get(valueType));
}
return null;
}
@@ -0,0 +1,22 @@
package com.zfoo.orm.codec;
/**
* map key编码接口
* @Authorlqh
* @Date2024/6/17 13:51
*/
public interface MapKeyCodec<K> {
/**
* 编码
* @param value
* @return
*/
String encode(K value);
/**
* 解析
* @param text
* @return
*/
K decode(String text);
}
@@ -0,0 +1,37 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* @Authorlqh
* @Date2024/6/17 11:32
*/
public class BooleanMapCodec implements MapKeyCodec<Boolean> {
@Override
public String encode(Boolean value) {
return value ? "True" : "False";
}
@Override
public Boolean decode(String text) {
if (text == null) {
return null;
} else if (isValidName(true, text)) {
return true;
} else if (isValidName(false, text)) {
return false;
} else {
throw new java.lang.IllegalArgumentException(text);
}
}
private String getValidName(boolean value) {
return value ? "True" : "False";
}
private boolean isValidName(boolean value, String name) {
return getValidName(value).equalsIgnoreCase(name);
}
}
@@ -0,0 +1,22 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* @Authorlqh
* @Date2024/6/17 11:39
*/
public class ByteMapCodec implements MapKeyCodec<Byte> {
@Override
public String encode(Byte value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Byte decode(String text) {
return (text == null) ? null : Byte.decode(text);
}
}
@@ -0,0 +1,27 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
import org.springframework.util.StringUtils;
/**
* @Authorlqh
* @Date2024/6/17 11:34
*/
public class CharacterMapCodec implements MapKeyCodec<Character> {
@Override
public String encode(Character value) {
return (value != null)
? value.toString()
: "";
}
@Override
public Character decode(String text) {
if (!StringUtils.hasLength(text)) {
return null;
} else {
return text.charAt(0);
}
}
}
@@ -0,0 +1,22 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* @Authorlqh
* @Date2024/6/17 11:35
*/
public class DoubleMapCodec<V> implements MapKeyCodec<Double> {
@Override
public String encode(Double value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Double decode(String text) {
return (text == null) ? null : Double.valueOf(text);
}
}
@@ -0,0 +1,22 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* @Authorlqh
* @Date2024/6/17 11:38
*/
public class FloatMapCodec implements MapKeyCodec<Float> {
@Override
public String encode(Float value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Float decode(String text) {
return (text == null) ? null : Float.valueOf(text);
}
}
@@ -0,0 +1,25 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* map解析器
*
* @Authorlqh
* @Date2024/6/14 10:32
*/
public class IntMapCodec implements MapKeyCodec<Integer> {
@Override
public String encode(Integer value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Integer decode(String text) {
return (text == null) ? null : Integer.parseInt(text);
}
}
@@ -0,0 +1,25 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* map解析器
*
* @Authorlqh
* @Date2024/6/14 10:32
*/
public class LongMapCodec implements MapKeyCodec<Long> {
@Override
public String encode(Long value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Long decode(String text) {
return (text == null) ? null : Long.parseLong(text);
}
}
@@ -0,0 +1,21 @@
package com.zfoo.orm.codec.basetype;
import com.zfoo.orm.codec.MapKeyCodec;
/**
* @Authorlqh
* @Date2024/6/17 11:38
*/
public class ShortMapCodec<V> implements MapKeyCodec<Short> {
@Override
public String encode(Short value) {
return (value != null)
? value.toString()
: null;
}
@Override
public Short decode(String text) {
return (text == null) ? null : Short.parseShort(text);
}
}