XTPCalendarMemoryDataProvider.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:26k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPCalendarMemoryDataProvider.cpp: implementation of the CXTPCalendarMemoryDataProvider class.
  2. //
  3. // This file is a part of the XTREME CALENDAR MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "XTPCalendarMemoryDataProvider.h"
  22. #include "XTPCalendarEvents.h"
  23. #include "XTPCalendarEvent.h"
  24. #include "XTPCalendarRecurrencePattern.h"
  25. #include "XTPCalendarNotifications.h"
  26. #include "XTPCalendarControl.h"
  27. #include "XTPCalendarResource.h"
  28. #include "Common/XTPPropExchange.h"
  29. #define _XML_FILE
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. #define XTP_MEM_DP_DATA_VER 1
  36. //===========================================================================
  37. //    Should be a prime number:
  38. // 37, 53, 67, 79, 101, 127, 199, 503, 1021, 1511, 2003, 3001
  39. //===========================================================================
  40. #define XTP_MEMDP_TMP_HASH_TABLE_SIZE 67
  41. //{{AFX_CODEJOCK_PRIVATE
  42. class CXTPCalendarEventHelper : public CXTPCalendarEvent
  43. {
  44. public:
  45. virtual CXTPCalendarRecurrencePattern* GetRPatternRef()
  46. {
  47. return CXTPCalendarEvent::GetRPatternRef();
  48. }
  49. };
  50. //}}AFX_CODEJOCK_PRIVATE
  51. /////////////////////////////////////////////////////////////////////////////
  52. // CXTPCalendarMemoryDataProvider implementation
  53. /////////////////////////////////////////////////////////////////////////////
  54. IMPLEMENT_DYNAMIC(CXTPCalendarMemoryDataProvider, CXTPCalendarData)
  55. //////////////////////////////////////////////////////////////////////
  56. CXTPCalendarMemoryDataProvider::CXTPCalendarMemoryDataProvider() :
  57. m_EventsStorage(XTP_EVENTS_STORAGE_HASH_TABLE_SIZE)
  58. {
  59. m_typeProvider = xtpCalendarDataProviderMemory;
  60. }
  61. CXTPCalendarMemoryDataProvider::~CXTPCalendarMemoryDataProvider()
  62. {
  63. }
  64. CString CXTPCalendarMemoryDataProvider::GetXMLEncoding()
  65. {
  66. CString strConnStr_lower = m_strConnectionString;
  67. strConnStr_lower.MakeLower();
  68. int nIndex = strConnStr_lower.Find(_T("encoding="));
  69. if (nIndex == -1)
  70. return _T("UTF-8");
  71. CString strEncoding = m_strConnectionString.Mid(nIndex + 9);
  72. nIndex = strEncoding.Find(_T(';'));
  73. if (nIndex != -1)
  74. strEncoding = strEncoding.Left(nIndex);
  75. return strEncoding;
  76. }
  77. BOOL CXTPCalendarMemoryDataProvider::IsProviderXML(BOOL bCheckXMLsupport, BOOL* pbXMLsupportError)
  78. {
  79. if (pbXMLsupportError)
  80. {
  81. *pbXMLsupportError = FALSE;
  82. }
  83. CString strConnStr_lower = m_strConnectionString;
  84. strConnStr_lower.MakeLower();
  85. if (strConnStr_lower.IsEmpty())
  86. return FALSE;
  87. if (strConnStr_lower.Find(_T("provider=xml")) == -1)
  88. return FALSE;
  89. if (bCheckXMLsupport)
  90. {
  91. CXTPDOMDocumentPtr xmlDocPtr;
  92. BOOL bCreated = SUCCEEDED(xmlDocPtr.CreateInstance(CLSID_XTPDOMDocument));
  93. if (pbXMLsupportError)
  94. {
  95. *pbXMLsupportError = !bCreated;
  96. }
  97. return bCreated;
  98. }
  99. return TRUE;
  100. }
  101. BOOL CXTPCalendarMemoryDataProvider::Open()
  102. {
  103. CString strFileName = GetDataSource();
  104. const int cnErrSize = 4096;
  105. TCHAR szError[cnErrSize+1];
  106. ZeroMemory(szError, sizeof(szError));
  107. CXTPCalendarData::Open();
  108. RemoveAllEvents();
  109. if (strFileName.IsEmpty())
  110. {
  111. return TRUE;
  112. }
  113. BOOL bResult = TRUE;
  114. try
  115. {
  116. BOOL bXMLsupportError = FALSE;
  117. if (!IsProviderXML(TRUE, &bXMLsupportError))
  118. {
  119. if (bXMLsupportError)
  120. {
  121. TRACE(_T("Warning: CXTPCalendarMemoryDataProvider::Open() cannot create XML parcer instance.n"));
  122. TRACE(_T("tperhaps AfxOleInit() has not been called, or msxml3.dll not found. n"));
  123. TRACE(_T("tThe binary data format is used. n."));
  124. }
  125. CFile fileData(strFileName, CFile::modeRead);
  126. if (fileData.GetLength() >= 8)
  127. {
  128. CArchive arData(&fileData, CArchive::load);
  129. CXTPPropExchangeArchive px(arData);
  130. bResult = _Load(&px);
  131. }
  132. }
  133. else
  134. {
  135. bResult = FALSE;
  136. #ifndef _XTP_EXCLUDE_XML
  137. CXTPPropExchangeXMLNode px(TRUE, 0, _T("Calendar"));
  138. px.SetEncoding(GetXMLEncoding());
  139. if (px.LoadFromFile(strFileName))
  140. {
  141. bResult = _Load(&px);
  142. }
  143. #else
  144. //bResult = FALSE;
  145. #endif
  146. }
  147. }
  148. catch(CFileException* pEfile)
  149. {
  150. if (pEfile->GetErrorMessage(szError, cnErrSize))
  151. {
  152. TRACE(_T("WARNING! MemoryDataProvider: Load Events data file error: %s n"), szError);
  153. }
  154. pEfile->Delete();
  155. bResult = FALSE;
  156. }
  157. catch(CArchiveException* pEarc)
  158. {
  159. if (pEarc->GetErrorMessage(szError, cnErrSize))
  160. {
  161. TRACE(_T("WARNING! MemoryDataProvider: Load Events data archive error: %s n"), szError);
  162. }
  163. //pEarc->ReportError();
  164. pEarc->Delete();
  165. bResult = FALSE;
  166. }
  167. catch(_com_error& e)
  168. {
  169. const TCHAR* pErrStr = e.ErrorMessage();
  170. if (pErrStr)
  171. {
  172. TRACE(_T("WARNING! MemoryDataProvider: Store Events data COM error: %s n"), pErrStr);
  173. }
  174. bResult = FALSE;
  175. }
  176. if (!bResult)
  177. {
  178. CXTPCalendarData::Close();
  179. }
  180. return bResult;
  181. }
  182. BOOL CXTPCalendarMemoryDataProvider::Create()
  183. {
  184. CXTPCalendarData::Create();
  185. return Save();
  186. }
  187. BOOL CXTPCalendarMemoryDataProvider::Save()
  188. {
  189. CString strFileName = GetDataSource();
  190. if (strFileName.IsEmpty())
  191. {
  192. return TRUE;
  193. }
  194. const int cnErrSize = 4096;
  195. TCHAR szError[cnErrSize+1];
  196. ZeroMemory(szError, sizeof(szError));
  197. try
  198. {
  199. BOOL bXMLsupportError = FALSE;
  200. if (!IsProviderXML(TRUE, &bXMLsupportError))
  201. {
  202. if (bXMLsupportError)
  203. {
  204. TRACE(_T("Warning: CXTPCalendarMemoryDataProvider::Save() cannot create XML parcer instance.n"));
  205. TRACE(_T("tperhaps AfxOleInit() has not been called, or msxml3.dll not found. n"));
  206. TRACE(_T("tThe binary data format is used. n."));
  207. }
  208. CFile fileData(strFileName, CFile::modeWrite | CFile::modeCreate);
  209. CArchive arData(&fileData, CArchive::store);
  210. CXTPPropExchangeArchive px(arData);
  211. _Save(&px);
  212. }
  213. else
  214. {
  215. #ifndef _XTP_EXCLUDE_XML
  216. CXTPPropExchangeXMLNode px(FALSE, 0, _T("Calendar"));
  217. px.SetEncoding(GetXMLEncoding());
  218. _Save(&px);
  219. px.SaveToFile(strFileName);
  220. #else
  221. return FALSE;
  222. #endif
  223. }
  224. }
  225. catch(CFileException* pEfile)
  226. {
  227. if (pEfile->GetErrorMessage(szError, cnErrSize))
  228. {
  229. TRACE(_T("WARNING! MemoryDataProvider: Store Events data file error: %s n"), szError);
  230. }
  231. pEfile->Delete();
  232. return FALSE;
  233. }
  234. catch(CArchiveException* pEarc)
  235. {
  236. if (pEarc->GetErrorMessage(szError, cnErrSize))
  237. {
  238. TRACE(_T("WARNING! MemoryDataProvider: Store Events data archive error: %s n"), szError);
  239. }
  240. pEarc->Delete();
  241. return FALSE;
  242. }
  243. catch(_com_error& e)
  244. {
  245. const TCHAR* pErrStr = e.ErrorMessage();
  246. if (pErrStr)
  247. {
  248. TRACE(_T("WARNING! MemoryDataProvider: Store Events data COM error: %s n"), pErrStr);
  249. }
  250. return FALSE;
  251. }
  252. return TRUE;
  253. }
  254. void CXTPCalendarMemoryDataProvider::Close()
  255. {
  256. if (!IsOpen())
  257. {
  258. CXTPCalendarData::Open();
  259. }
  260. RemoveAllEvents();
  261. CXTPCalendarData::Close();
  262. }
  263. CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoRetrieveDayEvents(COleDateTime dtDay)
  264. {
  265. CXTPCalendarEventsPtr ptrEvents = new CXTPCalendarEvents;
  266. if (!ptrEvents)
  267. {
  268. return NULL;
  269. }
  270. m_tree.SearchForEvents((DWORD)dtDay, (DWORD)dtDay, ptrEvents);
  271. _PostProcessOccurrencesFromMaster2(dtDay, dtDay, ptrEvents);
  272. // call this function here to increase performance (to avoid clone events which will be removed)
  273. _FilterDayEventsInstancesByEndTime(dtDay, ptrEvents);
  274. ptrEvents->CloneEvents();
  275. return ptrEvents;
  276. }
  277. CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::RetrieveEvents(COleDateTime dtStartDay, COleDateTime dtEndDay)
  278. {
  279. CXTPCalendarEventsPtr ptrEvents= new CXTPCalendarEvents;
  280. if (!ptrEvents)
  281. return NULL;
  282. m_tree.SearchForEvents((DWORD)dtStartDay, (DWORD)dtEndDay, ptrEvents);
  283. _PostProcessOccurrencesFromMaster2(dtStartDay, dtEndDay, ptrEvents);
  284. // to remove multiday events which end day is dtStartDay.
  285. _FilterDayEventsInstancesByEndTime(dtStartDay, ptrEvents);
  286. ptrEvents->CloneEvents();
  287. return ptrEvents;
  288. }
  289. CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoGetAllEvents_raw()
  290. {
  291. CXTPCalendarEventsPtr ptrArray = new CXTPCalendarEvents();
  292. if (!ptrArray)
  293. return NULL;
  294. POSITION pos = m_EventsStorage.GetStartPosition();
  295. while (pos)
  296. {
  297. DWORD dwID = 0;
  298. CXTPCalendarEvent* pEvent = m_EventsStorage.GetNextElement(pos, dwID);
  299. if (pEvent)
  300. {
  301. ptrArray->Add(pEvent, TRUE);
  302. }
  303. }
  304. ptrArray->CloneEvents();
  305. return ptrArray;
  306. }
  307. CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoGetUpcomingEvents(
  308. COleDateTime dtFrom, COleDateTimeSpan spPeriod)
  309. {
  310. UNREFERENCED_PARAMETER(dtFrom); UNREFERENCED_PARAMETER(spPeriod);
  311. return DoGetAllEvents_raw();
  312. }
  313. //////////////////////////////////////////////////////////////////////////
  314. //
  315. // Internal search algorithms and structures
  316. //
  317. //////////////////////////////////////////////////////////////////////////
  318. // DSTNode
  319. //////////////////////////////////////////////////////////////////////////
  320. CXTPCalendarMemoryDataProvider::DSTNode::DSTNode() :
  321. m_pMapEvents(NULL), pLeft(NULL), pRight(NULL)
  322. {}
  323. CXTPCalendarMemoryDataProvider::DSTNode::~DSTNode()
  324. {
  325. if (m_pMapEvents)
  326. delete m_pMapEvents;
  327. if (pLeft)
  328. delete pLeft;
  329. if (pRight)
  330. delete pRight;
  331. }
  332. void CXTPCalendarMemoryDataProvider::DSTNode::Mark(CXTPCalendarEvent* pEvent)
  333. {
  334. if (!m_pMapEvents)
  335. {
  336. m_pMapEvents = new EventsMap;
  337. if (!m_pMapEvents) {
  338. return;
  339. }
  340. }
  341. m_pMapEvents->SetAt(pEvent, TRUE);
  342. }
  343. void CXTPCalendarMemoryDataProvider::DSTNode::Unmark(CXTPCalendarEvent* pEvent)
  344. {
  345. if (m_pMapEvents)
  346. {
  347. m_pMapEvents->RemoveKey(pEvent);
  348. }
  349. }
  350. BOOL CXTPCalendarMemoryDataProvider::DSTNode::IsMarked(CXTPCalendarEvent* pEvent)
  351. {
  352. if (m_pMapEvents)
  353. {
  354. BOOL bValue;
  355. return m_pMapEvents->Lookup(pEvent, bValue);
  356. }
  357. return FALSE;
  358. }
  359. void CXTPCalendarMemoryDataProvider::DSTNode::AppendAll(CMapIDtoEvent* pMapEvents)
  360. {
  361. if (!pMapEvents || !m_pMapEvents)
  362. return;
  363. // enumerate all elements of the map
  364. POSITION pos = m_pMapEvents->GetStartPosition();
  365. BOOL bMark;
  366. CXTPCalendarEvent* pEvent = NULL;
  367. while (pos != NULL)
  368. {
  369. m_pMapEvents->GetNextAssoc(pos, pEvent, bMark);
  370. if (bMark && pEvent)
  371. {
  372. pMapEvents->SetAt(pEvent->GetEventID(),  pEvent);
  373. }
  374. }
  375. }
  376. //////////////////////////////////////////////////////////////////////////
  377. // DST
  378. //////////////////////////////////////////////////////////////////////////
  379. const int xtpBitsScan = sizeof(DWORD) * 8 - 1;
  380. CXTPCalendarMemoryDataProvider::DST::DST() :
  381. tmp_mapEvents(64)
  382. {
  383. pHead = new DSTNode();
  384. tmp_mapEvents.InitHashTable(XTP_MEMDP_TMP_HASH_TABLE_SIZE, FALSE);
  385. }
  386. CXTPCalendarMemoryDataProvider::DST::~DST()
  387. {
  388. if (pHead)
  389. delete pHead;
  390. }
  391. void CXTPCalendarMemoryDataProvider::DST::Insert(CXTPCalendarEvent* pEvent)
  392. {
  393. MarkRange(pEvent, dstScanMark);
  394. }
  395. void CXTPCalendarMemoryDataProvider::DST::Remove(CXTPCalendarEvent* pEvent)
  396. {
  397. MarkRange(pEvent, dstScanUnmark);
  398. }
  399. void CXTPCalendarMemoryDataProvider::DST::Clear()
  400. {
  401. if (pHead)
  402. delete pHead;
  403. pHead = new DSTNode();
  404. }
  405. void CXTPCalendarMemoryDataProvider::DST::MarkRange(CXTPCalendarEvent* pEvent, const DSTScanType eScanType)
  406. {
  407. DWORD dwStartDay = (DWORD)pEvent->GetStartTime();
  408. DWORD dwEndDay = (DWORD)pEvent->GetEndTime();
  409. ScanRange(pHead, xtpBitsScan - 1, 0, (DWORD)(1 << xtpBitsScan),
  410.   dwStartDay, dwEndDay,
  411.   pEvent, NULL, eScanType);
  412. }
  413. void CXTPCalendarMemoryDataProvider::DST::SearchForEvents(DWORD dwStart, DWORD dwEnd, CXTPCalendarEvents* pEvents)
  414. {
  415. if (!pEvents)
  416. return;
  417. tmp_mapEvents.RemoveAll();
  418. ScanRange(pHead, xtpBitsScan - 1, 0, (DWORD)(1 << xtpBitsScan),
  419.   dwStart, dwEnd,
  420.   NULL, &tmp_mapEvents, dstScanFind);
  421. // move events from temp map to array
  422. int nCount = (int)tmp_mapEvents.GetCount();
  423. if (nCount)
  424. {
  425. int nIndex = pEvents->GetCount();
  426. pEvents->SetSize(nIndex + nCount); // to avoid multi-reallocks
  427. DWORD dwKey;
  428. CXTPCalendarEvent* pEvent;
  429. POSITION pos = tmp_mapEvents.GetStartPosition();
  430. while(pos)
  431. {
  432. tmp_mapEvents.GetNextAssoc(pos, dwKey, pEvent);
  433. ASSERT(pEvent);
  434. if (pEvent)
  435. pEvents->SetAt(nIndex, pEvent, TRUE);
  436. nIndex++;
  437. }
  438. ASSERT(nIndex == pEvents->GetCount());
  439. tmp_mapEvents.RemoveAll();
  440. }
  441. }
  442. void CXTPCalendarMemoryDataProvider::DST::ScanRange(
  443. DSTNode* const pNode, const int nDepth,
  444. const DWORD dwMinValue, const DWORD dwMaxValue,
  445. const DWORD dwStart, const DWORD dwEnd,
  446. CXTPCalendarEvent* const pEvent, CMapIDtoEvent* pMapEvents,
  447. const DSTScanType eScanType)
  448. {
  449. DWORD dwMediumValue = dwMinValue | (nDepth >= 0 ? 1 << nDepth : 0);
  450. switch(eScanType)
  451. {
  452. case dstScanMark:
  453. case dstScanUnmark:
  454. // check if range contained in the min-max range
  455. if (dwStart <= dwMinValue && dwEnd >= dwMaxValue - 1)
  456. {
  457. switch(eScanType)
  458. {
  459. case dstScanMark:
  460. // Add this event to this entire range node.
  461. pNode->Mark(pEvent);
  462. return;
  463. case dstScanUnmark:
  464. // Delete this event from this entire range node.
  465. pNode->Unmark(pEvent);
  466. return;
  467. }
  468. }
  469. break;
  470. case dstScanFind:
  471. if (dwEnd >= dwMinValue && dwStart < dwMaxValue)
  472. {
  473. pNode->AppendAll(pMapEvents);
  474. }
  475. break;
  476. }
  477. // check for end recursion
  478. if (nDepth < 0)
  479. return;
  480. // run left search
  481. if (dwStart <= dwMediumValue)
  482. {
  483. if (!pNode->pLeft && eScanType == dstScanMark)
  484. pNode->pLeft = new DSTNode();
  485. if (pNode->pLeft)
  486. {
  487. ScanRange(pNode->pLeft, nDepth - 1,
  488.   dwMinValue, dwMediumValue,
  489.   dwStart, dwEnd,
  490.   pEvent, pMapEvents,
  491.   eScanType);
  492. }
  493. }
  494. // run right search
  495. if (dwEnd >= dwMediumValue)
  496. {
  497. if (!pNode->pRight && eScanType == dstScanMark)
  498. pNode->pRight = new DSTNode;
  499. if (pNode->pRight)
  500. {
  501. ScanRange(pNode->pRight, nDepth - 1,
  502.   dwMediumValue, dwMaxValue,
  503.   dwStart, dwEnd,
  504.   pEvent, pMapEvents,
  505.   eScanType);
  506. }
  507. }
  508. }
  509. ////////////////////////////////////////////////////////////////////////////
  510. void CXTPCalendarMemoryDataProvider::Serialize(CArchive& ar)
  511. {
  512. CXTPPropExchangeArchive px(ar);
  513. DoPropExchange(&px);
  514. }
  515. void CXTPCalendarMemoryDataProvider::DoPropExchange(CXTPPropExchange* pPX)
  516. {
  517. if (pPX->IsLoading())
  518. {
  519. VERIFY(_Load(pPX));
  520. }
  521. else
  522. {
  523. VERIFY(_Save(pPX));
  524. }
  525. }
  526. BOOL CXTPCalendarMemoryDataProvider::_Load(CXTPPropExchange* pPX)
  527. {
  528. //------------------------------------
  529. // - File data ver
  530. //
  531. // ..... - Events one by one
  532. //
  533. // a) MasterEvent
  534. // b) RecurrencePttern
  535. // c) DWORD - Exceptions count
  536. // d) ..... - RecurrencePttern_Exceptions one by one
  537. //
  538. // ..... - Events one by one
  539. //
  540. CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
  541. m_bDisableNotificationsSending = TRUE;
  542. long nSchema = 0;
  543. PX_Long(pPX, _T("Version"), (long&)nSchema);
  544. pPX->ExchangeLocale();
  545. if (nSchema != XTP_MEM_DP_DATA_VER)
  546. {
  547. //AfxMessageBox(_T("Unsupported data file version."));
  548. TRACE(_T("ERROR! MemoryDataProvider: Unsupported data file version. (%d) n"), nSchema);
  549. return FALSE;
  550. }
  551. CXTPPropExchangeSection secOptions(pPX->GetSection(_T("Options")));
  552. if (m_pCalendarOptions)
  553. {
  554. m_pCalendarOptions->DoPropExchange(&secOptions);
  555. }
  556. CXTPPropExchangeSection sec(pPX->GetSection(_T("Events")));
  557. CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
  558. POSITION pos = pEnumerator->GetPosition();
  559. DWORD dwMinEventID = (DWORD)-1;
  560. while (pos)
  561. {
  562. CXTPCalendarEventPtr ptrEvent = CreateNewEvent();
  563. if (!ptrEvent)
  564. {
  565. return FALSE;
  566. }
  567. CXTPPropExchangeSection secEvent(pEnumerator->GetNext(pos));
  568. ptrEvent->DoPropExchange(&secEvent);
  569. dwMinEventID = min(dwMinEventID, ptrEvent->GetEventID());
  570. int nRecState = ptrEvent->GetRecurrenceState();
  571. ASSERT(nRecState == xtpCalendarRecurrenceMaster || nRecState == xtpCalendarRecurrenceNotRecurring);
  572. if (nRecState == xtpCalendarRecurrenceMaster)
  573. {
  574. CXTPCalendarRecurrencePatternPtr ptrPattern = ptrEvent->GetRecurrencePattern();
  575. if (!ptrPattern || !ptrPattern)
  576. {
  577. ASSERT(FALSE);
  578. continue;
  579. }
  580. CXTPPropExchangeSection secPattern(secEvent->GetSection(_T("Pattern")));
  581. ptrPattern->DoPropExchange(&secPattern);
  582. DWORD dwPatternID = ptrPattern->GetPatternID();
  583. dwMinEventID = min(dwMinEventID, dwPatternID);
  584. CXTPPropExchangeEnumeratorPtr pEnumeratorExc(secPattern->GetEnumerator(_T("Exception")));
  585. POSITION posExc = pEnumeratorExc->GetPosition();
  586. while (posExc)
  587. {
  588. CXTPCalendarEventPtr ptrExcept = CreateNewEvent();
  589. if (!ptrExcept)
  590. {
  591. return TRUE;
  592. }
  593. CXTPPropExchangeSection secExceptEvent(pEnumeratorExc->GetNext(posExc));
  594. ptrExcept->DoPropExchange(&secExceptEvent);
  595. dwMinEventID = min(dwMinEventID, ptrExcept->GetEventID());
  596. nRecState = ptrExcept->GetRecurrenceState();
  597. ASSERT(nRecState == xtpCalendarRecurrenceException);
  598. ptrPattern->SetException(ptrExcept);
  599. }
  600. //=======================================================
  601. ptrEvent->UpdateRecurrence(ptrPattern);
  602. }
  603. VERIFY(AddEvent(ptrEvent));
  604. }
  605. //-----------------------------------------
  606. ms_dwNextFreeTempID = dwMinEventID;
  607. GetNextFreeTempID();
  608. //=========================================
  609. if (m_pSchedules)
  610. {
  611. CXTPPropExchangeSection secSchedules(pPX->GetSection(_T("EventsSchedules")));
  612. m_pSchedules->DoPropExchange(&secSchedules);
  613. }
  614. return TRUE;
  615. }
  616. BOOL CXTPCalendarMemoryDataProvider::_Save(CXTPPropExchange* pPX)
  617. {
  618. //------------------------------------
  619. // - File data ver
  620. //
  621. // ..... - Events one by one
  622. //
  623. // a) MasterEvent
  624. // b) RecurrencePttern
  625. // c) DWORD - Exceptions count
  626. // d) ..... - RecurrencePttern_Exceptions one by one
  627. //
  628. // ..... - Events one by one
  629. //
  630. long nSchema = XTP_MEM_DP_DATA_VER;
  631. PX_Long(pPX, _T("Version"), (long&)nSchema);
  632. pPX->ExchangeLocale();
  633. CXTPPropExchangeSection secOptions(pPX->GetSection(_T("Options")));
  634. secOptions->EmptySection();
  635. if (m_pCalendarOptions)
  636. {
  637. m_pCalendarOptions->DoPropExchange(&secOptions);
  638. }
  639. CXTPPropExchangeSection sec(pPX->GetSection(_T("Events")));
  640. sec->EmptySection();
  641. CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
  642. POSITION posEnum = pEnumerator->GetPosition(m_EventsStorage.GetCount());
  643. POSITION pos = m_EventsStorage.GetStartPosition();
  644. while (pos)
  645. {
  646. DWORD dwId = 0;
  647. CXTPCalendarEvent* pEvent = m_EventsStorage.GetNextElement(pos, dwId);
  648. int nRecState = pEvent->GetRecurrenceState();
  649. ASSERT(nRecState == xtpCalendarRecurrenceMaster || nRecState == xtpCalendarRecurrenceNotRecurring);
  650. CXTPCalendarRecurrencePatternPtr ptrPattern;
  651. if (nRecState == xtpCalendarRecurrenceMaster)
  652. {
  653. ptrPattern = pEvent->GetRecurrencePattern();
  654. ASSERT(ptrPattern);
  655. if (ptrPattern == NULL)
  656. continue;
  657. }
  658. CXTPPropExchangeSection secEvent(pEnumerator->GetNext(posEnum));
  659. pEvent->DoPropExchange(&secEvent);
  660. if (nRecState == xtpCalendarRecurrenceMaster)
  661. {
  662. CXTPPropExchangeSection secPattern(secEvent->GetSection(_T("Pattern")));
  663. ptrPattern->DoPropExchange(&secPattern);
  664. CXTPCalendarEventsPtr ptrExceptions = ptrPattern->GetExceptions();
  665. DWORD dwExcCount = ptrExceptions ? ptrExceptions->GetCount() : 0;
  666. CXTPPropExchangeEnumeratorPtr pEnumeratorExc(secPattern->GetEnumerator(_T("Exception")));
  667. POSITION posExc = pEnumeratorExc->GetPosition(dwExcCount);
  668. for (int n = 0; n < (int)dwExcCount; n++)
  669. {
  670. CXTPCalendarEvent* pExcept = ptrExceptions->GetAt(n, FALSE);
  671. ASSERT(pExcept->GetRecurrenceState() == xtpCalendarRecurrenceException);
  672. CXTPPropExchangeSection secExceptEvent(pEnumeratorExc->GetNext(posExc));
  673. pExcept->DoPropExchange(&secExceptEvent);
  674. }
  675. }
  676. }
  677. //=========================================
  678. if (m_pSchedules)
  679. {
  680. CXTPPropExchangeSection secSchedules(pPX->GetSection(_T("EventsSchedules")));
  681. m_pSchedules->DoPropExchange(&secSchedules);
  682. }
  683. return TRUE;
  684. }
  685. void CXTPCalendarMemoryDataProvider::DoRemoveAllEvents()
  686. {
  687. m_EventsStorage.RemoveAll();
  688. m_mapPatterns.RemoveAll();
  689. m_tree.Clear();
  690. }
  691. CXTPCalendarEventPtr CXTPCalendarMemoryDataProvider::DoRead_Event(DWORD dwEventID)
  692. {
  693. CXTPCalendarEvent* pEvent = m_EventsStorage.Get(dwEventID);
  694. if (!pEvent)
  695. {
  696. return NULL;
  697. }
  698. return pEvent->CloneEvent();
  699. }
  700. CXTPCalendarRecurrencePatternPtr CXTPCalendarMemoryDataProvider::DoRead_RPattern(DWORD dwPatternID)
  701. {
  702. CXTPCalendarRecurrencePattern* pPattern = m_mapPatterns.Get(dwPatternID);
  703. if (!pPattern)
  704. {
  705. return NULL;
  706. }
  707. CXTPCalendarRecurrencePatternPtr ptrPattern2 = pPattern->ClonePattern();
  708. if (ptrPattern2)
  709. {
  710. VERIFY( pPattern->GetOccReminders()->Save(ptrPattern2->GetCustomProperties(), NULL) );
  711. }
  712. return ptrPattern2;
  713. }
  714. BOOL CXTPCalendarMemoryDataProvider::DoCreate_Event(CXTPCalendarEvent* pEvent, DWORD& rdwNewEventID)
  715. {
  716. if (!pEvent)
  717. {
  718. ASSERT(FALSE);
  719. return FALSE;
  720. }
  721. DWORD dwEventID = pEvent->GetEventID();
  722. int nRState = pEvent->GetRecurrenceState();
  723. if (nRState == xtpCalendarRecurrenceException)
  724. {
  725. rdwNewEventID = _UniqueID_Event(dwEventID);
  726. return TRUE;
  727. }
  728. ASSERT(nRState == xtpCalendarRecurrenceMaster || nRState == xtpCalendarRecurrenceNotRecurring);
  729. CXTPCalendarEventPtr ptrEvent2 = pEvent->CloneEvent();
  730. if (!ptrEvent2)
  731. {
  732. return FALSE;
  733. }
  734. rdwNewEventID = _UniqueID_Event(dwEventID);
  735. ptrEvent2->SetEventID(rdwNewEventID);
  736. pEvent->SetEventID(rdwNewEventID);
  737. dwEventID = rdwNewEventID;
  738. // add to storage
  739. m_EventsStorage.Add(dwEventID, ptrEvent2);
  740. // add to search tree
  741. m_tree.Insert(ptrEvent2);
  742. //- Process recurrence event -------------------------
  743. if (nRState == xtpCalendarRecurrenceMaster)
  744. {
  745. CXTPCalendarEventHelper* pEvent2Ex = (CXTPCalendarEventHelper*)(CXTPCalendarEvent*)ptrEvent2;
  746. CXTPCalendarRecurrencePattern* pPatternRef = pEvent2Ex->GetRPatternRef();
  747. ASSERT(pPatternRef);
  748. if (pPatternRef)
  749. {
  750. DWORD dwPatternID = ptrEvent2->GetRecurrencePatternID();
  751. DWORD dwPatternIDnew = _UniqueID_Patern(dwPatternID);
  752. ptrEvent2->SetRecurrencePatternID(dwPatternIDnew);
  753. pEvent->SetRecurrencePatternID(dwPatternIDnew);
  754. m_mapPatterns.Add(dwPatternID, pPatternRef);
  755. }
  756. }
  757. //----------------------------------------------------
  758. return TRUE;
  759. }
  760. BOOL CXTPCalendarMemoryDataProvider::DoUpdate_Event(CXTPCalendarEvent* pEvent)
  761. {
  762. DWORD dwEventID = pEvent->GetEventID();
  763. ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
  764. //- new recurrence state ---------------------------
  765. int nRState = pEvent->GetRecurrenceState();
  766. if (nRState == xtpCalendarRecurrenceException ||
  767. nRState == xtpCalendarRecurrenceOccurrence)
  768. {
  769. ASSERT(nRState == xtpCalendarRecurrenceException);
  770. return TRUE;
  771. }
  772. //-------------------------------------------------------
  773. CXTPCalendarEventPtr ptrMainEvent(m_EventsStorage.Get(dwEventID), TRUE);
  774. if (!ptrMainEvent)
  775. {
  776. ASSERT(FALSE);
  777. return FALSE;
  778. }
  779. // update event in search tree
  780. m_tree.Remove(ptrMainEvent);
  781. VERIFY( m_EventsStorage.Remove(dwEventID) );
  782. if (ptrMainEvent->GetRecurrenceState() == xtpCalendarRecurrenceMaster)
  783. {
  784. DWORD dwPatternID = ptrMainEvent->GetRecurrencePatternID();
  785. m_mapPatterns.Remove(dwPatternID);
  786. }
  787. //******************************
  788. DWORD dwNewID;
  789. BOOL bRes = DoCreate_Event(pEvent, dwNewID);
  790. ASSERT(dwNewID == dwEventID);
  791. return bRes;
  792. }
  793. BOOL CXTPCalendarMemoryDataProvider::DoDelete_Event(CXTPCalendarEvent* pEvent)
  794. {
  795. DWORD dwEventID = pEvent->GetEventID();
  796. ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
  797. //- new recurrence state ---------------------------
  798. int nRState = pEvent->GetRecurrenceState();
  799. if (nRState == xtpCalendarRecurrenceException ||
  800. nRState == xtpCalendarRecurrenceOccurrence)
  801. {
  802. ASSERT(nRState == xtpCalendarRecurrenceException);
  803. return TRUE;
  804. }
  805. //-------------------------------------------------------
  806. CXTPCalendarEventPtr ptrEvent(m_EventsStorage.Get(dwEventID), TRUE);
  807. if (!ptrEvent)
  808. {
  809. ASSERT(FALSE);
  810. return FALSE;
  811. }
  812. // remove event from storage
  813. BOOL bRes = m_EventsStorage.Remove(dwEventID);
  814. if (!bRes)
  815. {
  816. return FALSE;
  817. }
  818. // remove event from search tree
  819. m_tree.Remove(ptrEvent);
  820. return TRUE;
  821. }
  822. BOOL CXTPCalendarMemoryDataProvider::DoCreate_RPattern(CXTPCalendarRecurrencePattern* pPattern, DWORD& rdwNewPatternID)
  823. {
  824. if (!pPattern)
  825. {
  826. ASSERT(FALSE);
  827. return FALSE;
  828. }
  829. rdwNewPatternID = pPattern->GetPatternID();
  830. CXTPCalendarRecurrencePattern* pPatternRef = m_mapPatterns.Get(rdwNewPatternID);
  831. if (pPatternRef)
  832. {
  833. VERIFY( pPatternRef->Update(pPattern) );
  834. }
  835. return TRUE;
  836. }
  837. BOOL CXTPCalendarMemoryDataProvider::DoUpdate_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  838. {
  839. if (!pPattern)
  840. {
  841. ASSERT(FALSE);
  842. return FALSE;
  843. }
  844. DWORD dwPatternID = pPattern->GetPatternID();
  845. ASSERT(m_mapPatterns.IsExist(dwPatternID));
  846. CXTPCalendarRecurrencePattern* pPatternRef = m_mapPatterns.Get(dwPatternID);
  847. ASSERT(pPatternRef);
  848. if (pPatternRef)
  849. {
  850. VERIFY( pPatternRef->Update(pPattern) );
  851. }
  852. return TRUE;
  853. }
  854. BOOL CXTPCalendarMemoryDataProvider::DoDelete_RPattern(CXTPCalendarRecurrencePattern* pPattern)
  855. {
  856. if (!pPattern)
  857. {
  858. ASSERT(FALSE);
  859. return FALSE;
  860. }
  861. DWORD dwPatternID = pPattern->GetPatternID();
  862. return m_mapPatterns.Remove(dwPatternID);
  863. }
  864. DWORD CXTPCalendarMemoryDataProvider::_UniqueID_Event(DWORD dwID)
  865. {
  866. if (dwID == XTP_CALENDAR_UNKNOWN_EVENT_ID)
  867. {
  868. dwID = GetNextFreeTempID();
  869. }
  870. for (int i = 0; i < 1000 && m_EventsStorage.IsExist(dwID); i++)
  871. {
  872. dwID = GetNextFreeTempID();
  873. }
  874. ASSERT(m_EventsStorage.IsExist(dwID) == FALSE);
  875. return dwID;
  876. }
  877. DWORD CXTPCalendarMemoryDataProvider::_UniqueID_Patern(DWORD dwID)
  878. {
  879. if (dwID == XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID)
  880. {
  881. dwID = GetNextFreeTempID();
  882. }
  883. for (int i = 0; i < 1000 && m_mapPatterns.IsExist(dwID); i++)
  884. {
  885. dwID = GetNextFreeTempID();
  886. }
  887. ASSERT(m_mapPatterns.IsExist(dwID) == FALSE);
  888. return dwID;
  889. }