@Test public void avatar_change() { DecryptedGroup from = DecryptedGroup.newBuilder().setAvatar("A").build(); DecryptedGroup to = DecryptedGroup.newBuilder().setAvatar("B").build(); DecryptedGroupChange decryptedGroupChange = GroupChangeReconstruct.reconstructGroupChange(from, to); assertEquals(DecryptedGroupChange.newBuilder().setNewAvatar(DecryptedString.newBuilder().setValue("B")).build(), decryptedGroupChange); }
public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder() .setRevision(toState.getRevision()); if (!fromState.getTitle().equals(toState.getTitle())) { builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle())); } if (!fromState.getAvatar().equals(toState.getAvatar())) { builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar())); } if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) { builder.setNewTimer(toState.getDisappearingMessagesTimer()); } if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) { builder.setNewAttributeAccess(toState.getAccessControl().getAttributes()); } if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) { builder.setNewMemberAccess(toState.getAccessControl().getMembers()); } Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { builder.addDeleteMembers(member.getUuid()); } for (DecryptedMember member : addedMembers) { builder.addNewMembers(member); } for (DecryptedMember member : addedMembersByInvitation) { builder.addPromotePendingMembers(member); } for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .setUuid(uninvitedMember.getUuid()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { builder.addNewPendingMembers(invitedMember); } Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); if (oldState.getRole() != newState.getRole()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setUuid(newState.getUuid()) .setRole(newState.getRole())); } if (!oldState.getProfileKey().equals(newState.getProfileKey())) { builder.addModifiedProfileKeys(newState); } } if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) { builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); } for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { builder.addNewRequestingMembers(requestingMember); } for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { builder.addDeleteRequestingMembers(requestingMember.getUuid()); } for (DecryptedMember member : addedMembersByRequestApproval) { builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .setUuid(member.getUuid()) .setRole(member.getRole())); } if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } return builder.build(); }
GroupChangeReconstruct { public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder() .setRevision(toState.getRevision()); if (!fromState.getTitle().equals(toState.getTitle())) { builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle())); } if (!fromState.getAvatar().equals(toState.getAvatar())) { builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar())); } if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) { builder.setNewTimer(toState.getDisappearingMessagesTimer()); } if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) { builder.setNewAttributeAccess(toState.getAccessControl().getAttributes()); } if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) { builder.setNewMemberAccess(toState.getAccessControl().getMembers()); } Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { builder.addDeleteMembers(member.getUuid()); } for (DecryptedMember member : addedMembers) { builder.addNewMembers(member); } for (DecryptedMember member : addedMembersByInvitation) { builder.addPromotePendingMembers(member); } for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .setUuid(uninvitedMember.getUuid()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { builder.addNewPendingMembers(invitedMember); } Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); if (oldState.getRole() != newState.getRole()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setUuid(newState.getUuid()) .setRole(newState.getRole())); } if (!oldState.getProfileKey().equals(newState.getProfileKey())) { builder.addModifiedProfileKeys(newState); } } if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) { builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); } for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { builder.addNewRequestingMembers(requestingMember); } for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { builder.addDeleteRequestingMembers(requestingMember.getUuid()); } for (DecryptedMember member : addedMembersByRequestApproval) { builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .setUuid(member.getUuid()) .setRole(member.getRole())); } if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } return builder.build(); } }
GroupChangeReconstruct { public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder() .setRevision(toState.getRevision()); if (!fromState.getTitle().equals(toState.getTitle())) { builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle())); } if (!fromState.getAvatar().equals(toState.getAvatar())) { builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar())); } if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) { builder.setNewTimer(toState.getDisappearingMessagesTimer()); } if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) { builder.setNewAttributeAccess(toState.getAccessControl().getAttributes()); } if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) { builder.setNewMemberAccess(toState.getAccessControl().getMembers()); } Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { builder.addDeleteMembers(member.getUuid()); } for (DecryptedMember member : addedMembers) { builder.addNewMembers(member); } for (DecryptedMember member : addedMembersByInvitation) { builder.addPromotePendingMembers(member); } for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .setUuid(uninvitedMember.getUuid()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { builder.addNewPendingMembers(invitedMember); } Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); if (oldState.getRole() != newState.getRole()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setUuid(newState.getUuid()) .setRole(newState.getRole())); } if (!oldState.getProfileKey().equals(newState.getProfileKey())) { builder.addModifiedProfileKeys(newState); } } if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) { builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); } for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { builder.addNewRequestingMembers(requestingMember); } for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { builder.addDeleteRequestingMembers(requestingMember.getUuid()); } for (DecryptedMember member : addedMembersByRequestApproval) { builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .setUuid(member.getUuid()) .setRole(member.getRole())); } if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } return builder.build(); }  }
GroupChangeReconstruct { public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder() .setRevision(toState.getRevision()); if (!fromState.getTitle().equals(toState.getTitle())) { builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle())); } if (!fromState.getAvatar().equals(toState.getAvatar())) { builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar())); } if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) { builder.setNewTimer(toState.getDisappearingMessagesTimer()); } if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) { builder.setNewAttributeAccess(toState.getAccessControl().getAttributes()); } if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) { builder.setNewMemberAccess(toState.getAccessControl().getMembers()); } Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { builder.addDeleteMembers(member.getUuid()); } for (DecryptedMember member : addedMembers) { builder.addNewMembers(member); } for (DecryptedMember member : addedMembersByInvitation) { builder.addPromotePendingMembers(member); } for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .setUuid(uninvitedMember.getUuid()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { builder.addNewPendingMembers(invitedMember); } Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); if (oldState.getRole() != newState.getRole()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setUuid(newState.getUuid()) .setRole(newState.getRole())); } if (!oldState.getProfileKey().equals(newState.getProfileKey())) { builder.addModifiedProfileKeys(newState); } } if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) { builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); } for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { builder.addNewRequestingMembers(requestingMember); } for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { builder.addDeleteRequestingMembers(requestingMember.getUuid()); } for (DecryptedMember member : addedMembersByRequestApproval) { builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .setUuid(member.getUuid()) .setRole(member.getRole())); } if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } return builder.build(); }  static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState); }
GroupChangeReconstruct { public static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState) { DecryptedGroupChange.Builder builder = DecryptedGroupChange.newBuilder() .setRevision(toState.getRevision()); if (!fromState.getTitle().equals(toState.getTitle())) { builder.setNewTitle(DecryptedString.newBuilder().setValue(toState.getTitle())); } if (!fromState.getAvatar().equals(toState.getAvatar())) { builder.setNewAvatar(DecryptedString.newBuilder().setValue(toState.getAvatar())); } if (!fromState.getDisappearingMessagesTimer().equals(toState.getDisappearingMessagesTimer())) { builder.setNewTimer(toState.getDisappearingMessagesTimer()); } if (!fromState.getAccessControl().getAttributes().equals(toState.getAccessControl().getAttributes())) { builder.setNewAttributeAccess(toState.getAccessControl().getAttributes()); } if (!fromState.getAccessControl().getMembers().equals(toState.getAccessControl().getMembers())) { builder.setNewMemberAccess(toState.getAccessControl().getMembers()); } Set<ByteString> fromStateMemberUuids = membersToSetOfUuids(fromState.getMembersList()); Set<ByteString> toStateMemberUuids = membersToSetOfUuids(toState.getMembersList()); Set<ByteString> pendingMembersListA = pendingMembersToSetOfUuids(fromState.getPendingMembersList()); Set<ByteString> pendingMembersListB = pendingMembersToSetOfUuids(toState.getPendingMembersList()); Set<ByteString> requestingMembersListA = requestingMembersToSetOfUuids(fromState.getRequestingMembersList()); Set<ByteString> requestingMembersListB = requestingMembersToSetOfUuids(toState.getRequestingMembersList()); Set<ByteString> removedPendingMemberUuids = subtract(pendingMembersListA, pendingMembersListB); Set<ByteString> removedRequestingMemberUuids = subtract(requestingMembersListA, requestingMembersListB); Set<ByteString> newPendingMemberUuids = subtract(pendingMembersListB, pendingMembersListA); Set<ByteString> newRequestingMemberUuids = subtract(requestingMembersListB, requestingMembersListA); Set<ByteString> removedMemberUuids = subtract(fromStateMemberUuids, toStateMemberUuids); Set<ByteString> newMemberUuids = subtract(toStateMemberUuids, fromStateMemberUuids); Set<ByteString> addedByInvitationUuids = intersect(newMemberUuids, removedPendingMemberUuids); Set<ByteString> addedByRequestApprovalUuids = intersect(newMemberUuids, removedRequestingMemberUuids); Set<DecryptedMember> addedMembersByInvitation = intersectByUUID(toState.getMembersList(), addedByInvitationUuids); Set<DecryptedMember> addedMembersByRequestApproval = intersectByUUID(toState.getMembersList(), addedByRequestApprovalUuids); Set<DecryptedMember> addedMembers = intersectByUUID(toState.getMembersList(), subtract(newMemberUuids, addedByInvitationUuids, addedByRequestApprovalUuids)); Set<DecryptedPendingMember> uninvitedMembers = intersectPendingByUUID(fromState.getPendingMembersList(), subtract(removedPendingMemberUuids, addedByInvitationUuids)); Set<DecryptedRequestingMember> rejectedRequestMembers = intersectRequestingByUUID(fromState.getRequestingMembersList(), subtract(removedRequestingMemberUuids, addedByRequestApprovalUuids)); for (DecryptedMember member : intersectByUUID(fromState.getMembersList(), removedMemberUuids)) { builder.addDeleteMembers(member.getUuid()); } for (DecryptedMember member : addedMembers) { builder.addNewMembers(member); } for (DecryptedMember member : addedMembersByInvitation) { builder.addPromotePendingMembers(member); } for (DecryptedPendingMember uninvitedMember : uninvitedMembers) { builder.addDeletePendingMembers(DecryptedPendingMemberRemoval.newBuilder() .setUuid(uninvitedMember.getUuid()) .setUuidCipherText(uninvitedMember.getUuidCipherText())); } for (DecryptedPendingMember invitedMember : intersectPendingByUUID(toState.getPendingMembersList(), newPendingMemberUuids)) { builder.addNewPendingMembers(invitedMember); } Set<ByteString> consistentMemberUuids = intersect(fromStateMemberUuids, toStateMemberUuids); Set<DecryptedMember> changedMembers = intersectByUUID(subtract(toState.getMembersList(), fromState.getMembersList()), consistentMemberUuids); Map<ByteString, DecryptedMember> membersUuidMap = uuidMap(fromState.getMembersList()); for (DecryptedMember newState : changedMembers) { DecryptedMember oldState = membersUuidMap.get(newState.getUuid()); if (oldState.getRole() != newState.getRole()) { builder.addModifyMemberRoles(DecryptedModifyMemberRole.newBuilder() .setUuid(newState.getUuid()) .setRole(newState.getRole())); } if (!oldState.getProfileKey().equals(newState.getProfileKey())) { builder.addModifiedProfileKeys(newState); } } if (!fromState.getAccessControl().getAddFromInviteLink().equals(toState.getAccessControl().getAddFromInviteLink())) { builder.setNewInviteLinkAccess(toState.getAccessControl().getAddFromInviteLink()); } for (DecryptedRequestingMember requestingMember : intersectRequestingByUUID(toState.getRequestingMembersList(), newRequestingMemberUuids)) { builder.addNewRequestingMembers(requestingMember); } for (DecryptedRequestingMember requestingMember : rejectedRequestMembers) { builder.addDeleteRequestingMembers(requestingMember.getUuid()); } for (DecryptedMember member : addedMembersByRequestApproval) { builder.addPromoteRequestingMembers(DecryptedApproveMember.newBuilder() .setUuid(member.getUuid()) .setRole(member.getRole())); } if (!fromState.getInviteLinkPassword().equals(toState.getInviteLinkPassword())) { builder.setNewInviteLinkPassword(toState.getInviteLinkPassword()); } return builder.build(); }  static DecryptedGroupChange reconstructGroupChange(DecryptedGroup fromState, DecryptedGroup toState);  }