From ee6c22f5acc2b6fb721d3a9cdc28815fb83bc59d Mon Sep 17 00:00:00 2001 From: yangtu222 Date: Fri, 20 Jul 2018 10:52:18 +0800 Subject: [PATCH] IGNORE_ALL_NULL_SOURCE_VALUE for v1.0.7 --- README.md | 9 +++- pom.xml | 4 +- .../beanutils/annotation/CopyFeature.java | 1 + .../beanutils/internal/dump/BeanCopyDump.java | 21 +++++++- .../javassist/JavassistBeanCopyFactory.java | 10 +++- .../internal/reflect/ReflectBeanCopy.java | 3 ++ .../tuyang/test/testIgnoreAll/FromBean.java | 44 +++++++++++++++++ .../tuyang/test/testIgnoreAll/FromBean2.java | 22 +++++++++ .../test/testIgnoreAll/TestIgnoreAll.java | 40 ++++++++++++++++ .../com/tuyang/test/testIgnoreAll/ToBean.java | 48 +++++++++++++++++++ 10 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/tuyang/test/testIgnoreAll/FromBean.java create mode 100644 src/test/java/com/tuyang/test/testIgnoreAll/FromBean2.java create mode 100644 src/test/java/com/tuyang/test/testIgnoreAll/TestIgnoreAll.java create mode 100644 src/test/java/com/tuyang/test/testIgnoreAll/ToBean.java diff --git a/README.md b/README.md index 0461889..bc419a5 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This BeanUtils library is a Java bean copy utility with powerful functionality a com.github.yangtu222 BeanUtils - 1.0.6 + 1.0.7 ~~~ @@ -26,6 +26,7 @@ This BeanUtils library is a Java bean copy utility with powerful functionality a * easy debug by dump the property mappings, and can be disabled using BeanCopyConfig. (version 1.0.2 ) * support copy with Java Enum <=> String (v1.0.4, thanks TuWei1992) * support copy from JavaBean to String (v1.0.4, thanks TuWei1992, using Object.toString() ) +* support one copy feature (IGNORE_ALL_NULL_SOURCE_VALUE) (v1.0.7, thanks sj853) ## A full Sample: @@ -153,9 +154,13 @@ Specify the source object class. #### features Specify the copy features. The features are: * IGNORE_PRIMITIVE_NULL_SOURCE_VALUE - Ignore copy object type null to primitive type. e.g. Copy null (Integer type) to int. + Ignore copying source null property to target primitive type property. e.g. Copy null (Integer type) to int. By default this feature is disabled, so we can debug where the pointer is null by thrown exception. +* IGNORE_ALL_NULL_SOURCE_VALUE + Ignore copying source null property to target property. + By default this feature is disabled. + * IGNORE_ENUM_CONVERT_EXCEPTION Ignore exceptions when converting from String to Enum when call Enum.valueOf(). This will happens when converting an invalid String value to Enum, and null will be set in this situation. diff --git a/pom.xml b/pom.xml index b3ed309..2adc005 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.yangtu222 BeanUtils BeanUtils - 1.0.6 + 1.0.7 BeanUtils library is a Java bean copy utility with powerful functionality and high performance. https://github.com/yangtu222/BeanUtils @@ -27,7 +27,7 @@ scm:git:https://github.com/yangtu222/BeanUtils.git scm:git:https://github.com/yangtu222/BeanUtils.git https://github.com/yangtu222/BeanUtils.git - v1.0.2 + v1.0.7 diff --git a/src/main/java/com/tuyang/beanutils/annotation/CopyFeature.java b/src/main/java/com/tuyang/beanutils/annotation/CopyFeature.java index 6ca11ba..8498303 100644 --- a/src/main/java/com/tuyang/beanutils/annotation/CopyFeature.java +++ b/src/main/java/com/tuyang/beanutils/annotation/CopyFeature.java @@ -2,6 +2,7 @@ public enum CopyFeature { IGNORE_PRIMITIVE_NULL_SOURCE_VALUE, + IGNORE_ALL_NULL_SOURCE_VALUE, IGNORE_ENUM_CONVERT_EXCEPTION, ENABLE_JAVA_BEAN_TO_STRING, } diff --git a/src/main/java/com/tuyang/beanutils/internal/dump/BeanCopyDump.java b/src/main/java/com/tuyang/beanutils/internal/dump/BeanCopyDump.java index 79a4025..c9d157e 100644 --- a/src/main/java/com/tuyang/beanutils/internal/dump/BeanCopyDump.java +++ b/src/main/java/com/tuyang/beanutils/internal/dump/BeanCopyDump.java @@ -6,6 +6,8 @@ import java.util.Collection; import java.util.List; +import com.tuyang.beanutils.annotation.BeanCopySource; +import com.tuyang.beanutils.annotation.CopyFeature; import com.tuyang.beanutils.config.BeanCopyConfig; import com.tuyang.beanutils.config.BeanCopyConfig.DumpOption; import com.tuyang.beanutils.internal.cache.BeanCopyCache; @@ -105,7 +107,24 @@ private static void dumpPropertyMappingInternal(Class sourceClass, Class t logger.info("---------------------------------------------------------------------------------------------"); logger.info("From: [" + sourceClass.getSimpleName() + "] To: [" + targetClass.getSimpleName() + "] Option: [" + optionClass.getSimpleName() + "]"); logger.info("---------------------------------------------------------------------------------------------"); - + CopyFeature[] features = null; + if( optionClass != null && optionClass.isAnnotationPresent(BeanCopySource.class)) { + BeanCopySource copyAnnotation = optionClass.getAnnotation(BeanCopySource.class); + features = copyAnnotation.features(); + } else if( targetClass.isAnnotationPresent(BeanCopySource.class)) { + BeanCopySource copyAnnotation = targetClass.getAnnotation(BeanCopySource.class); + features = copyAnnotation.features(); + } + if( features == null ) { + logger.info("CopyFeature: (NONE)"); + } else { + logger.info("CopyFeature:"); + for( CopyFeature f : features) { + logger.info(" " + f.toString()); + } + } + logger.info("---------------------------------------------------------------------------------------------"); + if( itemList == null ) itemList = BeanCopyCache.buildBeanCopyPropertyItem(sourceClass, targetClass, optionClass); diff --git a/src/main/java/com/tuyang/beanutils/internal/javassist/JavassistBeanCopyFactory.java b/src/main/java/com/tuyang/beanutils/internal/javassist/JavassistBeanCopyFactory.java index 1cc9aa0..3558768 100644 --- a/src/main/java/com/tuyang/beanutils/internal/javassist/JavassistBeanCopyFactory.java +++ b/src/main/java/com/tuyang/beanutils/internal/javassist/JavassistBeanCopyFactory.java @@ -178,14 +178,22 @@ else if( item.convertorClass != null ) { + writeType.getName() +".class ) );\n"); } else { if( writeType.isPrimitive() && !readType.isPrimitive() ) { - boolean ignoreInvoke = findFeature(features, CopyFeature.IGNORE_PRIMITIVE_NULL_SOURCE_VALUE ); + boolean ignoreInvoke = findFeature(features, CopyFeature.IGNORE_ALL_NULL_SOURCE_VALUE ); + if( !ignoreInvoke ) + ignoreInvoke = findFeature(features, CopyFeature.IGNORE_PRIMITIVE_NULL_SOURCE_VALUE ); if( ignoreInvoke ) sb.append("if ( "+sourceMethod +" != null ) { \n"); sb.append("target." + item.writeMethod.getName() +"( "+sourceMethod + "." + writeType.toString() +"Value() );\n"); if( ignoreInvoke ) sb.append("}\n"); } else if( !writeType.isPrimitive() && readType.isPrimitive() ) { sb.append("target." + item.writeMethod.getName() +"( "+ getPrimitiveName(readType) +".valueOf(" + sourceMethod + " ) );\n"); + } else if( !readType.isPrimitive() ) { + boolean ignoreInvoke = findFeature(features, CopyFeature.IGNORE_ALL_NULL_SOURCE_VALUE ); + if( ignoreInvoke ) sb.append("if ( "+sourceMethod +" != null ) { \n"); + sb.append("target." + item.writeMethod.getName() +"( "+sourceMethod + " );\n"); + if( ignoreInvoke ) sb.append("}\n"); } else { sb.append("target." + item.writeMethod.getName() +"( "+sourceMethod + " );\n"); + } } diff --git a/src/main/java/com/tuyang/beanutils/internal/reflect/ReflectBeanCopy.java b/src/main/java/com/tuyang/beanutils/internal/reflect/ReflectBeanCopy.java index 94a0d26..44b860a 100644 --- a/src/main/java/com/tuyang/beanutils/internal/reflect/ReflectBeanCopy.java +++ b/src/main/java/com/tuyang/beanutils/internal/reflect/ReflectBeanCopy.java @@ -130,6 +130,9 @@ else if( item.convertorClass != null ) { if( targetPropertyType.isPrimitive() && sourceData == null ) { ignoreInvoke = findFeature( CopyFeature.IGNORE_PRIMITIVE_NULL_SOURCE_VALUE ); } + if( !ignoreInvoke && sourceData == null) { + ignoreInvoke = findFeature( CopyFeature.IGNORE_ALL_NULL_SOURCE_VALUE ); + } if( !ignoreInvoke ) { item.writeMethod.invoke(targetObject, sourceData ); } diff --git a/src/test/java/com/tuyang/test/testIgnoreAll/FromBean.java b/src/test/java/com/tuyang/test/testIgnoreAll/FromBean.java new file mode 100644 index 0000000..fa8859a --- /dev/null +++ b/src/test/java/com/tuyang/test/testIgnoreAll/FromBean.java @@ -0,0 +1,44 @@ +package com.tuyang.test.testIgnoreAll; + +public class FromBean { + + private int beanInt; + private long beanLong; + + private String beanString; + + private FromBean2 bean2; + + public int getBeanInt() { + return beanInt; + } + + public void setBeanInt(int beanInt) { + this.beanInt = beanInt; + } + + public long getBeanLong() { + return beanLong; + } + + public void setBeanLong(long beanLong) { + this.beanLong = beanLong; + } + + public String getBeanString() { + return beanString; + } + + public void setBeanString(String beanString) { + this.beanString = beanString; + } + + public FromBean2 getBean2() { + return bean2; + } + + public void setBean2(FromBean2 bean2) { + this.bean2 = bean2; + } + +} \ No newline at end of file diff --git a/src/test/java/com/tuyang/test/testIgnoreAll/FromBean2.java b/src/test/java/com/tuyang/test/testIgnoreAll/FromBean2.java new file mode 100644 index 0000000..aae9fa6 --- /dev/null +++ b/src/test/java/com/tuyang/test/testIgnoreAll/FromBean2.java @@ -0,0 +1,22 @@ +package com.tuyang.test.testIgnoreAll; + +public class FromBean2 { + + private Float beanFloat; + private String beanString; + + public Float getBeanFloat() { + return beanFloat; + } + public void setBeanFloat(Float beanFloat) { + this.beanFloat = beanFloat; + } + public String getBeanString() { + return beanString; + } + public void setBeanString(String beanString) { + this.beanString = beanString; + } + + +} \ No newline at end of file diff --git a/src/test/java/com/tuyang/test/testIgnoreAll/TestIgnoreAll.java b/src/test/java/com/tuyang/test/testIgnoreAll/TestIgnoreAll.java new file mode 100644 index 0000000..9f717c2 --- /dev/null +++ b/src/test/java/com/tuyang/test/testIgnoreAll/TestIgnoreAll.java @@ -0,0 +1,40 @@ +package com.tuyang.test.testIgnoreAll; + +import static org.junit.Assert.*; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.tuyang.beanutils.BeanCopyUtils; + +public class TestIgnoreAll { + + private FromBean getFromBean() { + FromBean fromBean = new FromBean(); + fromBean.setBeanInt(100); + fromBean.setBeanLong(200); + fromBean.setBeanString(null); + + FromBean2 bean2 = new FromBean2(); + bean2.setBeanFloat(10.4f); + bean2.setBeanString(null); + + fromBean.setBean2(bean2); + + return fromBean; + } + + @Test + public void testIgnoreAll() { + FromBean fromBean = getFromBean(); + ToBean toBean = new ToBean(); + toBean.setBeanString("Not Empty"); + toBean.setBean2String("Not Empty"); + BeanCopyUtils.copyBean(fromBean, toBean); + assertEquals( toBean.getBeanString(), "Not Empty" ); + assertEquals( toBean.getBean2String(), "Not Empty" ); + } +} + diff --git a/src/test/java/com/tuyang/test/testIgnoreAll/ToBean.java b/src/test/java/com/tuyang/test/testIgnoreAll/ToBean.java new file mode 100644 index 0000000..4fefeb1 --- /dev/null +++ b/src/test/java/com/tuyang/test/testIgnoreAll/ToBean.java @@ -0,0 +1,48 @@ +package com.tuyang.test.testIgnoreAll; + +import com.tuyang.beanutils.annotation.BeanCopySource; +import com.tuyang.beanutils.annotation.CopyProperty; +import com.tuyang.beanutils.annotation.CopyFeature; + +@BeanCopySource(source=FromBean.class, features={CopyFeature.IGNORE_ALL_NULL_SOURCE_VALUE}) +public class ToBean { + + private Integer beanInt; + private long beanLong; + private String beanString; + + @CopyProperty(property="bean2.beanString") + private String bean2String; + + public Integer getBeanInt() { + return beanInt; + } + + public void setBeanInt(Integer beanInt) { + this.beanInt = beanInt; + } + + public long getBeanLong() { + return beanLong; + } + + public void setBeanLong(long beanLong) { + this.beanLong = beanLong; + } + + public String getBeanString() { + return beanString; + } + + public void setBeanString(String beanString) { + this.beanString = beanString; + } + + public String getBean2String() { + return bean2String; + } + + public void setBean2String(String bean2String) { + this.bean2String = bean2String; + } +} \ No newline at end of file