/// <summary> /// Adds a new AD serach result entry to a list of StdElement /// </summary> /// <param name="result"> /// The result list that should get this entry. /// </param> /// <param name="searchItem"> /// The search result item. /// </param> private void AddContactFromSearchResult(ICollection <StdElement> result, SearchResult searchItem) { var newContact = ConvertToContact(searchItem.Properties); if (string.IsNullOrEmpty(newContact.ToStringSimple())) { return; } var existing = from x in result where x.ExternalIdentifier.GetProfileId(ProfileIdentifierType.ActiveDirectoryId) == newContact.ExternalIdentifier.GetProfileId(ProfileIdentifierType.ActiveDirectoryId) select x; if (existing.Count() != 0) { return; } if (!string.IsNullOrEmpty(this.DumpPath)) { DumpUserInformation( searchItem, Path.Combine(this.DumpPath, SyncTools.NormalizeFileName(newContact.ToStringSimple()) + ".txt")); } this.LogProcessingEvent(newContact, "adding new element"); result.Add(newContact); }
public void CopyTestsvCardExternal() { var connector = new ContactClient(); var vcardConnector = new ContactClientVCards(true); var tempFolder = PrepareFolder(false); var file1 = Path.Combine(tempFolder, "file1"); var file2 = Path.Combine(tempFolder, "file2"); var path1 = Path.Combine(tempFolder, "vCards"); var originalList = connector.GetAll(file1); vcardConnector.WriteRange(originalList, path1); var copyList = vcardConnector.GetAll(path1); connector.WriteRange(copyList, file2); AssertOriginalAndCopyCompare(originalList, copyList, false); vcardConnector = new ContactClientVCards(true); vcardConnector.WriteRange(originalList, path1); Assert.IsTrue( File.Exists( Path.Combine( tempFolder, "vCards\\" + SyncTools.NormalizeFileName( originalList.GetElementById <StdContact>(ContactWithPicture).ToStringSimple())) + "-ContactPicture.jpg")); }
public void TestSyncToolsNormalizeFileName() { Assert.AreEqual(@"hello.txt", SyncTools.NormalizeFileName(@"hello.txt")); Assert.AreEqual(@"hello1.txt", SyncTools.NormalizeFileName(@"hello1.txt")); Assert.AreEqual(@"hello..txt", SyncTools.NormalizeFileName(@"hello..txt")); Assert.AreEqual(@"hello_.txt", SyncTools.NormalizeFileName(@"hello?.txt")); Assert.AreEqual(@"hello_.txt", SyncTools.NormalizeFileName(@"hello:.txt")); Assert.AreEqual(@"hello_.txt", SyncTools.NormalizeFileName(@"hello\.txt")); Assert.AreEqual(@"hello_.txt", SyncTools.NormalizeFileName(@"hello/.txt")); }
public void TestGenderByText() { Assert.AreEqual(Gender.Female, SyncTools.GenderByText("Mrs.")); Assert.AreEqual(Gender.Female, SyncTools.GenderByText("Frau")); Assert.AreEqual(Gender.Male, SyncTools.GenderByText("Mr.")); Assert.AreEqual(Gender.Male, SyncTools.GenderByText("Herr")); Assert.AreEqual(Gender.Unspecified, SyncTools.GenderByText("something")); Assert.AreEqual(Gender.Unspecified, SyncTools.GenderByText(null)); Assert.AreEqual(Gender.Unspecified, SyncTools.GenderByText(string.Empty)); }
/// <summary> /// Extract contact information from an Active Directory entry /// </summary> /// <param name="resultProperties"> </param> /// <returns> a standard contact entity </returns> private static StdContact ConvertToContact(PropertyCollection resultProperties) { var result = new StdContact { Id = Guid.NewGuid(), InternalSyncData = new SyncData { DateOfCreation = resultProperties.GetPropDate("whencreated"), DateOfLastChange = resultProperties.GetPropDate("whenchanged"), }, BusinessAddressPrimary = new AddressDetail { CountryName = resultProperties.GetPropString("co"), StateName = resultProperties.GetPropString("st"), PostalCode = resultProperties.GetPropString("postalcode"), CityName = resultProperties.GetPropString("l"), StreetName = resultProperties.GetPropString("streetaddress"), Phone = new PhoneNumber(resultProperties.GetPropString("telephonenumber")), Room = resultProperties.GetPropString("physicaldeliveryofficename", "roomnumber"), }, BusinessPhoneMobile = new PhoneNumber(resultProperties.GetPropString("mobile")), BusinessPosition = resultProperties.GetPropString("title"), BusinessCompanyName = resultProperties.GetPropString("company"), BusinessDepartment = resultProperties.GetPropString("department"), BusinessEmailPrimary = resultProperties.GetPropString("mail"), PersonalAddressPrimary = new AddressDetail { Phone = new PhoneNumber(resultProperties.GetPropString("homephone")), }, Name = new PersonName { FirstName = resultProperties.GetPropString("givenname"), LastName = resultProperties.GetPropString("sn"), }, PersonGender = SyncTools.GenderByText(resultProperties.GetPropString("personaltitle")), AdditionalTextData = resultProperties.GetPropString("info"), ImageEntries = new List <ImageEntry> { new ImageEntry { ImageData = resultProperties.GetPropBytes("thumbnailPhoto"), ImageName = "ActiveDirectory", } } }; result.ExternalIdentifier.SetProfileId(ProfileIdentifierType.ActiveDirectoryId, resultProperties.GetPropString("CN")); result.NormalizeContent(); return(result); }
/// <summary> /// Detects merge conflicts and resolves them using user interaction /// </summary> /// <param name="sourceClient"> /// The source client. /// </param> /// <param name="targetClient"> /// The target client. /// </param> /// <param name="baseliClient"> /// The baseline client. /// </param> /// <param name="sourceStorePath"> /// The source storage path. /// </param> /// <param name="targetStorePath"> /// The target storage path. /// </param> /// <param name="baselineStorePath"> /// The baseline storage path. /// </param> /// <param name="commandParameter"> /// The command parameter. /// </param> /// <returns> /// True if the response from the <see cref="SyncComponent.UiProvider"/> is "continue" /// </returns> public bool ExecuteCommand( IClientBase sourceClient, IClientBase targetClient, IClientBase baseliClient, string sourceStorePath, string targetStorePath, string baselineStorePath, string commandParameter) { if (targetClient == null) { throw new InvalidOperationException("item.targetClient is null"); } if (sourceClient == null) { throw new InvalidOperationException("item.sourceClient is null"); } if (sourceStorePath == null) { throw new InvalidOperationException("sourceStorePath is null"); } if (targetStorePath == null) { throw new InvalidOperationException("targetStorePath is null"); } var targetList = targetClient.GetAll(targetStorePath); var sourceList = sourceClient.GetAll(sourceStorePath); var type = targetList.Count > 0 ? targetList[0].GetType() : sourceList.Count > 0 ? sourceList[0].GetType() : typeof(StdElement); var mergeResultList = ((IUiSyncInteraction)this.UiProvider).PerformAttributeMerge( SyncTools.DetectConflicts( SyncTools.BuildConflictTestContainerList( sourceList, targetList, (baseliClient == null) ? null : baseliClient.GetAll(baselineStorePath), type), true), targetList); // only write to target if we did get a merge result if (mergeResultList != null) { targetClient.WriteRange(mergeResultList, targetStorePath); } return(true); }
/// <summary> /// normalizes the content of this entity in order to exclude leading/tailing spaces in strings etc. /// </summary> /// <exception cref="NotImplementedException"> /// </exception> public override void NormalizeContent() { if (!string.IsNullOrEmpty(this.Description)) { this.Description = this.Description.Trim(); } if (!string.IsNullOrEmpty(this.Title)) { this.Title = this.Title.Trim(); } SyncTools.ClearNulls(this, typeof(StdCalendarItem)); }
/// <summary> /// Write method for full list of elements. This will write the properties of the <see cref="StdElement"/> /// to the file specified by the parameter <paramref name="clientFolderName"/>. /// </summary> /// <param name="elements"> /// the list of elements that should be written to the target system. /// </param> /// <param name="clientFolderName"> /// The path and file name to where the elements should be written. /// </param> /// <param name="skipIfExisting"> /// this parameter is ignored in this client implementation /// </param> protected override void WriteFullList(List <StdElement> elements, string clientFolderName, bool skipIfExisting) { var columnDefinition = this.GetColumnDefinition(GetColumnDefinitionFileName(clientFolderName), typeof(T)); using (var file = new StreamWriter(GetFileName(clientFolderName), false, new UnicodeEncoding(false, true))) { foreach (var column in columnDefinition) { file.Write(column.Title + "\t"); } file.WriteLine(); foreach (T element in elements) { this.LogProcessingEvent(element, "writing element ..."); SyncTools.ClearNulls(element, typeof(T)); if (element == null) { this.LogProcessingEvent("NULL-element skipped"); continue; } var line = new StringBuilder(); foreach (var column in columnDefinition) { var valueString = Tools.GetPropertyValueString(element, column.Selector); // skipping "empty" dates if (valueString != "01.01.0001 00:00:00") { line.Append(valueString.Replace("\t", " ")); } line.Append("\t"); } file.WriteLine(line.ToString().Replace("\n", " ").Replace("\r", " ")); } this.LogProcessingEvent("write completed"); } }
/// <summary> /// Overrides the method to write the full list of data. /// </summary> /// <param name="elements"> /// The elements to be exported. /// </param> /// <param name="clientFolderName"> /// the full path that will get the contact files while exporting data. /// </param> /// <param name="skipIfExisting"> /// this value is not used in this client. /// </param> protected override void WriteFullList(List <StdElement> elements, string clientFolderName, bool skipIfExisting) { var useGuid = clientFolderName.Contains("{id}"); clientFolderName = clientFolderName.Replace("{id}", string.Empty); Tools.EnsurePathExist(clientFolderName); foreach (var element in elements) { var fileName = (useGuid ? element.Id.ToString("D") : SyncTools.NormalizeFileName(element.ToStringSimple())) + ".xmlcontact"; using (var file = new FileStream(Path.Combine(clientFolderName, fileName), FileMode.Create)) { ContactListFormatter.Serialize(file, element); } } }
/// <summary> /// Performs a cleanup of the elements of the list /// </summary> /// <param name="elements"> The elements. </param> protected static void CleanUpEntities(List <StdElement> elements) { var itemsToRemove = new List <StdElement>(); foreach (var element in elements) { SyncTools.ClearNulls(element, element.GetType()); var contact = element as StdContact; if (contact != null && contact.Name == null) { itemsToRemove.Add(element); } } foreach (var element in itemsToRemove) { elements.Remove(element); } }
/// <summary> /// Overrides the method to write the full list of data. /// </summary> /// <param name="elements"> /// The elements to be exported. /// </param> /// <param name="clientFolderName"> /// the name of the folder that will get the vCard files while exporting data. /// </param> /// <param name="skipIfExisting"> /// a value indicating whether existing entries should be added overwritten or skipped. /// </param> protected override void WriteFullList(List <StdElement> elements, string clientFolderName, bool skipIfExisting) { Tools.EnsurePathExist(clientFolderName); var use3Char = this.GetConfigValueBoolean("FileExtensionVCF"); foreach (var element in elements.ToStdContacts()) { if (element.Name == null) { continue; } var fileName = Path.Combine(clientFolderName, SyncTools.NormalizeFileName(element.ToStringSimple())); File.WriteAllBytes( fileName + (use3Char ? VCardFilenameExtension2 : VCardFilenameExtension), VCardConverter.StdContactToVCard(element)); if (this.savePictureExternal && !string.IsNullOrEmpty(element.PictureName)) { File.WriteAllBytes(fileName + "-" + element.PictureName, element.PictureData); } } }
/// <summary> /// Compares two contact instances and reports the difference. /// </summary> /// <param name="baselineContact"> /// The contact from the base line (how it has been read last time). /// </param> /// <param name="currentContact"> /// The contact currently read from the source. /// </param> private void CompareEntities(StdContact baselineContact, StdContact currentContact) { var changes = SyncTools.DetectConflicts( SyncTools.BuildConflictTestContainerList( new List <StdElement>(new[] { currentContact }), new List <StdElement>(new[] { baselineContact }), null, typeof(StdContact)), true); var changeSet = new ChangeInfo(); foreach (var change in changes) { changeSet.ChangedProperties.Add( change.PathToProperty + " " + change.PropertyConflict + ": " + change.SourceElement); } if (changeSet.ChangedProperties.Count <= 0) { return; } changeSet.DisplayName = string.Format( CultureInfo.InvariantCulture, "{0} has {1} properties changed.", baselineContact.Name, changeSet.ChangedProperties.Count); this.DetectedChanges.Add(changeSet); while (this.DetectedChanges.Count > this.MaxEntries) { this.DetectedChanges.RemoveAt(0); } }
private static bool ConvertToNativeContact(StdContact stdNewContact, ContactItem outlookContact) { var dirty = false; var stdOldContact = ConvertToStandardContact(outlookContact, null); var gender = stdNewContact.PersonGender == Gender.Unspecified ? OlGender.olUnspecified : ((stdNewContact.PersonGender == Gender.Male) ? OlGender.olMale : OlGender.olFemale); SyncTools.ClearNulls(stdNewContact, typeof(StdContact)); SyncTools.ClearNulls(stdOldContact, typeof(StdContact)); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.DateOfBirth, x => outlookContact.Birthday = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonGender, x => outlookContact.Gender = gender); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.Name.FirstName, x => outlookContact.FirstName = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.Name.MiddleName, x => outlookContact.MiddleName = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.Name.LastName, x => outlookContact.LastName = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.Name.AcademicTitle, x => outlookContact.Title = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessEmailPrimary, x => outlookContact.Email2Address = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalEmailPrimary, x => outlookContact.Email1Address = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessHomepage, x => outlookContact.BusinessHomePage = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalHomepage, x => outlookContact.PersonalHomePage = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessCompanyName, x => outlookContact.CompanyName = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessPosition, x => outlookContact.JobTitle = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.CityName, x => outlookContact.BusinessAddressCity = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.CountryName, x => outlookContact.BusinessAddressCountry = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.PostalCode, x => outlookContact.BusinessAddressPostalCode = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.StateName, x => outlookContact.BusinessAddressState = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.StreetName, x => outlookContact.BusinessAddressStreet = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessAddressPrimary.Phone.ToString(), x => outlookContact.BusinessTelephoneNumber = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.CityName, x => outlookContact.HomeAddressCity = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.CountryName, x => outlookContact.HomeAddressCountry = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.PostalCode, x => outlookContact.HomeAddressPostalCode = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.StateName, x => outlookContact.HomeAddressState = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.StreetName, x => outlookContact.HomeAddressStreet = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalAddressPrimary.Phone.ToString(), x => outlookContact.HomeTelephoneNumber = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalPhoneMobile.ToString(), x => outlookContact.MobileTelephoneNumber = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.BusinessPhoneMobile.ToString(), x => outlookContact.Business2TelephoneNumber = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.PersonalInstantMessengerAddresses.MsnMessenger, x => outlookContact.IMAddress = x); MappingHelper.MapIfDiffers( ref dirty, stdNewContact, stdOldContact, x => x.AdditionalTextData.Replace("\r\n", "\n"), x => outlookContact.Body = x); if (stdOldContact.Id != stdNewContact.Id) { outlookContact.UserProperties.Add(ContactIdOutlookPropertyName, OlUserPropertyType.olText, true, 1). Value = stdNewContact.Id.ToString(); dirty = true; } // import pictures if we have more data inside the new contact if (stdNewContact.PictureData != null && stdNewContact.PictureData.Length > stdOldContact.PictureData.Length) { var fullName = Path.GetTempFileName() + ".jpg"; File.WriteAllBytes(fullName, stdNewContact.PictureData); outlookContact.AddPicture(fullName); File.Delete(fullName); dirty = true; } if (stdNewContact.Categories != null && (stdOldContact.Categories == null || stdNewContact.Categories.Count != stdOldContact.Categories.Count)) { outlookContact.Categories = string.Join( ";", stdNewContact.Categories.MergeList(stdOldContact.Categories)); dirty = true; } return(dirty); }
/// <summary> /// Converts an outlook contact to a standard contact. /// </summary> /// <param name="outlookContact"> /// The outlook contact to be converted. /// </param> /// <param name="contactList"> /// The contact List to lookup duplicates. /// </param> /// <returns> /// a new standard contact /// </returns> /// <exception cref="ArgumentNullException"> /// if the outlook contact is null /// </exception> internal static StdContact ConvertToStandardContact( ContactItem outlookContact, IEnumerable <StdContact> contactList) { if (outlookContact == null) { throw new ArgumentNullException("outlookContact"); } // generate the new id this contact will get in case there is no contact id in outlook var newId = GetStandardContactId(outlookContact, contactList); // read the picture data and name of this contact string pictureName; var pictureData = SaveOutlookContactPicture(outlookContact, out pictureName); StdContact returnValue; try { // create a new contact and assign the corresponding values from the outlook contact returnValue = new StdContact { Id = newId, InternalSyncData = new SyncData { DateOfLastChange = outlookContact.LastModificationTime, DateOfCreation = outlookContact.CreationTime }, PersonGender = (outlookContact.Gender == OlGender.olMale) ? Gender.Male : (outlookContact.Gender == OlGender.olFemale) ? Gender.Female : SyncTools.GenderByText(outlookContact.Title), DateOfBirth = outlookContact.Birthday, Name = new PersonName { FirstName = outlookContact.FirstName, LastName = outlookContact.LastName, MiddleName = outlookContact.MiddleName, AcademicTitle = outlookContact.Title.IsOneOf("Herr", "Mr.", "Frau", "Mrs.") ? null : outlookContact.Title, }, PersonalAddressPrimary = new AddressDetail { Phone = (!string.IsNullOrEmpty(outlookContact.HomeTelephoneNumber)) ? new PhoneNumber(outlookContact.HomeTelephoneNumber) : null, CountryName = outlookContact.HomeAddressCountry, PostalCode = outlookContact.HomeAddressPostalCode, CityName = outlookContact.HomeAddressCity, StateName = outlookContact.HomeAddressState, StreetName = outlookContact.HomeAddressStreet, }, PersonalHomepage = outlookContact.PersonalHomePage, PersonalEmailPrimary = outlookContact.Email1Address, PersonalInstantMessengerAddresses = string.IsNullOrEmpty(outlookContact.IMAddress) ? null : new InstantMessengerAddresses(outlookContact.IMAddress), PersonalPhoneMobile = (!string.IsNullOrEmpty(outlookContact.MobileTelephoneNumber)) ? new PhoneNumber(outlookContact.MobileTelephoneNumber) : null, BusinessCompanyName = outlookContact.CompanyName, BusinessPosition = outlookContact.JobTitle, BusinessAddressPrimary = new AddressDetail { Phone = (!string.IsNullOrEmpty(outlookContact.BusinessTelephoneNumber)) ? new PhoneNumber(outlookContact.BusinessTelephoneNumber) : null, CountryName = outlookContact.BusinessAddressCountry, PostalCode = outlookContact.BusinessAddressPostalCode, CityName = outlookContact.BusinessAddressCity, StateName = outlookContact.BusinessAddressState, StreetName = outlookContact.BusinessAddressStreet, }, BusinessHomepage = outlookContact.BusinessHomePage, BusinessEmailPrimary = outlookContact.Email2Address, BusinessPhoneMobile = (!string.IsNullOrEmpty(outlookContact.Business2TelephoneNumber)) ? new PhoneNumber(outlookContact.Business2TelephoneNumber) : null, AdditionalTextData = outlookContact.Body, PictureName = pictureName, PictureData = pictureData }; } catch (COMException ex) { if (ex.ErrorCode == -2147467260) { return(null); } throw; } if (!string.IsNullOrEmpty(outlookContact.Categories)) { returnValue.Categories = MergeStrings(returnValue.Categories, outlookContact.Categories); } if (string.IsNullOrEmpty(returnValue.PersonalAddressPrimary.ToString())) { returnValue.PersonalAddressPrimary = null; } if (string.IsNullOrEmpty(returnValue.BusinessAddressPrimary.ToString())) { returnValue.PersonalAddressPrimary = null; } // return the newly generated standard contact return(returnValue); }
/// <summary> /// Converts a Oracle CRM on Demand <see cref="ContactData"/> to a <see cref="StdContact"/> /// </summary> /// <param name="contact"> The Oracle CRM on Demand contact. </param> /// <param name="addCustomAttributes"> a value specifying whether non-mapped properties should be added to the <see cref="StdContact.SourceSpecificAttributes"/>. </param> /// <returns> the converted data as a <see cref="StdContact"/> </returns> internal static StdContact ToStdContact(this ContactData contact, bool addCustomAttributes) { var result = new StdContact { InternalSyncData = new SyncData { DateOfCreation = contact.CreatedDate, DateOfLastChange = contact.ModifiedDate, }, AdditionalTextData = contact.Description, BusinessAddressPrimary = new AddressDetail { Phone = new PhoneNumber(contact.WorkPhone), CityName = contact.PrimaryCity, PostalCode = contact.PrimaryZipCode, CountryName = contact.PrimaryCountry, StreetName = contact.PrimaryAddress, StateName = contact.PrimaryProvince, }, PersonalAddressPrimary = new AddressDetail { Phone = new PhoneNumber(contact.HomePhone), CityName = contact.PrimaryCity, PostalCode = contact.PrimaryZipCode, CountryName = contact.PrimaryCountry, StreetName = contact.PrimaryAddress, StateName = contact.PrimaryProvince, }, BusinessEmailPrimary = contact.ContactEmail, BusinessPhoneMobile = new PhoneNumber(contact.CellularPhone), BusinessPosition = contact.JobTitle, BusinessDepartment = contact.Department, BusinessCompanyName = contact.AccountName, // todo: check the values here! "male" and "female" are just guesses PersonGender = contact.Gender == "male" ? Gender.Male : contact.Gender == "female" ? Gender.Female : Gender.Unspecified, // todo: check the values here! "married" and "other" are just guesses RelationshipStatus = contact.MaritalStatus == "married" ? RelationshipStatus.Married : RelationshipStatus.Undefined, DateOfBirth = contact.DateofBirth, Name = new PersonName { AcademicTitle = contact.MrMrs, FirstName = contact.ContactFirstName, MiddleName = contact.MiddleName, LastName = contact.ContactLastName, }, ExternalIdentifier = new ProfileIdentifierDictionary(ProfileIdentifierType.OracleCrmOnDemandId, contact.Id), }; // we may need to collect the "other" properties if (addCustomAttributes) { result.SourceSpecificAttributes = new SerializableDictionary <string, string>(); // create a string with the full qualified name of the SemSync connector var sourceConnectorName = typeof(ContactClient).FullName; // enumerate the properties of the contact that have no explicit mapping foreach (var x in Constants.PropertiesNotMapped) { // get this properties var value = Tools.GetPropertyValueString(contact, x).Trim(); // the custom properties do have a "connected" boolean telling us if the value is specified // (the better alternative would have been to use nullable types ... but it's oracles choice, // maybe nullables would have had more interoperability issues) if (x.StartsWith("Custom", StringComparison.OrdinalIgnoreCase) && !Tools.GetPropertyValueBoolean(contact, x + "Specified") && !string.IsNullOrEmpty(Tools.GetPropertyValueString(contact, x + "Specified"))) { // it's a custom attribute without being specified, so skip the rest continue; } // only add non-null and non-empty values if (!string.IsNullOrEmpty(value)) { result.SourceSpecificAttributes.Add(sourceConnectorName + "." + x, value); } } } // clean up the values (set all defaults to NULL) SyncTools.ClearNulls(result, typeof(StdContact)); var check = result.ToOracleContact(true); Tools.GetPropertyList(string.Empty, typeof(ContactData)).ForEach( x => { if (Tools.GetPropertyValueString(check, x).Trim().Replace("\n", string.Empty) != Tools.GetPropertyValueString(contact, x).Trim().Replace("\n", string.Empty)) { if (!x.EndsWith("Specified", StringComparison.OrdinalIgnoreCase) || Tools.GetPropertyValueBoolean(contact, x)) { Tools.DebugWriteLine("problem"); } } }); return(result); }
/// <summary> /// Normalizes the information inside the contact by performing data clean up. This includes processing of replacement lists and /// setting dates out of "normal" range to 1900.01.01. /// </summary> public override void NormalizeContent() { var dictionary = SyncTools.Replacements; if (dictionary != null) { if (dictionary.BusinessCompanyName != null) { foreach (var item in dictionary.BusinessCompanyName) { if (this.BusinessCompanyName == item.Key) { this.BusinessCompanyName = item.Value; } } } if (dictionary.BusinessHomepage != null) { foreach (var item in dictionary.BusinessHomepage) { if (this.BusinessHomepage == item.Key) { this.BusinessHomepage = item.Value; } } } if (dictionary.City != null) { foreach (var item in dictionary.City) { var value = item.Value; var key = item.Key; if (this.PersonalAddressPrimary != null && this.PersonalAddressPrimary.CityName == key) { this.PersonalAddressPrimary.CityName = value; } if (this.BusinessAddressPrimary != null && this.BusinessAddressPrimary.CityName == key) { this.BusinessAddressPrimary.CityName = value; } if (this.PersonalAddressSecondary != null && this.PersonalAddressSecondary.CityName == key) { this.PersonalAddressSecondary.CityName = value; } if (this.BusinessAddressSecondary != null && this.BusinessAddressSecondary.CityName == key) { this.BusinessAddressSecondary.CityName = value; } } } } if (!string.IsNullOrEmpty(this.BusinessCompanyName)) { this.BusinessCompanyName = this.BusinessCompanyName.Trim(); } if (this.BusinessAddressPrimary != null) { if (!string.IsNullOrEmpty(this.BusinessAddressPrimary.PostalCode)) { this.BusinessAddressPrimary.PostalCode = this.BusinessAddressPrimary.PostalCode.Trim(); } if (!string.IsNullOrEmpty(this.BusinessAddressPrimary.StreetName)) { this.BusinessAddressPrimary.StreetName = this.BusinessAddressPrimary.StreetName.Trim(); } if (!string.IsNullOrEmpty(this.BusinessAddressPrimary.CityName)) { this.BusinessAddressPrimary.CityName = this.BusinessAddressPrimary.CityName.Trim(); } } if (this.Categories != null) { var newCategories = new List <string>(this.Categories.Count); foreach (var category in this.Categories) { var newCategory = category.Trim(); if (!newCategories.Contains(newCategory)) { newCategories.Add(newCategory); } } this.Categories = newCategories; } if (this.DateOfBirth.Year < 1900 || this.DateOfBirth.Year > 2200) { this.DateOfBirth = new DateTime(1900, 1, 1); } if (this.Name != null) { this.Name.NormalizeContent(); } SyncTools.ClearNulls(this, typeof(StdContact)); }