Reputation: 557
I need to merge values of 2 objects in Java, same properties.
The values of object 1 have priority over object 2. If on the other hand the value of object 1 is null, then we take the value of object 2.
So i have this objet which references other objets ( again and again )
@Data
@NoArgsConstructor
@AllArgsConstructor
@SuperBuilder
public class ResourcesConfigDTO implements Serializable {
private String environment;
private String type;
private Component component;
private Autoscaler autoscaler;
}
Actually i use this code for merging 2 objects between them :
public static <T> T mergeObjects(T first, T second) {
Class<?> clas = first.getClass();
Field[] fields = clas.getDeclaredFields();
Object result = null;
try {
result = clas.getDeclaredConstructor().newInstance();
for (Field field : fields) {
field.setAccessible(true);
Object value1 = field.get(first);
Object value2 = field.get(second);
System.out.println("value1 " + value1 + " value2: " + value2);
Object value = (value1 != null) ? value1 : value2;
field.set(result, value);
}
} catch (Exception e) {
e.printStackTrace();
}
return (T) result;
}
But it only works with objects that only have one level, it does not work for multi level objects. I don't understand how i can fix this
Update 1 : The mergeObjects is called, the first object environment value is "d" but the objects 2 value is "null".
After the isNestedObject, it calls again mergeObjects, with this "d" and "null" value, but it fails at Object value2 = field.get(second);
with NPE
:
public static <T> T mergeObjects(T first, T second) {
Class<?> clas = first.getClass();
Field[] fields = clas.getDeclaredFields();
Object result = null;
try {
result = clas.getDeclaredConstructor().newInstance();
for (Field field : fields) {
field.setAccessible(true);
Object value1 = field.get(first);
Object value2 = field.get(second);
if (!(isNestedObject(value1) && isNestedObject(value2))) {
// call your method recursively..
Object mergedValue = mergeObjects(value1, value2);
field.set(result, mergedValue);
} else {
// do what you were doing
System.out.println("value1 " + value1 + " value2: " + value2);
Object value = (value1 != null) ? value1 : value2;
field.set(result, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return (T) result;
}
private static boolean isNestedObject(Object value) {
if (value instanceof String ||
value instanceof Integer ||
value instanceof Double ||
value instanceof Float ||
value instanceof Boolean ||
value instanceof Component ||
value instanceof Routes ||
value instanceof Replicas ||
value instanceof DefaultRouteParameters ||
value instanceof DefaultRoute ||
value instanceof Cpu ||
value instanceof ComponentParameters ||
value instanceof Component ||
value instanceof Autoscaler
) {
return true;
}
return false;
}
Upvotes: 1
Views: 915
Reputation: 7394
You need to check if your field is not a primitive field or wrapper class than you need to do the same logic recursively .
Inside your for loop, once you fetch value1, you need to check if its not a primitive field or wrapper class than call the same method recursively.
Example:
for (Field field : fields) {
field.setAccessible(true);
Object value1 = field.get(first);
Object value2 = field.get(second);
if(!(isNestedObject(value1) && isNestedObject(value2))) {
//call your method recursively..
Object mergedValue = mergeObjects(value1, value2);
field.set(result, mergedValue);
} else {
//do what you were doing
System.out.println("value1 " + value1 + " value2: " + value2);
Object value = (value1 != null) ? value1 : value2;
field.set(result, value);
}
}
boolean isNestedObject(Object value) {
if(value instanceOf String.class ||
value instanceOf Integer.class) ||
value instanceOf Double.class) ||
value instanceOf Float.class) ||
value instanceOf Boolean.class) ||
//....add all wrapper classes here
) {
return true;
}
return false;
}
Upvotes: 1