Beans { public static <C> C combine(C origin, C override) { if (origin == null) { return override; } if (override == null) { return origin; } Class<C> originClass = (Class<C>) origin.getClass(); Class<C> overrideClass = (Class<C>) override.getClass(); if (String.class.isAssignableFrom(originClass)) { if (Strings.isNullOrEmpty((String) origin)) { return override; } if (Strings.isNullOrEmpty((String) override)) { return origin; } } if (!overrideClass.equals(originClass)) { throw new IllegalStateException( String.format("Objects types don't match. Found: [%s] and [%s].", overrideClass, originClass)); } if (overrideClass.isPrimitive() || overrideClass.isEnum()) { return override; } if (List.class.isAssignableFrom(originClass)) { return mergeList(origin, override); } if (Set.class.isAssignableFrom(originClass)) { return mergeSet(origin, override); } if (Map.class.isAssignableFrom(originClass)) { return mergeMap(origin, override); } if (originClass.isArray()) { return mergeArray(origin, override); } String fcqn = overrideClass.getCanonicalName(); if (fcqn.startsWith("java") || fcqn.startsWith("com.sun") || fcqn.startsWith("sun.")) { return override; } try { final C result = originClass.newInstance(); for (Field f : getAllFields(originClass)) { try { String name = f.getName(); f.setAccessible(true); Object value = combine(f.get(origin), f.get(override)); f.set(result, value); } catch (Exception e) { throw DekorateException.launderThrowable(e); } } return result; } catch (Exception e) { throw DekorateException.launderThrowable(e); } }  static C combine(C origin, C override);  }
@Test public void shouldCombineSimpleBeans() throws Exception { Person person1 = new Person("Jim", null, null); Person person2 = new Person(null, "Some place", null); Person combined = Beans.combine(person1, person2); assertNotNull(combined); assertEquals("Jim", combined.getName()); assertEquals("Some place", combined.getAddress()); }
@Test public void shouldCombineSynteticObjects() throws Exception { Person captain = new Person("Jim", null, null); Person member1 = new Person("Joe", null, null); Team team1 = new Team("A", captain, null); List<Person> members = new ArrayList<>(); members.add(member1); Team team2 = new Team("A", null, members); Team combined = Beans.combine(team1, team2); assertNotNull(combined); assertEquals("A", combined.getName()); assertEquals(captain, combined.getCaptain()); assertNotNull(combined.getMembers()); assertEquals(member1, combined.getMembers().get(0)); }
@Test public void shouldCombineList() throws Exception { Person member1 = new Person("Joe", null, null); Person member2 = new Person("John", null, null); Person member3a = new Person("Jordan", "Some Place", null); Person member3b = new Person("Jordan", null, "555-12345"); List<Person> team1Members = new ArrayList<>(); team1Members.add(member1); team1Members.add(member2); team1Members.add(member3a); List<Person> team2Members = new ArrayList<>(); team2Members.add(member3b); Team team1 = new Team("A", null, team1Members); Team team2 = new Team("A", null, team2Members); Team combined = Beans.combine(team1, team2); assertNotNull(combined); assertEquals("A", combined.getName()); assertNotNull(combined.getMembers()); assertEquals(3, combined.getMembers().size()); Person combinePerson = combined.getMembers().stream().filter(p -> "Jordan".equals(p.name)).findFirst().get(); assertNotNull(combinePerson); assertEquals("Some Place", combinePerson.getAddress()); assertEquals("555-12345", combinePerson.getPhone()); }
@Test public void shouldCombineMaps() throws Exception { Person member1 = new Person("Joe", null, null); Person member2 = new Person("John", null, null); Person member3a = new Person("Jordan", "Some Place", null); Person member3b = new Person("Jordan", null, "555-12345"); Map<String, Person> team1 = new HashMap<>(); team1.put("Joe", member1); team1.put("John", member2); team1.put("Jordan", member3a); Map<String, Person> team2 = new HashMap<>(); team2.put("Jordan", member3b); Map<String, Person> combined = Beans.combine(team1, team2); assertNotNull(combined); assertEquals(3, combined.size()); Person combinePerson = combined.get("Jordan"); assertNotNull(combinePerson); assertEquals("Some Place", combinePerson.getAddress()); assertEquals("555-12345", combinePerson.getPhone()); }