ModificationsUtil { public static <T1, T2> Modifications<T2> convertModifications(Modifications<T1> src, Converter<T1, T2> converter) { ModificationsImpl<T2> result = new ModificationsImpl<T2>(); for (T1 t1 : src.getAddedItems()) { result.registerAddedItem(converter.convert(t1)); } for (T1 t1 : src.getUpdatedItems()) { result.registerUpdatedItem(converter.convert(t1), true); } Set<T2> removedItems = new HashSet<T2>(); for (T1 t1 : src.getRemovedItems()) { removedItems.add(converter.convert(t1)); } result.setRemovedItems(new ItemSetSelection<T2>(removedItems)); return result; } private  ModificationsUtil(); static Modifications<T2> convertModifications(Modifications<T1> src, Converter<T1, T2> converter); static Modifications<T> createModfications(Collection<T> added, Collection<T> updated,
      Collection<T> removed); static boolean isModified(Modifications<T> modifications, T item); static void registerAddedItems(ModificationsImpl<T> modifications, Iterable<T> items); static void registerUpdatedItems(ModificationsImpl<T> modifications, Iterable<T> items); static void registerRemovedItems(ModificationsImpl<T> modifications, Iterable<T> items); static Modifications<T> joinModifications(Collection<? extends Modifications<T>> modificationSet);  }
@Test public void testConvertModifications() { modifications.registerAddedItem("a"); modifications.registerUpdatedItem("b", true); modifications.setRemovedItems(new ItemSetSelection<String>("c")); Modifications<String> converted = ModificationsUtil.convertModifications(modifications, new ModificationsUtil.Converter<String, String>() { @Override public String convert(String src) { return src + "'"; } }); assertEquals("{added: 1, updated: 1, removed: 1}", converted.toString()); assertEquals("[a']", converted.getAddedItems().toString()); assertEquals("[b']", converted.getUpdatedItems().toString()); assertEquals("[c']", converted.getRemovedItems().toString()); }