From b9886d22768b3d67c03c3ae1c5152be92fdf1c89 Mon Sep 17 00:00:00 2001 From: Steve Brokenshire Date: Wed, 23 Dec 2015 16:03:11 +0000 Subject: [PATCH] Added source code, headers and unit tests for the CATEGORIES vCard property for ContactDataObject. --- source/contacteditor/ContactDataObject.cpp | 314 ++++++++++++++++++++- source/contacteditor/ContactDataObject.h | 2 + source/tests/LoadCheck-Load4.vcf | 4 + source/tests/xestiaab_contactload.h | 200 +++++++++++++ 4 files changed, 514 insertions(+), 6 deletions(-) diff --git a/source/contacteditor/ContactDataObject.cpp b/source/contacteditor/ContactDataObject.cpp index 0770747..e6c82a1 100644 --- a/source/contacteditor/ContactDataObject.cpp +++ b/source/contacteditor/ContactDataObject.cpp @@ -96,6 +96,7 @@ ContactLoadStatus ContactDataObject::LoadFile(wxString Filename){ int RoleCount = 0; int OrganisationCount = 0; int NoteCount = 0; + int CategoryCount = 0; wxString ContactLine; wxString PropertyLine; wxString PropertySeg1; @@ -314,6 +315,13 @@ ContactLoadStatus ContactDataObject::LoadFile(wxString Filename){ ProcessNote(PropertySeg1, PropertySeg2, &NoteCount); NoteCount++; + } else if (Property == wxT("CATEGORIES")) { + + // See frmContactEditor-LoadCategory.cpp + + ProcessCategory(PropertySeg1, PropertySeg2, &CategoryCount); + CategoryCount++; + } } @@ -3587,7 +3595,6 @@ void ContactDataObject::ProcessNote(wxString PropertySeg1, wxString PropertySeg2 std::map *NoteListType = NULL; std::map *NoteListTokens = NULL; std::map *NoteListLanguage = NULL; - std::map *NoteListSortAs = NULL; std::map *NoteListPref = NULL; // Setup blank lines for later on. @@ -3666,11 +3673,6 @@ void ContactDataObject::ProcessNote(wxString PropertySeg1, wxString PropertySeg2 NoteListPID->erase(*NoteCount); NoteListPID->insert(std::make_pair(*NoteCount, PropertyValue)); - } else if (PropertyName == wxT("SORT-AS")){ - - NoteListSortAs->erase(*NoteCount); - NoteListSortAs->insert(std::make_pair(*NoteCount, PropertyValue)); - } else if (PropertyName == wxT("PREF")){ int PriorityNumber = 0; @@ -3734,6 +3736,306 @@ void ContactDataObject::ProcessNote(wxString PropertySeg1, wxString PropertySeg2 } +void ContactDataObject::ProcessCategory(wxString PropertySeg1, wxString PropertySeg2, int *CategoryCount){ + + std::map SplitPoints; + std::map SplitLength; + std::map::iterator SLiter; + wxString PropertyData; + wxString PropertyName; + wxString PropertyValue; + wxString PropertyTokens; + bool FirstToken = TRUE; + int intPrevValue = 12; + int intPref = 0; + int intType = 0; + long ListCtrlIndex; + + SplitValues(&PropertySeg1, &SplitPoints, &SplitLength, intPrevValue); + + intPrevValue = 11; + + PropertyType PropType = PROPERTY_NONE; + + // Look for type before continuing. + + CheckType(&PropertySeg1, &SplitPoints, &SplitLength, &intPrevValue, &PropType); + + // Setup blank lines for later on. + + switch(PropType){ + case PROPERTY_NONE: + break; + case PROPERTY_HOME: + CategoriesListType.insert(std::make_pair(*CategoryCount, "home")); + break; + case PROPERTY_WORK: + CategoriesListType.insert(std::make_pair(*CategoryCount, "work")); + break; + } + + intPrevValue = 11; + + for (std::map::iterator intiter = SplitPoints.begin(); + intiter != SplitPoints.end(); ++intiter){ + + SLiter = SplitLength.find(intiter->first); + + PropertyData = PropertySeg1.Mid(intPrevValue, (SLiter->second)); + + wxStringTokenizer PropertyElement (PropertyData, wxT("=")); + PropertyName = PropertyElement.GetNextToken(); + PropertyValue = PropertyElement.GetNextToken(); + + intPrevValue = intiter->second; + + // Process properties. + + size_t intPropertyValueLen = PropertyValue.Len(); + + if (PropertyValue.Mid((intPropertyValueLen - 1), 1) == wxT("\"")){ + + PropertyValue.Trim(); + PropertyValue.RemoveLast(); + + } + + if (PropertyValue.Mid(0, 1) == wxT("\"")){ + + PropertyValue.Remove(0, 1); + + } + + CaptureString(&PropertyValue, FALSE); + + if (PropertyName == wxT("ALTID")){ + + CategoriesListAltID.erase(*CategoryCount); + CategoriesListAltID.insert(std::make_pair(*CategoryCount, PropertyValue)); + + } else if (PropertyName == wxT("PID")){ + + CategoriesListPID.erase(*CategoryCount); + CategoriesListPID.insert(std::make_pair(*CategoryCount, PropertyValue)); + + } else if (PropertyName == wxT("PREF")){ + + int PriorityNumber = 0; + bool ValidNumber = TRUE; + + try{ + PriorityNumber = std::stoi(PropertyValue.ToStdString()); + } + + catch(std::invalid_argument &e){ + ValidNumber = FALSE; + } + + if (ValidNumber == TRUE){ + + CategoriesListPref.erase(*CategoryCount); + CategoriesListPref.insert(std::make_pair(*CategoryCount, PriorityNumber)); + + } + + } else if (PropertyName == wxT("LANGUAGE")){ + + CategoriesListLanguage.erase(*CategoryCount); + CategoriesListLanguage.insert(std::make_pair(*CategoryCount, PropertyValue)); + + } else { + + // Something else we don't know about so append + // to the tokens variable. + + if (!PropertyName.IsEmpty() && !PropertyValue.IsEmpty() && PropertyName != wxT("TYPE")){ + + if (FirstToken == TRUE){ + + PropertyTokens.Append(PropertyName + wxT("=") + PropertyValue); + FirstToken = FALSE; + + } else { + + PropertyTokens.Append(wxT(";") + PropertyName + wxT("=") + PropertyValue); + + } + + } + + } + + } + + // Deal with multiple categories. + + int intOrigCatCount = *CategoryCount; + bool FirstCategoryProcessed = TRUE; + bool AfterFirstToken = FALSE; + int intSplitSize = 0; + int intSplitsFound = 0; + int intSplitSeek = 0; + int intPropertyLen = PropertySeg2.Len(); + + SplitPoints.clear(); + SplitLength.clear(); + intPrevValue = 0; + + for (int i = 0; i <= intPropertyLen; i++){ + + if (intSplitSize == 0 && PropertySeg2.Mid(i, 1) == wxT(" ")){ + + continue; + + } + + intSplitSize++; + + if (PropertySeg2.Mid(i, 1) == wxT(",") && PropertySeg2.Mid((i - 1), 1) != wxT("\\")){ + + if (AfterFirstToken == TRUE){ + + SplitPoints.insert(std::make_pair(intSplitsFound, (i - intSplitSize + 1))); + SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 2))); + + } else { + + SplitPoints.insert(std::make_pair(intSplitsFound, 0)); + SplitLength.insert(std::make_pair(intSplitsFound, (intSplitSize - 2))); + AfterFirstToken = TRUE; + + } + + intSplitsFound++; + intSplitSeek = i; + intSplitSize = 0; + + } + + } + + if (SplitPoints.size() > 0){ + + SplitPoints.insert(std::make_pair(intSplitsFound, (intSplitSeek + 1))); + SplitLength.insert(std::make_pair(intSplitsFound, intSplitSize)); + + } + + if (SplitPoints.size() == 0){ + + CategoriesList.insert(std::make_pair(*CategoryCount, PropertySeg2)); + + if (!PropertyTokens.IsEmpty()){ + + CategoriesListTokens.insert(std::make_pair(*CategoryCount, PropertyTokens)); + + } + + } + + for (std::map::iterator intiter = SplitPoints.begin(); + intiter != SplitPoints.end(); ++intiter){ + + SLiter = SplitLength.find(intiter->first); + + intPrevValue = intiter->second; + + PropertyData = PropertySeg2.Mid(intPrevValue, (SLiter->second + 1)); + + // Add the data to the General/Home/Work address variables. + + // Trim any whitespace from the start and end. + + PropertyData = PropertyData.Trim(FALSE); + PropertyData = PropertyData.Trim(TRUE); + + CaptureString(&PropertyData, FALSE); + + if (FirstCategoryProcessed == TRUE){ + + FirstCategoryProcessed = FALSE; + + CategoriesList.insert(std::make_pair(*CategoryCount, PropertyData)); + + if (!PropertyTokens.IsEmpty()){ + + CategoriesListTokens.insert(std::make_pair(*CategoryCount, PropertyTokens)); + + } + + continue; + + } else { + + (*CategoryCount)++; + + CategoriesList.insert(std::make_pair(*CategoryCount, PropertyData)); + + if (!PropertyTokens.IsEmpty()){ + + CategoriesListTokens.insert(std::make_pair(*CategoryCount, PropertyTokens)); + + } + + } + + // Copy the properties to each of the categories (if it exists). + + if (!PropertyTokens.IsEmpty()){ + + CategoriesListTokens.insert(std::make_pair(*CategoryCount, CategoriesListTokens.find(intOrigCatCount)->second)); + + } + + // Check if ALTID was used. + + if (CategoriesListAltID.find(intOrigCatCount) != CategoriesListAltID.end()){ + + CategoriesListAltID.insert(std::make_pair(*CategoryCount, CategoriesListAltID.find(intOrigCatCount)->second)); + + } + + // Check if PID was used. + + if (CategoriesListPID.find(intOrigCatCount) != CategoriesListPID.end()){ + + CategoriesListPID.insert(std::make_pair(*CategoryCount, CategoriesListPID.find(intOrigCatCount)->second)); + + } + + // Check if PREF was used. + + if (CategoriesListPref.find(intOrigCatCount) != CategoriesListPref.end()){ + + CategoriesListPref.insert(std::make_pair(*CategoryCount, CategoriesListPref.find(intOrigCatCount)->second)); + + } + + // Check if LANGUAGE was used. + + if (CategoriesListLanguage.find(intOrigCatCount) != CategoriesListLanguage.end()){ + + CategoriesListLanguage.insert(std::make_pair(*CategoryCount, CategoriesListLanguage.find(intOrigCatCount)->second)); + + } + + // Check if TYPE was used. + + switch(PropType){ + case PROPERTY_NONE: + break; + case PROPERTY_HOME: + CategoriesListType.insert(std::make_pair(*CategoryCount, "home")); + break; + case PROPERTY_WORK: + CategoriesListType.insert(std::make_pair(*CategoryCount, "work")); + break; + } + + } + +} + void SplitValues(wxString *PropertyLine, std::map *SplitPoints, std::map *SplitLength, diff --git a/source/contacteditor/ContactDataObject.h b/source/contacteditor/ContactDataObject.h index 1ea9eba..e18bf70 100644 --- a/source/contacteditor/ContactDataObject.h +++ b/source/contacteditor/ContactDataObject.h @@ -75,6 +75,7 @@ class ContactDataObject{ void ProcessRole(wxString PropertySeg1, wxString PropertySeg2, int *RoleCount); void ProcessOrganisation(wxString PropertySeg1, wxString PropertySeg2, int *OrganisationCount); void ProcessNote(wxString PropertySeg1, wxString PropertySeg2, int *NoteCount); + void ProcessCategory(wxString PropertySeg1, wxString PropertySeg2, int *CategoryCount); public: @@ -475,6 +476,7 @@ class ContactDataObject{ std::map CategoriesListPID; std::map CategoriesListType; std::map CategoriesListTokens; + std::map CategoriesListLanguage; std::map CategoriesListPref; /* Items on the Groups tab */ diff --git a/source/tests/LoadCheck-Load4.vcf b/source/tests/LoadCheck-Load4.vcf index e282dbc..4942c05 100644 --- a/source/tests/LoadCheck-Load4.vcf +++ b/source/tests/LoadCheck-Load4.vcf @@ -82,4 +82,8 @@ NOTE;TYPE=home;ALTID=80;PID=81;LANGUAGE=kw;PREF=82;MOO=MEEP:Note\n\n\n\nLine 5\nLine 6\nLine 7 NOTE;TYPE=work;ALTID=70;PID=71;LANGUAGE=fr;PREF=72;BOING=BOOP:Note\n\n\n\nLi ne 8\nLine 9\nLine 10 +CATEGORIES;ALTID=40;PID=41;LANGUAGE=en;PREF=42;CAT=TAC:Category One +CATEGORIES;TYPE=home;ALTID=44;PID=46;LANGUAGE=kw;PREF=48;TAC=CAT:Category Tw + o,Category Three +CATEGORIES:Category Four,Category Five,Category Six END:VCARD diff --git a/source/tests/xestiaab_contactload.h b/source/tests/xestiaab_contactload.h index 8f0f752..bc22008 100644 --- a/source/tests/xestiaab_contactload.h +++ b/source/tests/xestiaab_contactload.h @@ -2080,4 +2080,204 @@ TEST(ContactLoad, NoteTests){ } +TEST(ContactLoad, CategoryTests){ + + ContactDataObject TestFile; + + // Check that the vCard 4.0 file loads OK. + + ASSERT_EQ(CONTACTLOAD_OK, TestFile.LoadFile("LoadCheck-Load4.vcf")); + + std::map::iterator TestFileIter; + std::map::iterator TestFileIntIter; + + // Start with the first category. + + TestFileIter = TestFile.CategoriesList.find(0); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category One", TestFileIter->second); + + // Check the TYPE section. + + TestFileIter = TestFile.CategoriesListType.find(0); + ASSERT_EQ(TestFile.CategoriesListType.end(), TestFileIter); + + // Check the ALTID section. + + TestFileIter = TestFile.CategoriesListAltID.find(0); + ASSERT_NE(TestFile.CategoriesListAltID.end(), TestFileIter); + ASSERT_EQ("40", TestFileIter->second); + + // Check the PID section. + + TestFileIter = TestFile.CategoriesListPID.find(0); + ASSERT_NE(TestFile.CategoriesListPID.end(), TestFileIter); + ASSERT_EQ("41", TestFileIter->second); + + // Check the LANGUAGE section. + + TestFileIter = TestFile.CategoriesListLanguage.find(0); + ASSERT_NE(TestFile.CategoriesListLanguage.end(), TestFileIter); + ASSERT_EQ("en", TestFileIter->second); + + // Check the PREF section. + + TestFileIntIter = TestFile.CategoriesListPref.find(0); + ASSERT_NE(TestFile.CategoriesListPref.end(), TestFileIntIter); + ASSERT_EQ(42, TestFileIntIter->second); + + // Check the extra tokens. + + TestFileIter = TestFile.CategoriesListTokens.find(0); + ASSERT_NE(TestFile.CategoriesListTokens.end(), TestFileIter); + ASSERT_EQ("CAT=TAC", TestFileIter->second); + + // Start with the second & third category. + // (Category Two, Category Three). + + TestFileIter = TestFile.CategoriesList.find(1); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category Two", TestFileIter->second); + + TestFileIter = TestFile.CategoriesList.find(2); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category Three", TestFileIter->second); + + // Check the TYPE section. + + TestFileIter = TestFile.CategoriesListType.find(1); + ASSERT_NE(TestFile.CategoriesListType.end(), TestFileIter); + ASSERT_EQ("home", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListType.find(2); + ASSERT_NE(TestFile.CategoriesListType.end(), TestFileIter); + ASSERT_EQ("home", TestFileIter->second); + + // Check the ALTID section. + + TestFileIter = TestFile.CategoriesListAltID.find(1); + ASSERT_NE(TestFile.CategoriesListAltID.end(), TestFileIter); + ASSERT_EQ("44", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListAltID.find(2); + ASSERT_NE(TestFile.CategoriesListAltID.end(), TestFileIter); + ASSERT_EQ("44", TestFileIter->second); + + // Check the PID section. + + TestFileIter = TestFile.CategoriesListPID.find(1); + ASSERT_NE(TestFile.CategoriesListPID.end(), TestFileIter); + ASSERT_EQ("46", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListPID.find(2); + ASSERT_NE(TestFile.CategoriesListPID.end(), TestFileIter); + ASSERT_EQ("46", TestFileIter->second); + + // Check the LANGUAGE section. + + TestFileIter = TestFile.CategoriesListLanguage.find(1); + ASSERT_NE(TestFile.CategoriesListLanguage.end(), TestFileIter); + ASSERT_EQ("kw", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListLanguage.find(2); + ASSERT_NE(TestFile.CategoriesListLanguage.end(), TestFileIter); + ASSERT_EQ("kw", TestFileIter->second); + + // Check the PREF section. + + TestFileIntIter = TestFile.CategoriesListPref.find(1); + ASSERT_NE(TestFile.CategoriesListPref.end(), TestFileIntIter); + ASSERT_EQ(48, TestFileIntIter->second); + + TestFileIntIter = TestFile.CategoriesListPref.find(2); + ASSERT_NE(TestFile.CategoriesListPref.end(), TestFileIntIter); + ASSERT_EQ(48, TestFileIntIter->second); + + // Check the extra tokens. + + TestFileIter = TestFile.CategoriesListTokens.find(1); + ASSERT_NE(TestFile.CategoriesListTokens.end(), TestFileIter); + ASSERT_EQ("TAC=CAT", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListTokens.find(2); + ASSERT_NE(TestFile.CategoriesListTokens.end(), TestFileIter); + ASSERT_EQ("TAC=CAT", TestFileIter->second); + + // Start with the third, fourth & fifth category. + // (Category Three,Category Four,Category Five). + + TestFileIter = TestFile.CategoriesList.find(3); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category Four", TestFileIter->second.ToStdString()); + + TestFileIter = TestFile.CategoriesList.find(4); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category Five", TestFileIter->second.ToStdString()); + + TestFileIter = TestFile.CategoriesList.find(5); + ASSERT_NE(TestFile.CategoriesList.end(), TestFileIter); + ASSERT_EQ("Category Six", TestFileIter->second); + + // Check the TYPE section. + + /*TestFileIter = TestFile.CategoriesListType.find(1); + ASSERT_NE(TestFile.CategoriesListType.end(), TestFileIter); + ASSERT_EQ("home", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListType.find(2); + ASSERT_NE(TestFile.CategoriesListType.end(), TestFileIter); + ASSERT_EQ("home", TestFileIter->second); + + // Check the ALTID section. + + TestFileIter = TestFile.CategoriesListAltID.find(1); + ASSERT_NE(TestFile.CategoriesListAltID.end(), TestFileIter); + ASSERT_EQ("44", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListAltID.find(2); + ASSERT_NE(TestFile.CategoriesListAltID.end(), TestFileIter); + ASSERT_EQ("44", TestFileIter->second); + + // Check the PID section. + + TestFileIter = TestFile.CategoriesListPID.find(1); + ASSERT_NE(TestFile.CategoriesListPID.end(), TestFileIter); + ASSERT_EQ("46", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListPID.find(2); + ASSERT_NE(TestFile.CategoriesListPID.end(), TestFileIter); + ASSERT_EQ("46", TestFileIter->second); + + // Check the LANGUAGE section. + + TestFileIter = TestFile.CategoriesListLanguage.find(1); + ASSERT_NE(TestFile.CategoriesListLanguage.end(), TestFileIter); + ASSERT_EQ("kw", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListLanguage.find(2); + ASSERT_NE(TestFile.CategoriesListLanguage.end(), TestFileIter); + ASSERT_EQ("kw", TestFileIter->second); + + // Check the PREF section. + + TestFileIntIter = TestFile.CategoriesListPref.find(1); + ASSERT_NE(TestFile.CategoriesListPref.end(), TestFileIntIter); + ASSERT_EQ(48, TestFileIntIter->second); + + TestFileIntIter = TestFile.CategoriesListPref.find(2); + ASSERT_NE(TestFile.CategoriesListPref.end(), TestFileIntIter); + ASSERT_EQ(48, TestFileIntIter->second);*/ + + // Check the extra tokens. + + TestFileIter = TestFile.CategoriesListTokens.find(1); + ASSERT_NE(TestFile.CategoriesListTokens.end(), TestFileIter); + ASSERT_EQ("TAC=CAT", TestFileIter->second); + + TestFileIter = TestFile.CategoriesListTokens.find(2); + ASSERT_NE(TestFile.CategoriesListTokens.end(), TestFileIter); + ASSERT_EQ("TAC=CAT", TestFileIter->second); + +} + // TODO: Add tests for the Contact Loading process. \ No newline at end of file -- 2.39.2