From 906c147ed69850f4ebc66b601b4ae5caca0dc725 Mon Sep 17 00:00:00 2001 From: redkale Date: Sun, 6 Aug 2023 00:27:14 +0800 Subject: [PATCH] =?UTF-8?q?Reproduce=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/org/redkale/util/Reproduce.java | 158 ++++++++++++------ .../org/redkale/util/ResourceFactory.java | 2 +- .../redkale/test/util/ReproduceBeanMap.java | 50 ++++++ .../redkale/test/util/ReproduceMapBean.java | 31 ++++ .../org/redkale/test/util/ReproduceTest.java | 27 +++ .../redkale/test/util/ResourceLoaderTest.java | 8 +- 6 files changed, 218 insertions(+), 58 deletions(-) create mode 100644 src/test/java/org/redkale/test/util/ReproduceBeanMap.java create mode 100644 src/test/java/org/redkale/test/util/ReproduceMapBean.java diff --git a/src/main/java/org/redkale/util/Reproduce.java b/src/main/java/org/redkale/util/Reproduce.java index 0e9b2d187..ee80eb5f8 100644 --- a/src/main/java/org/redkale/util/Reproduce.java +++ b/src/main/java/org/redkale/util/Reproduce.java @@ -182,6 +182,7 @@ public interface Reproduce extends BiFunction { */ @SuppressWarnings("unchecked") public static Reproduce create(final Class destClass, final Class srcClass, final BiPredicate srcColumnPredicate, final Map names) { + final boolean allowMapNull = !ConcurrentHashMap.class.isAssignableFrom(destClass); if (Map.class.isAssignableFrom(destClass) && Map.class.isAssignableFrom(srcClass)) { final Map names0 = names; if (srcColumnPredicate != null) { @@ -189,7 +190,7 @@ public interface Reproduce extends BiFunction { return (D dest, S src) -> { Map d = (Map) dest; ((Map) src).forEach((k, v) -> { - if (srcColumnPredicate.test(null, k.toString())) { + if (srcColumnPredicate.test(null, k.toString()) && (allowMapNull || v != null)) { d.put(names0.getOrDefault(k, k), v); } }); @@ -199,7 +200,7 @@ public interface Reproduce extends BiFunction { return (D dest, S src) -> { Map d = (Map) dest; ((Map) src).forEach((k, v) -> { - if (srcColumnPredicate.test(null, k.toString())) { + if (srcColumnPredicate.test(null, k.toString()) && (allowMapNull || v != null)) { d.put(k, v); } }); @@ -210,7 +211,9 @@ public interface Reproduce extends BiFunction { return (D dest, S src) -> { Map d = (Map) dest; ((Map) src).forEach((k, v) -> { - d.put(names0.getOrDefault(k, k), v); + if (allowMapNull || v != null) { + d.put(names0.getOrDefault(k, k), v); + } }); return dest; }; @@ -218,7 +221,16 @@ public interface Reproduce extends BiFunction { return new Reproduce() { @Override public D apply(D dest, S src) { - ((Map) dest).putAll((Map) src); + if (allowMapNull) { + ((Map) dest).putAll((Map) src); + } else { + Map d = (Map) dest; + ((Map) src).forEach((k, v) -> { + if (v != null) { + d.put(names0.getOrDefault(k, k), v); + } + }); + } return dest; } }; @@ -320,7 +332,7 @@ public interface Reproduce extends BiFunction { } mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$0", "(" + destDesc + "Ljava/lang/Object;Ljava/lang/Object;)V", null, null); - Label ifLabel = new Label(); + Label goLabel = new Label(); int i = 0; for (Map.Entry en : elements.entrySet()) { final int index = ++i; @@ -330,12 +342,17 @@ public interface Reproduce extends BiFunction { final Class fieldClass = en.getValue() instanceof Field ? ((Field) en.getValue()).getType() : ((Method) en.getValue()).getParameterTypes()[0]; + final boolean primitive = fieldClass.isPrimitive(); mv.visitLdcInsn(en.getKey()); mv.visitVarInsn(ALOAD, 1); mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false); - Label ifeq = index == elements.size() ? ifLabel : new Label(); + Label ifeq = index == elements.size() ? goLabel : new Label(); mv.visitJumpInsn(IFEQ, ifeq); + if (primitive) { + mv.visitVarInsn(ALOAD, 2); + mv.visitJumpInsn(IFNULL, ifeq); + } mv.visitVarInsn(ALOAD, 0); if (fieldClass == boolean.class) { @@ -394,10 +411,12 @@ public interface Reproduce extends BiFunction { Method setter = (Method) en.getValue(); mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface()); } - if (index != elements.size()) { - mv.visitJumpInsn(GOTO, ifLabel); + if (index == elements.size()) { + mv.visitLabel(goLabel); + } else { + mv.visitJumpInsn(GOTO, goLabel); + mv.visitLabel(ifeq); } - mv.visitLabel(ifeq); mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } @@ -426,31 +445,47 @@ public interface Reproduce extends BiFunction { final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname); if (destIsMap) { - mv.visitVarInsn(ALOAD, 1); - mv.visitLdcInsn(dfname); - mv.visitVarInsn(ALOAD, 2); Class st = field.getType(); String td = Type.getDescriptor(st); - mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); - if (st == boolean.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - } else if (st == byte.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); - } else if (st == short.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); - } else if (st == char.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); - } else if (st == int.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); - } else if (st == float.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); - } else if (st == long.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); - } else if (st == double.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + if (allowMapNull || st.isPrimitive()) { + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 2); + mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); + if (st == boolean.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (st == byte.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (st == short.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (st == char.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); + } else if (st == int.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (st == float.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (st == long.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (st == double.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + } + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); + mv.visitInsn(POP); + } else { + mv.visitVarInsn(ALOAD, 2); + mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td); + mv.visitVarInsn(ASTORE, 3); + mv.visitVarInsn(ALOAD, 3); + Label ifLabel = new Label(); + mv.visitJumpInsn(IFNULL, ifLabel); + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 3); + mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true); + mv.visitInsn(POP); + mv.visitLabel(ifLabel); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } - mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); - mv.visitInsn(POP); } else { java.lang.reflect.Method setter = null; try { @@ -506,29 +541,46 @@ public interface Reproduce extends BiFunction { final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname); if (destIsMap) { Class st = getter.getReturnType(); - mv.visitVarInsn(ALOAD, 1); - mv.visitLdcInsn(dfname); - mv.visitVarInsn(ALOAD, 2); - mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface()); - if (st == boolean.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); - } else if (st == byte.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); - } else if (st == short.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); - } else if (st == char.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); - } else if (st == int.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); - } else if (st == float.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); - } else if (st == long.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); - } else if (st == double.class) { - mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + if (allowMapNull || st.isPrimitive()) { + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface()); + if (st == boolean.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false); + } else if (st == byte.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false); + } else if (st == short.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false); + } else if (st == char.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false); + } else if (st == int.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false); + } else if (st == float.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false); + } else if (st == long.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false); + } else if (st == double.class) { + mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false); + } + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); + mv.visitInsn(POP); + } else { + mv.visitVarInsn(ALOAD, 2); + mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface()); + mv.visitVarInsn(ASTORE, 3); + mv.visitVarInsn(ALOAD, 3); + Label ifLabel = new Label(); + mv.visitJumpInsn(IFNULL, ifLabel); + mv.visitVarInsn(ALOAD, 1); + mv.visitLdcInsn(dfname); + mv.visitVarInsn(ALOAD, 3); + mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); + mv.visitInsn(POP); + mv.visitLabel(ifLabel); + mv.visitLineNumber(47, ifLabel); + mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null); } - mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface()); - mv.visitInsn(POP); } else { java.lang.reflect.Method setter = null; java.lang.reflect.Field srcField = null; diff --git a/src/main/java/org/redkale/util/ResourceFactory.java b/src/main/java/org/redkale/util/ResourceFactory.java index 0a6c01c3d..a35668426 100644 --- a/src/main/java/org/redkale/util/ResourceFactory.java +++ b/src/main/java/org/redkale/util/ResourceFactory.java @@ -965,7 +965,7 @@ public final class ResourceFactory { } } } - if (rs == null && re == null && autoRegNull && rcname.indexOf('$') < 0) { + if (rs == null && re == null && autoRegNull && rcname.indexOf(Resource.PARENT_NAME) < 0) { register(rcname, gencType, null); //自动注入null的值 re = findEntry(rcname, gencType); } diff --git a/src/test/java/org/redkale/test/util/ReproduceBeanMap.java b/src/test/java/org/redkale/test/util/ReproduceBeanMap.java new file mode 100644 index 000000000..e2701e986 --- /dev/null +++ b/src/test/java/org/redkale/test/util/ReproduceBeanMap.java @@ -0,0 +1,50 @@ +/* + * + */ +package org.redkale.test.util; + +import java.util.Map; +import org.redkale.util.Reproduce; + +/** + * + * @author zhangjx + */ +public class ReproduceBeanMap implements Reproduce, TestInterface> { + + @Override + public Map apply(Map dest, TestInterface src) { + Object v; + dest.put("id", src.getId()); + + v = src.getMap(); + if (v != null) { + dest.put("map", v); + } + return dest; + } + + public Map run(Map dest, TestBean src) { + Object v; + + v = src.getName(); + if (v != null) { + dest.put("name", v); + } + + v = src.time; + if (v != null) { + dest.put("time", v); + } + + dest.put("id", src.getId()); + + v = src.getName(); + if (v != null) { + dest.put("name", v); + } +// + return dest; + } + +} diff --git a/src/test/java/org/redkale/test/util/ReproduceMapBean.java b/src/test/java/org/redkale/test/util/ReproduceMapBean.java new file mode 100644 index 000000000..3b3d017d4 --- /dev/null +++ b/src/test/java/org/redkale/test/util/ReproduceMapBean.java @@ -0,0 +1,31 @@ +/* + * + */ +package org.redkale.test.util; + +import java.util.*; +import org.redkale.util.*; + +/** + * @author zhangjx + */ +public class ReproduceMapBean implements Reproduce { + + @Override + public TestBean apply(TestBean dest, HashMap src) { + src.forEach((k, v) -> { + if ("id".equals(k) && v != null) { + dest.setId(Utility.convertValue(int.class, v)); + } else if ("map".equals(k)) { + dest.setMap(Utility.convertValue(Map.class, v)); + } else if ("map2".equals(k) && v != null) { + dest.setMap(Utility.convertValue(Map.class, v)); + } else if ("time".equals(k)) { + dest.time = Utility.convertValue(long.class, v); + } else { + + } + }); + return dest; + } +} diff --git a/src/test/java/org/redkale/test/util/ReproduceTest.java b/src/test/java/org/redkale/test/util/ReproduceTest.java index d6f9d3b0e..b963be205 100644 --- a/src/test/java/org/redkale/test/util/ReproduceTest.java +++ b/src/test/java/org/redkale/test/util/ReproduceTest.java @@ -4,6 +4,7 @@ package org.redkale.test.util; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import org.junit.jupiter.api.*; import org.redkale.convert.json.JsonConvert; import org.redkale.util.*; @@ -21,6 +22,8 @@ public class ReproduceTest { test.run3(); test.run4(); test.run5(); + test.run6(); + test.run7(); } @Test @@ -87,4 +90,28 @@ public class ReproduceTest { System.out.println("Map: " + JsonConvert.root().convertTo(rs)); Assertions.assertEquals(JsonConvert.root().convertTo(map), JsonConvert.root().convertTo(rs)); } + + @Test + public void run6() throws Exception { + TestBean bean = new TestBean(); + bean.setId(222); + bean.time = 55555L; + bean.setName(null); + bean.setMap(Utility.ofMap("aa", "bbb")); + ConcurrentHashMap rs = Reproduce.copy(ConcurrentHashMap.class, bean); + System.out.println(JsonConvert.root().convertTo(rs)); + System.out.println("------------------------------------------"); + } + + @Test + public void run7() throws Exception { + TestBean bean = new TestBean(); + Map map = new TreeMap(); + map.put("name", "haha"); + map.put("time", "55555"); + map.put("id", null); + map.put("map", Utility.ofMap("aa", "bbb")); + Reproduce.load(TestBean.class, Map.class).apply(bean, map); + System.out.println(JsonConvert.root().convertTo(bean)); + } } diff --git a/src/test/java/org/redkale/test/util/ResourceLoaderTest.java b/src/test/java/org/redkale/test/util/ResourceLoaderTest.java index 54a73b443..1af3352ed 100644 --- a/src/test/java/org/redkale/test/util/ResourceLoaderTest.java +++ b/src/test/java/org/redkale/test/util/ResourceLoaderTest.java @@ -2,10 +2,10 @@ */ package org.redkale.test.util; -import org.redkale.annotation.Resource; import org.junit.jupiter.api.*; +import org.redkale.annotation.Resource; import org.redkale.convert.json.JsonFactory; -import org.redkale.util.*; +import org.redkale.util.ResourceFactory; /** * @@ -46,10 +46,10 @@ public class ResourceLoaderTest { public static class Bean { - @Resource(name = "$.id") + @Resource(name = "#.id") public int id; - @Resource(name = "$.name") + @Resource(name = "#.name") public String name; public Bean() {