From 921aedaf9d31783bb1c0a5165b30de240fee2e20 Mon Sep 17 00:00:00 2001 From: Redkale <22250530@qq.com> Date: Mon, 25 Dec 2017 10:12:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0Optional=E7=9A=84=E5=BA=8F?= =?UTF-8?q?=E5=88=97=E5=8C=96=E5=92=8C=E5=8F=8D=E5=BA=8F=E5=88=97=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redkale/convert/CollectionDecoder.java | 2 +- src/org/redkale/convert/ConvertFactory.java | 4 + src/org/redkale/convert/MapEncoder.java | 24 +--- src/org/redkale/convert/OptionalCoder.java | 107 ++++++++++++++++++ .../redkale/test/convert/BsonTestMain.java | 18 +++ 5 files changed, 133 insertions(+), 22 deletions(-) create mode 100644 src/org/redkale/convert/OptionalCoder.java diff --git a/src/org/redkale/convert/CollectionDecoder.java b/src/org/redkale/convert/CollectionDecoder.java index 23e3a5c5a..2ff8efb49 100644 --- a/src/org/redkale/convert/CollectionDecoder.java +++ b/src/org/redkale/convert/CollectionDecoder.java @@ -50,7 +50,7 @@ public final class CollectionDecoder implements Decodeable { decoder = new StreamDecoder(this, type); } else if (Map.class.isAssignableFrom(clazz)) { decoder = new MapDecoder(this, type); + } else if (Optional.class == clazz) { + decoder = new OptionalCoder(this, type); } else if (clazz == Object.class) { od = new ObjectDecoder(type); decoder = od; @@ -553,6 +555,8 @@ public abstract class ConvertFactory { encoder = new StreamEncoder(this, type); } else if (Map.class.isAssignableFrom(clazz)) { encoder = new MapEncoder(this, type); + } else if (Optional.class == clazz) { + encoder = new OptionalCoder(this, type); } else if (clazz == Object.class) { return (Encodeable) this.anyEncoder; } else if (!clazz.getName().startsWith("java.") || java.net.HttpCookie.class == clazz) { diff --git a/src/org/redkale/convert/MapEncoder.java b/src/org/redkale/convert/MapEncoder.java index 6c60f64a4..d7be51a38 100644 --- a/src/org/redkale/convert/MapEncoder.java +++ b/src/org/redkale/convert/MapEncoder.java @@ -28,12 +28,6 @@ public final class MapEncoder implements Encodeable> { private final Encodeable valencoder; - private final Encodeable stringencoder; - - private final boolean keyany; - - private final boolean valany; - private boolean inited = false; private final Object lock = new Object(); @@ -49,9 +43,6 @@ public final class MapEncoder implements Encodeable> { this.keyencoder = factory.getAnyEncoder(); this.valencoder = factory.getAnyEncoder(); } - this.keyany = this.keyencoder == factory.getAnyEncoder(); - this.valany = this.valencoder == factory.getAnyEncoder(); - this.stringencoder = factory.loadEncoder(String.class); } finally { inited = true; synchronized (lock) { @@ -67,6 +58,7 @@ public final class MapEncoder implements Encodeable> { out.writeNull(); return; } + if (this.keyencoder == null || this.valencoder == null) { if (!this.inited) { synchronized (lock) { @@ -82,19 +74,9 @@ public final class MapEncoder implements Encodeable> { boolean first = true; for (Map.Entry en : values.entrySet()) { if (!first) out.writeArrayMark(); - K key = en.getKey(); - V val = en.getValue(); - if (keyany && key instanceof String) { - this.stringencoder.convertTo(out, key); - } else { - this.keyencoder.convertTo(out, key); - } + this.keyencoder.convertTo(out, en.getKey()); out.writeMapMark(); - if (valany && val instanceof String) { - this.stringencoder.convertTo(out, val); - } else { - this.valencoder.convertTo(out, val); - } + this.valencoder.convertTo(out, en.getValue()); if (first) first = false; } out.writeMapE(); diff --git a/src/org/redkale/convert/OptionalCoder.java b/src/org/redkale/convert/OptionalCoder.java new file mode 100644 index 000000000..189fc659a --- /dev/null +++ b/src/org/redkale/convert/OptionalCoder.java @@ -0,0 +1,107 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.redkale.convert; + +import java.lang.reflect.*; +import java.util.*; + +/** + * Optional 的SimpledCoder实现 + * + *

+ * 详情见: https://redkale.org + * + * @author zhangjx + * @param Reader输入的子类型 + * @param Writer输出的子类型 + */ +public class OptionalCoder extends SimpledCoder> { + + private final Type type; + + private final Type componentType; + + protected final Class componentClass; + + protected final Decodeable decoder; + + protected final Encodeable encoder; + + private boolean inited = false; + + private final Object lock = new Object(); + + public OptionalCoder(final ConvertFactory factory, final Type type) { + this.type = type; + try { + if (type instanceof ParameterizedType) { + final ParameterizedType pt = (ParameterizedType) type; + this.componentType = pt.getActualTypeArguments()[0]; + factory.register(type, this); + this.decoder = factory.loadDecoder(this.componentType); + if (this.componentType instanceof TypeVariable) { + this.encoder = factory.getAnyEncoder(); + this.componentClass = Object.class; + } else { + if (componentType instanceof ParameterizedType) { + final ParameterizedType pt2 = (ParameterizedType) componentType; + this.componentClass = (Class) pt2.getRawType(); + } else { + this.componentClass = (Class) componentType; + } + this.encoder = factory.loadEncoder(this.componentType); + } + } else { + this.componentType = Object.class; + this.componentClass = Object.class; + this.decoder = factory.loadDecoder(this.componentType); + this.encoder = factory.getAnyEncoder(); + } + } finally { + inited = true; + synchronized (lock) { + lock.notifyAll(); + } + } + } + + @Override + public void convertTo(W out, Optional value) { + if (value == null || !value.isPresent()) { + out.writeObjectNull(null); + return; + } + if (this.encoder == null) { + if (!this.inited) { + synchronized (lock) { + try { + lock.wait(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + this.encoder.convertTo(out, value.get()); + } + + @Override + public Optional convertFrom(R in) { + if (this.decoder == null) { + if (!this.inited) { + synchronized (lock) { + try { + lock.wait(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + return Optional.ofNullable(this.decoder.convertFrom(in)); + } + +} diff --git a/test/org/redkale/test/convert/BsonTestMain.java b/test/org/redkale/test/convert/BsonTestMain.java index ecf845c48..b2ccf6aa7 100644 --- a/test/org/redkale/test/convert/BsonTestMain.java +++ b/test/org/redkale/test/convert/BsonTestMain.java @@ -13,6 +13,7 @@ import org.redkale.convert.bson.BsonConvert; import java.nio.*; import java.util.*; import org.redkale.convert.json.*; +import org.redkale.util.*; /** * @@ -31,6 +32,7 @@ public class BsonTestMain { main3(args); main4(args); main5(args); + main6(args); } public static void main2(String[] args) throws Exception { @@ -98,4 +100,20 @@ public class BsonTestMain { Object mapobj = convert.convertFrom(Object.class, bs); System.out.println(mapobj); } + + public static void main6(String[] args) throws Exception { + final BsonConvert convert = BsonFactory.root().getConvert(); + + Optional val = Optional.ofNullable("haha"); + byte[] bs = convert.convertTo(val); + Object obj = convert.convertFrom(Optional.class, bs); + System.out.println(obj); + bs = convert.convertTo(Object.class, val); + obj = convert.convertFrom(Object.class, bs); + System.out.println(obj); + bs = convert.convertTo(new TypeToken>(){}.getType(), val); + obj = convert.convertFrom(new TypeToken>(){}.getType(), bs); + System.out.println(obj); + System.out.println(JsonConvert.root().convertTo(val)); + } }