UpdateOp { static UpdateOp combine(String id, Iterable<UpdateOp> ops) { Map<Key, Operation> changes = Maps.newHashMap(); Map<Key, Condition> conditions = Maps.newHashMap(); for (UpdateOp op : ops) { changes.putAll(op.getChanges()); if (op.conditions != null) { conditions.putAll(op.conditions); } } if (conditions.isEmpty()) { conditions = null; } return new UpdateOp(id, false, false, changes, conditions); } UpdateOp(@NotNull String id, boolean isNew);   UpdateOp(@NotNull String id,
             boolean isNew,
             boolean isDelete,
             @NotNull Map<Key, Operation> changes,
             @Nullable Map<Key, Condition> conditions); UpdateOp shallowCopy(String id); UpdateOp copy(); @NotNull String getId(); boolean isNew(); void setNew(boolean isNew); Map<Key, Operation> getChanges(); Map<Key, Condition> getConditions(); boolean hasChanges(); void remove(@NotNull String property); void removeMapEntry(@NotNull String property, @NotNull Revision revision); void set(String property, long value); void set(String property, boolean value); void set(String property, String value); void increment(@NotNull String property, long value); UpdateOp getReverseOperation(); @Override String toString();  }
@Test public void combine() { UpdateOp op1 = new UpdateOp("id", false); op1.set("p", "value"); UpdateOp op2 = new UpdateOp("id", false); Revision r = Revision.newRevision(1); op2.containsMapEntry("e", r, true); UpdateOp combined = UpdateOp.combine("id", newArrayList(op1, op2)); assertTrue(combined.hasChanges()); assertEquals(1, combined.getChanges().size()); assertEquals(1, combined.getConditions().size()); }