ObjectHandler implements MetadataPriorityDependenciesHandler<Object>, MetadataMergeHandler<Object> { @Override public void merge(final Object existing, final Object incoming, final ImportType importType, final Map<Object, Object> incomingToExisting) { if (existing == null) { visitor.visitFields(incoming, false, new ObjectVisitor.FieldVisitor() { @Override public void visit(String fieldName, Class<?> type, Class<?> definedIn, Object incomingField) { if (incomingField instanceof OpenmrsObject) { Object existing = incomingToExisting.get(incomingField); if (existing != null) { visitor.writeField(incoming, fieldName, existing, definedIn); } } else if (incomingField instanceof Collection) { @SuppressWarnings("unchecked") Collection<Object> collection = (Collection<Object>) incomingField; Iterator<Object> it = collection.iterator(); Collection<Object> replacements = new ArrayList<Object>(); while (it.hasNext()) { incomingField = it.next(); Object existing = incomingToExisting.get(incomingField); if (existing != null) { replacements.add(existing); it.remove(); } } collection.addAll(replacements); } } }); } else { if (importType.isPreferTheirs() || importType.isPreferMine() || importType.isOverwriteMine()) { Integer id = Handler.getId(existing); visitor.visitFields(incoming, false, new ObjectVisitor.FieldVisitor() { @Override public void visit(String fieldName, Class<?> type, Class<?> definedIn, Object incomingField) { if (Collection.class.isAssignableFrom(type)) { if (incomingField == null) { return; } Object existingField = visitor.readField(existing, fieldName, definedIn); if (existingField instanceof Collection) { @SuppressWarnings("unchecked") Collection<Object> existingCollection = (Collection<Object>) existingField; @SuppressWarnings("unchecked") Collection<Object> incomingCollection = (Collection<Object>) incomingField; if (importType.isOverwriteMine()) { List<Object> incomingDiffCollection = new LinkedList<Object>(incomingCollection); Iterator<Object> existingCollectionIt = existingCollection.iterator(); while(existingCollectionIt.hasNext()) { Object existingElement = existingCollectionIt.next(); boolean existingMissing = findAndRemoveMatchingElementByUuid(incomingDiffCollection, existingElement) == null; if (existingMissing) { if (existingElement instanceof ConceptName) { ((ConceptName) existingElement).setVoided(true); } else { existingCollectionIt.remove(); } } } for (Object incomingElement : incomingDiffCollection) { Object mappedToExisting = incomingToExisting.get(incomingElement); if (mappedToExisting != null) { existingCollection.add(mappedToExisting); } else { existingCollection.add(incomingElement); } } } else { for (Object incomingElement : incomingCollection) { Object existing = incomingToExisting.get(incomingElement); if (existing == null) { boolean incomingMissing = true; for (Object existingElement : existingCollection) { if (comparisonEngine.equal(incomingElement, existingElement, incomingToExisting)) { incomingMissing = false; break; } } if (incomingMissing) { existingCollection.add(incomingElement); } } } } } } else if (!importType.isPreferMine()) { if (incomingField instanceof OpenmrsObject) { Object existingField = incomingToExisting.get(incomingField); if (existingField != null) { visitor.writeField(existing, fieldName, existingField, definedIn); } else { visitor.writeField(existing, fieldName, incomingField, definedIn); } } else { if (!fieldName.equals("uuid") && !(incomingField instanceof User)) { visitor.writeField(existing, fieldName, incomingField, definedIn); } } } } private Object findAndRemoveMatchingElementByUuid(List<Object> incomingDiffCollection, Object existingElement) { Iterator<Object> incomingDiffCollectionIt = incomingDiffCollection.iterator(); while (incomingDiffCollectionIt.hasNext()) { Object incomingElement = incomingDiffCollectionIt.next(); if (incomingToExisting.get(incomingElement) != null) { incomingElement = incomingToExisting.get(incomingElement); } if (equalUuids(existingElement, incomingElement)) { incomingDiffCollectionIt.remove(); return incomingElement; } } return null; } private boolean equalUuids(Object a, Object b) { try { return ((OpenmrsObject) a).getUuid().equals(((OpenmrsObject) b).getUuid()); } catch (Exception ex) { return false; } } }); if (id != null) { Handler.setId(existing, id); } } } } ObjectHandler();  ObjectHandler(ObjectVisitor visitor, ComparisonEngine comparisonEngine); @Override int getPriority(); @Override List<Object> getPriorityDependencies(Object object); @Override void merge(final Object existing, final Object incoming, final ImportType importType, final Map<Object, Object> incomingToExisting);  }
@Test public void testMerge() throws Exception { PowerMockito.mockStatic(Handler.class, new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { return null; } }); Privilege p1 = buildPrivilege("Privilege 1", "A privilege"); Privilege p2 = buildPrivilege("Privilege 2", "A privilege"); Privilege p3 = buildPrivilege("Privilege 3", "A privilege"); Privilege p4 = buildPrivilege("Privilege 4", "A privilege"); Role existing = new Role(); existing.addPrivilege(p2); existing.addPrivilege(p3); Role incoming = new Role(); incoming.addPrivilege(p1); incoming.addPrivilege(p2); incoming.addPrivilege(p3); incoming.addPrivilege(p4); Map<Object, Object> incomingToExisting = new HashMap<Object, Object>(); incomingToExisting.put(p1, p1); incomingToExisting.put(p2, p2); incomingToExisting.put(p3, p3); incomingToExisting.put(p4, p4); ObjectHandler objectHandler = new ObjectHandler(new OpenmrsObjectVisitor(), new ComparisonEngine()); objectHandler.merge(existing, incoming, ImportType.OVERWRITE_MINE, incomingToExisting); assertThat(existing.getPrivileges().size(), is(4)); assertThat(existing.getPrivileges(), containsInAnyOrder(p1, p2, p3, p4)); }