mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-06-01 06:13:55 +00:00
chore[orm]: support map of basic types
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
package com.zfoo.orm.codec;
|
||||
|
||||
import com.zfoo.orm.codec.basetype.*;
|
||||
|
||||
/**
|
||||
* 基础类型枚举
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
}
|
||||
}
|
||||
+19
-14
@@ -11,45 +11,49 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* map解析器
|
||||
*
|
||||
* 基础类型作为key的map解析器
|
||||
* @Author:lqh
|
||||
* @Date:2024/6/14 10:32
|
||||
* @Date:2024/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解析器
|
||||
*
|
||||
* @Author:lqh
|
||||
* @Date:2024/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编码接口
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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解析器
|
||||
*
|
||||
* @Author:lqh
|
||||
* @Date:2024/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解析器
|
||||
*
|
||||
* @Author:lqh
|
||||
* @Date:2024/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;
|
||||
|
||||
/**
|
||||
* @Author:lqh
|
||||
* @Date:2024/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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user