private void MergeIndividualAddressBook(ABFindContactsPagedResultType forwardList) { lock (SyncObject) { #region Get Default AddressBook Information if (forwardList.Ab != null && forwardList.Ab.abId == WebServiceConstants.MessengerIndividualAddressBookId && WebServiceDateTimeConverter.ConvertToDateTime(GetAddressBookLastChange(forwardList.Ab.abId)) < WebServiceDateTimeConverter.ConvertToDateTime(forwardList.Ab.lastChange)) { Scenario scene = Scenario.None; if (IsContactTableEmpty()) scene = Scenario.Initial; else scene = Scenario.DeltaRequest; #region Get groups if (null != forwardList.Groups) { foreach (GroupType groupType in forwardList.Groups) { Guid key = new Guid(groupType.groupId); if (groupType.fDeleted) { Groups.Remove(key); ContactGroup contactGroup = NSMessageHandler.ContactGroups[groupType.groupId]; if (contactGroup != null) { NSMessageHandler.ContactGroups.RemoveGroup(contactGroup); NSMessageHandler.ContactService.OnContactGroupRemoved(new ContactGroupEventArgs(contactGroup)); } } else { Groups[key] = groupType; // Add a new group NSMessageHandler.ContactGroups.AddGroup( new ContactGroup(System.Web.HttpUtility.UrlDecode(groupType.groupInfo.name), groupType.groupId, NSMessageHandler, groupType.groupInfo.IsFavorite)); // Fire the event NSMessageHandler.ContactService.OnContactGroupAdded( new ContactGroupEventArgs(NSMessageHandler.ContactGroups[groupType.groupId])); } } } #endregion #region Process Contacts Dictionary<string, CircleInverseInfoType> newInverseInfos = new Dictionary<string, CircleInverseInfoType>(); Dictionary<string, CircleInverseInfoType> modifiedConnections = new Dictionary<string, CircleInverseInfoType>(); if (forwardList.CircleResult != null && forwardList.CircleResult.Circles != null) { foreach (CircleInverseInfoType info in forwardList.CircleResult.Circles) { string abId = info.Content.Handle.Id.ToLowerInvariant(); if (HasWLConnection(abId)) { if (!modifiedConnections.ContainsKey(abId)) { modifiedConnections[abId] = info; } } else { newInverseInfos[abId] = info; } } } if (null != forwardList.Contacts) { #region Update the messenger contacts. foreach (ContactType contactType in forwardList.Contacts) { if (null != contactType.contactInfo) { SetContactToAddressBookContactPage(forwardList.Ab.abId, contactType); /* * Circle update rules: * 1. If your own circle has any update (i.e. adding or deleting members), no hidden representative will be changed, only circle inverse info will be provided. * 2. If a remote owner removes you from his circle, the hidden representative of that circle will change its RelationshipState to 2, circle inverse info will not provided. * 3. If a remote owner re-adds you into a circle which you've left before, the hidden representative will be created, its relationshipState is 3, and the circle inverse info will be provided. * 4. If you are already in a circle, the circle's owner removed you, then add you back, the hidden representative's RelationshipState property in NetworkInfo will change from 2 to 3. * 5. If a remote contact has left your own circle, hidden representative will not change but circle inverse info will be provided. * 6. If you delete your own circle, the hidden representative's contactType will change, and circle reverse info will be provided. * 7. If you create a circle, the hidden representative will also create and circle inverse info will be provided. * 8. If a remote owner invites you to join a circle, the hidden representative will be created, its relationshipState is 1 and circle inverse info will be provided, Role = StatePendingOutbound. */ long CID = contactType.contactInfo.CID; if (HasContact(CID)) { //modifiedConnections[CID] = SelectCircleInverseInfo(SelectWLConnection(CID)); ContactType savedContact = SelecteContact(contactType.contactInfo.CID); //A deleted or modified circle; We are NOT in initial scene. if (savedContact.contactInfo.contactType == MessengerContactType.Circle) { if (savedContact.contactInfo.contactType != contactType.contactInfo.contactType) { //Owner deleted circles found. //The members in the circle which this contact represents are all livepending contacts. //Or, the circle this contact represents has no member. //ModifyCircles(contactType, forwardList.CircleResult); Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "A deleted circle found: contactType: " + contactType.contactInfo.contactType + "\r\n " + "CID: " + contactType.contactInfo.CID.ToString() + "\r\n " + "PassportName: " + contactType.contactInfo.passportName + "\r\n " + "DomainTag: " + GetHiddenRepresentativeDomainTag(contactType) + "\r\n " + "RelationshipState: " + GetCircleMemberRelationshipStateFromNetworkInfo(contactType.contactInfo.NetworkInfoList).ToString() + "\r\n"); } else { //We may remove by the circle owner, so a circle is deleted. //ModifyCircles(contactType, forwardList.CircleResult); Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "A modified circle found: contactType: " + contactType.contactInfo.contactType + "\r\n " + "CID: " + contactType.contactInfo.CID.ToString() + "\r\n " + "PassportName: " + contactType.contactInfo.passportName + "\r\n " + "DomainTag: " + GetHiddenRepresentativeDomainTag(contactType) + "\r\n " + "RelationshipState: " + GetCircleMemberRelationshipStateFromNetworkInfo(contactType.contactInfo.NetworkInfoList).ToString() + "\r\n"); } continue; } } else { if (contactType.contactInfo.contactType == MessengerContactType.Circle) { //We get the hidden representative of a new circle. Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "A circle contact found: contactType: " + contactType.contactInfo.contactType + "\r\n " + "CID: " + contactType.contactInfo.CID.ToString() + "\r\n " + "PassportName: " + contactType.contactInfo.passportName + "\r\n " + "DomainTag: " + GetHiddenRepresentativeDomainTag(contactType) + "\r\n " + "RelationshipState: " + GetCircleMemberRelationshipStateFromNetworkInfo(contactType.contactInfo.NetworkInfoList).ToString() + "\r\n"); continue; } } Contact contact = NSMessageHandler.ContactList.GetContactByGuid(new Guid(contactType.contactId)); if (contactType.fDeleted) { //The contact was deleted. RemoveContactFromAddressBook(forwardList.Ab.abId, new Guid(contactType.contactId)); if (contact != null) { contact.RemoveFromList(RoleLists.Forward); NSMessageHandler.ContactService.OnContactRemoved(new ListMutateEventArgs(contact, RoleLists.Forward)); contact.Guid = Guid.Empty; contact.SetIsMessengerUser(false); PresenceStatus oldStatus = contact.Status; PresenceStatus newStatus = PresenceStatus.Offline; contact.SetStatus(newStatus); //Force the contact offline. NSMessageHandler.OnContactStatusChanged(new ContactStatusChangedEventArgs(contact, oldStatus, newStatus)); NSMessageHandler.OnContactOffline(new ContactStatusChangedEventArgs(contact, oldStatus, newStatus)); if (RoleLists.None == contact.Lists) { NSMessageHandler.ContactList.Remove(contact.Account, contact.ClientType); contact.NSMessageHandler = null; } } } else { if (UpdateContact(contactType, out contact) != ReturnState.UpdateError && contact != null) { NSMessageHandler.ContactService.OnContactAdded(new ListMutateEventArgs(contact, RoleLists.Forward)); } } } } #endregion #region CreateContactsFromShellContact(); #endregion } if (forwardList.Ab != null) { // Update lastchange SetAddressBookInfo(forwardList.Ab.abId, forwardList.Ab); } SaveContactTable(forwardList.Contacts); if (forwardList.CircleResult != null) SaveCircleInverseInfo(forwardList.CircleResult.Circles); ProcessCircles(modifiedConnections, newInverseInfos, scene); } #endregion #endregion } }
public XMLContactList Merge(ABFindContactsPagedResultType forwardList) { Initialize(); if (forwardList != null && forwardList.Ab != null) { if (WebServiceConstants.MessengerIndividualAddressBookId == forwardList.Ab.abId.ToLowerInvariant()) { MergeIndividualAddressBook(forwardList); } else { MergeGroupAddressBook(forwardList); } } return this; }
/// <summary> /// Update members for circles. /// </summary> /// <param name="forwardList"></param> private void MergeGroupAddressBook(ABFindContactsPagedResultType forwardList) { lock (SyncObject) { #region Get Individual AddressBook Information (Circle information) if (forwardList.Ab != null && forwardList.Ab.abId != WebServiceConstants.MessengerIndividualAddressBookId && forwardList.Ab.abInfo.AddressBookType == AddressBookType.Group && WebServiceDateTimeConverter.ConvertToDateTime(GetAddressBookLastChange(forwardList.Ab.abId)) < WebServiceDateTimeConverter.ConvertToDateTime(forwardList.Ab.lastChange)) { SetAddressBookInfo(forwardList.Ab.abId, forwardList.Ab); SaveAddressBookContactPage(forwardList.Ab.abId, forwardList.Contacts); //Create or update circle. Contact targetCircle = UpdateCircleFromAddressBook(forwardList.Ab.abId); if (targetCircle != null) { //Update circle mebers. UpdateCircleMembersFromAddressBookContactPage(targetCircle, Scenario.Initial); switch (targetCircle.CircleRole) { case RoleId.Admin: case RoleId.AssistantAdmin: case RoleId.Member: AddCircleToCircleList(targetCircle); break; case RoleId.StatePendingOutbound: FireJoinCircleInvitationReceivedEvents(targetCircle); break; } if (IsPendingCreateConfirmCircle(targetCircle.AddressBookId)) { FireCreateCircleCompletedEvent(targetCircle); } #region Print Info Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "Getting non-default addressbook: \r\nId: " + forwardList.Ab.abId + "\r\nName: " + forwardList.Ab.abInfo.name + "\r\nType: " + forwardList.Ab.abInfo.AddressBookType + "\r\nMembers:"); foreach (ContactType contact in forwardList.Contacts) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "PassportName: " + contact.contactInfo.passportName + ", DisplayName: " + contact.contactInfo.displayName + ", Type: " + contact.contactInfo.contactType); } Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "\r\n"); #endregion SaveContactTable(forwardList.Contacts); if (requestCircleCount > 0) { //Only the individual addressbook merge which contains new circles will cause this action. requestCircleCount--; if (requestCircleCount == 0) { Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "************This is the initial circle ADL, should be sent after the initial contact ADL **********" ); Save(); NSMessageHandler.SendInitialADL(Scenario.SendInitialCirclesADL); } } } else { RemoveCircleInverseInfo(forwardList.Ab.abId); RemoveAddressBookContatPage(forwardList.Ab.abId); RemoveAddressBookInfo(forwardList.Ab.abId); //Error? Save! Save(); Trace.WriteLineIf(Settings.TraceSwitch.TraceVerbose, "An error occured while merging the GroupAddressBook, addressbook info removed: " + forwardList.Ab.abId); } } #endregion } }