Merge/Copy properties using reflection in Java
There is already build in function in org.springframework.beans.BeanUtils.copyProperties which you can use to copy properties. But if want some customisation or need simpler one you can use below method :
This method also merge the collection if found.
This method also merge the collection if found.
package com.vivek.references.spring.example.common.reference; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; public class MergeProperties { private static final Logger logger = LoggerFactory.getLogger(MergeProperties.class); @Setter @Getter @NoArgsConstructor @AllArgsConstructor @ToString static class Parent { private String name; private String id; } @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Builder @ToString(callSuper = true) static class Child extends Parent { private String var1; private String var2; private int version; private SetvalueSet; } @SuppressWarnings("unchecked") private static void copyMissingValues(T source, T target) { if (source == null || target == null) return; PropertyDescriptor[] propertyDescriptors; try { propertyDescriptors = Introspector.getBeanInfo(target.getClass()).getPropertyDescriptors(); } catch (IntrospectionException e) { return; } for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { Method writeMethod = propertyDescriptor.getWriteMethod(); if (Objects.nonNull(writeMethod)) { Method readMethod = propertyDescriptor.getReadMethod(); if (Objects.nonNull(readMethod)) { try { if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(target); if (Objects.isNull(value) || value.toString().isEmpty() || value.toString().equals("0")) { value = readMethod.invoke(source); if (Objects.nonNull(value)) { if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } } else if (Collection.class.isAssignableFrom(propertyDescriptor.getPropertyType())) { // merge collection Collection sourceValues = (Collection)readMethod.invoke(source); if (Objects.nonNull(sourceValues)) { Collections.addAll((Collection)value, sourceValues.toArray()); } } } catch (Throwable ex) { logger.error("{}", ex); } } } } } public static void main(String[] args) throws IntrospectionException { Child child1 = new Child(); child1.setId("40"); child1.setName("A"); child1.setVar1("Value 1"); child1.setVar2("10"); child1.setVersion(1); child1.setValueSet(new HashSet<>(Arrays.asList("A", "B", "C"))); Child child2 = new Child(); child2.setName("B"); child2.setVar2("50"); child2.setValueSet(new HashSet<>(Arrays.asList("D", "E", "C"))); MergeProperties.copyMissingValues(child1, child2); logger.info("{}", child2); } }
Comments
Post a Comment