TagGroupsMutation implements JsonSerializable { @NonNull @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) public static List<TagGroupsMutation> collapseMutations(@Nullable List<TagGroupsMutation> mutations) { if (mutations == null || mutations.isEmpty()) { return Collections.emptyList(); } HashMap<String, Set<String>> addTags = new HashMap<>(); HashMap<String, Set<String>> removeTags = new HashMap<>(); HashMap<String, Set<String>> setTags = new HashMap<>(); for (TagGroupsMutation mutation : mutations) { if (mutation.addTags != null) { for (Map.Entry<String, Set<String>> entry : mutation.addTags.entrySet()) { Set<String> tags = entry.getValue(); String group = entry.getKey().trim(); if (group.isEmpty() || tags == null || tags.isEmpty()) { continue; } Set<String> existingSetTags = setTags.get(group); if (existingSetTags != null) { existingSetTags.addAll(tags); continue; } Set<String> existingRemoveTags = removeTags.get(group); if (existingRemoveTags != null) { existingRemoveTags.removeAll(tags); if (existingRemoveTags.isEmpty()) { removeTags.remove(group); } } Set<String> existingAddTags = addTags.get(group); if (existingAddTags == null) { existingAddTags = new HashSet<>(); addTags.put(group, existingAddTags); } existingAddTags.addAll(tags); } } if (mutation.removeTags != null) { for (Map.Entry<String, Set<String>> entry : mutation.removeTags.entrySet()) { Set<String> tags = entry.getValue(); String group = entry.getKey().trim(); if (group.isEmpty() || tags == null || tags.isEmpty()) { continue; } Set<String> existingSetTags = setTags.get(group); if (existingSetTags != null) { existingSetTags.removeAll(tags); continue; } Set<String> existingAddTags = addTags.get(group); if (existingAddTags != null) { existingAddTags.removeAll(tags); if (existingAddTags.isEmpty()) { addTags.remove(group); } } Set<String> existingRemoveTags = removeTags.get(group); if (existingRemoveTags == null) { existingRemoveTags = new HashSet<>(); removeTags.put(group, existingRemoveTags); } existingRemoveTags.addAll(tags); } } if (mutation.setTags != null) { for (Map.Entry<String, Set<String>> entry : mutation.setTags.entrySet()) { Set<String> tags = entry.getValue(); String group = entry.getKey().trim(); if (group.isEmpty()) { continue; } setTags.put(group, tags == null ? new HashSet<String>() : new HashSet<>(tags)); removeTags.remove(group); addTags.remove(group); } } } List<TagGroupsMutation> collapsedMutations = new ArrayList<>(); if (!setTags.isEmpty()) { TagGroupsMutation mutation = new TagGroupsMutation(null, null, setTags); collapsedMutations.add(mutation); } if (!addTags.isEmpty() || !removeTags.isEmpty()) { TagGroupsMutation mutation = new TagGroupsMutation(addTags, removeTags, null); collapsedMutations.add(mutation); } return collapsedMutations; } private  TagGroupsMutation(@Nullable Map<String, Set<String>> addTags, @Nullable Map<String, Set<String>> removeTags, @Nullable Map<String, Set<String>> setTags); @NonNull static TagGroupsMutation newAddTagsMutation(@NonNull String group, @NonNull Set<String> tags); @NonNull static TagGroupsMutation newRemoveTagsMutation(@NonNull String group, @NonNull Set<String> tags); @NonNull static TagGroupsMutation newSetTagsMutation(@NonNull String group, @NonNull Set<String> tags); @NonNull @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) static List<TagGroupsMutation> collapseMutations(@Nullable List<TagGroupsMutation> mutations); @NonNull @Override JsonValue toJsonValue(); @NonNull static TagGroupsMutation fromJsonValue(@NonNull JsonValue jsonValue); @NonNull static List<TagGroupsMutation> fromJsonList(@NonNull JsonList jsonList); @Override boolean equals(Object o); @Override int hashCode(); void apply(@NonNull Map<String, Set<String>> tagGroups);  }
@Test public void testCollapseEmptyMutations() throws JsonException { List<TagGroupsMutation> mutations = new ArrayList<>(); List<TagGroupsMutation> collapsed = TagGroupsMutation.collapseMutations(mutations); assertEquals(0, collapsed.size()); }