You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1072 lines
25 KiB
C++
1072 lines
25 KiB
C++
// XTPCalendarMemoryDataProvider.cpp: implementation of the CXTPCalendarMemoryDataProvider class.
|
|
//
|
|
// This file is a part of the XTREME CALENDAR MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "Common/XTPPropExchange.h"
|
|
#include "Common/XTPNotifyConnection.h"
|
|
#include "Common/XTPSmartPtrInternalT.h"
|
|
|
|
#include "XTPCalendarDefines.h"
|
|
#include "XTPCalendarUtils.h"
|
|
#include "XTPCalendarPtrCollectionT.h"
|
|
|
|
#include "XTPCalendarResource.h"
|
|
#include "XTPCalendarOptions.h"
|
|
|
|
#include "XTPCalendarEvent.h"
|
|
#include "XTPCalendarEvents.h"
|
|
#include "XTPCalendarRecurrencePattern.h"
|
|
|
|
#include "XTPCalendarData.h"
|
|
#include "XTPCalendarMemoryDataProvider.h"
|
|
|
|
#define _XML_FILE
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#define XTP_MEM_DP_DATA_VER 1
|
|
|
|
//===========================================================================
|
|
// Should be a prime number:
|
|
// 37, 53, 67, 79, 101, 127, 199, 503, 1021, 1511, 2003, 3001
|
|
//===========================================================================
|
|
#define XTP_MEMDP_TMP_HASH_TABLE_SIZE 67
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPCalendarMemoryDataProvider implementation
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPCalendarMemoryDataProvider, CXTPCalendarData)
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
CXTPCalendarMemoryDataProvider::CXTPCalendarMemoryDataProvider() :
|
|
m_EventsStorage(XTP_EVENTS_STORAGE_HASH_TABLE_SIZE)
|
|
{
|
|
m_typeProvider = xtpCalendarDataProviderMemory;
|
|
}
|
|
|
|
CXTPCalendarMemoryDataProvider::~CXTPCalendarMemoryDataProvider()
|
|
{
|
|
}
|
|
|
|
CString CXTPCalendarMemoryDataProvider::GetXMLEncoding()
|
|
{
|
|
CString strConnStr_lower = m_strConnectionString;
|
|
strConnStr_lower.MakeLower();
|
|
|
|
int nIndex = strConnStr_lower.Find(_T("encoding="));
|
|
if (nIndex == -1)
|
|
return _T("UTF-8");
|
|
|
|
CString strEncoding = m_strConnectionString.Mid(nIndex + 9);
|
|
|
|
nIndex = strEncoding.Find(_T(';'));
|
|
if (nIndex != -1)
|
|
strEncoding = strEncoding.Left(nIndex);
|
|
|
|
return strEncoding;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::IsProviderXML(BOOL bCheckXMLsupport, BOOL* pbXMLsupportError)
|
|
{
|
|
if (pbXMLsupportError)
|
|
{
|
|
*pbXMLsupportError = FALSE;
|
|
}
|
|
|
|
CString strConnStr_lower = m_strConnectionString;
|
|
strConnStr_lower.MakeLower();
|
|
|
|
if (strConnStr_lower.IsEmpty())
|
|
return FALSE;
|
|
|
|
if (strConnStr_lower.Find(_T("provider=xml")) == -1)
|
|
return FALSE;
|
|
|
|
if (bCheckXMLsupport)
|
|
{
|
|
CXTPDOMDocumentPtr xmlDocPtr;
|
|
BOOL bCreated = SUCCEEDED(xmlDocPtr.CreateInstance(CLSID_XTPDOMDocument));
|
|
|
|
if (pbXMLsupportError)
|
|
{
|
|
*pbXMLsupportError = !bCreated;
|
|
}
|
|
return bCreated;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::Open()
|
|
{
|
|
CString strFileName = GetDataSource();
|
|
|
|
const int cnErrSize = 4096;
|
|
TCHAR szError[cnErrSize+1];
|
|
ZeroMemory(szError, sizeof(szError));
|
|
|
|
CXTPCalendarData::Open();
|
|
RemoveAllEvents();
|
|
|
|
if (strFileName.IsEmpty())
|
|
{
|
|
return TRUE;
|
|
}
|
|
BOOL bResult = TRUE;
|
|
|
|
try
|
|
{
|
|
BOOL bXMLsupportError = FALSE;
|
|
if (!IsProviderXML(TRUE, &bXMLsupportError))
|
|
{
|
|
if (bXMLsupportError)
|
|
{
|
|
TRACE(_T("Warning: CXTPCalendarMemoryDataProvider::Open() cannot create XML parcer instance.\n"));
|
|
TRACE(_T("\tperhaps AfxOleInit() has not been called, or msxml3.dll not found. \n"));
|
|
TRACE(_T("\tThe binary data format is used. \n."));
|
|
}
|
|
|
|
CFile fileData(strFileName, CFile::modeRead);
|
|
|
|
if (fileData.GetLength() >= 8)
|
|
{
|
|
CArchive arData(&fileData, CArchive::load);
|
|
CXTPPropExchangeArchive px(arData);
|
|
bResult = _Load(&px);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bResult = FALSE;
|
|
#ifndef _XTP_EXCLUDE_XML
|
|
CXTPPropExchangeXMLNode px(TRUE, 0, _T("Calendar"));
|
|
px.SetEncoding(GetXMLEncoding());
|
|
if (px.LoadFromFile(strFileName))
|
|
{
|
|
bResult = _Load(&px);
|
|
}
|
|
#else
|
|
//bResult = FALSE;
|
|
#endif
|
|
}
|
|
}
|
|
catch(CFileException* pEfile)
|
|
{
|
|
if (pEfile->GetErrorMessage(szError, cnErrSize))
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Load Events data file error: %s \n"), szError);
|
|
}
|
|
pEfile->Delete();
|
|
bResult = FALSE;
|
|
}
|
|
catch(CArchiveException* pEarc)
|
|
{
|
|
if (pEarc->GetErrorMessage(szError, cnErrSize))
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Load Events data archive error: %s \n"), szError);
|
|
}
|
|
//pEarc->ReportError();
|
|
pEarc->Delete();
|
|
bResult = FALSE;
|
|
}
|
|
catch(_com_error& e)
|
|
{
|
|
const TCHAR* pErrStr = e.ErrorMessage();
|
|
|
|
if (pErrStr)
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Store Events data COM error: %s \n"), pErrStr);
|
|
}
|
|
bResult = FALSE;
|
|
}
|
|
|
|
if (!bResult)
|
|
{
|
|
CXTPCalendarData::Close();
|
|
}
|
|
return bResult;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::Create()
|
|
{
|
|
CXTPCalendarData::Create();
|
|
|
|
return Save();
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::Save()
|
|
{
|
|
CString strFileName = GetDataSource();
|
|
|
|
if (strFileName.IsEmpty())
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
const int cnErrSize = 4096;
|
|
TCHAR szError[cnErrSize+1];
|
|
ZeroMemory(szError, sizeof(szError));
|
|
|
|
try
|
|
{
|
|
BOOL bXMLsupportError = FALSE;
|
|
if (!IsProviderXML(TRUE, &bXMLsupportError))
|
|
{
|
|
if (bXMLsupportError)
|
|
{
|
|
TRACE(_T("Warning: CXTPCalendarMemoryDataProvider::Save() cannot create XML parcer instance.\n"));
|
|
TRACE(_T("\tperhaps AfxOleInit() has not been called, or msxml3.dll not found. \n"));
|
|
TRACE(_T("\tThe binary data format is used. \n."));
|
|
}
|
|
|
|
CFile fileData(strFileName, CFile::modeWrite | CFile::modeCreate);
|
|
CArchive arData(&fileData, CArchive::store);
|
|
|
|
CXTPPropExchangeArchive px(arData);
|
|
_Save(&px);
|
|
}
|
|
else
|
|
{
|
|
#ifndef _XTP_EXCLUDE_XML
|
|
CXTPPropExchangeXMLNode px(FALSE, 0, _T("Calendar"));
|
|
px.SetEncoding(GetXMLEncoding());
|
|
_Save(&px);
|
|
px.SaveToFile(strFileName);
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
}
|
|
catch(CFileException* pEfile)
|
|
{
|
|
if (pEfile->GetErrorMessage(szError, cnErrSize))
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Store Events data file error: %s \n"), szError);
|
|
}
|
|
pEfile->Delete();
|
|
return FALSE;
|
|
}
|
|
catch(CArchiveException* pEarc)
|
|
{
|
|
if (pEarc->GetErrorMessage(szError, cnErrSize))
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Store Events data archive error: %s \n"), szError);
|
|
}
|
|
pEarc->Delete();
|
|
return FALSE;
|
|
}
|
|
catch(_com_error& e)
|
|
{
|
|
const TCHAR* pErrStr = e.ErrorMessage();
|
|
|
|
if (pErrStr)
|
|
{
|
|
TRACE(_T("WARNING! MemoryDataProvider: Store Events data COM error: %s \n"), pErrStr);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::Close()
|
|
{
|
|
if (!IsOpen())
|
|
{
|
|
CXTPCalendarData::Open();
|
|
}
|
|
|
|
RemoveAllEvents();
|
|
|
|
CXTPCalendarData::Close();
|
|
}
|
|
|
|
CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoRetrieveDayEvents(COleDateTime dtDay)
|
|
{
|
|
CXTPCalendarEventsPtr ptrEvents = new CXTPCalendarEvents;
|
|
if (!ptrEvents)
|
|
{
|
|
return NULL;
|
|
}
|
|
m_tree.SearchForEvents((DWORD)dtDay, (DWORD)dtDay, ptrEvents);
|
|
|
|
_PostProcessOccurrencesFromMaster2(dtDay, dtDay, ptrEvents);
|
|
|
|
// call this function here to increase performance (to avoid clone events which will be removed)
|
|
_FilterDayEventsInstancesByEndTime(dtDay, ptrEvents);
|
|
|
|
ptrEvents->CloneEvents();
|
|
|
|
return ptrEvents;
|
|
}
|
|
|
|
CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::RetrieveEvents(COleDateTime dtStartDay, COleDateTime dtEndDay)
|
|
{
|
|
CXTPCalendarEventsPtr ptrEvents= new CXTPCalendarEvents;
|
|
if (!ptrEvents)
|
|
return NULL;
|
|
|
|
m_tree.SearchForEvents((DWORD)dtStartDay, (DWORD)dtEndDay, ptrEvents);
|
|
|
|
_PostProcessOccurrencesFromMaster2(dtStartDay, dtEndDay, ptrEvents);
|
|
|
|
// to remove multiday events which end day is dtStartDay.
|
|
_FilterDayEventsInstancesByEndTime(dtStartDay, ptrEvents);
|
|
|
|
ptrEvents->CloneEvents();
|
|
|
|
return ptrEvents;
|
|
}
|
|
|
|
CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoGetAllEvents_raw()
|
|
{
|
|
CXTPCalendarEventsPtr ptrArray = new CXTPCalendarEvents();
|
|
if (!ptrArray)
|
|
return NULL;
|
|
|
|
POSITION pos = m_EventsStorage.GetStartPosition();
|
|
while (pos)
|
|
{
|
|
DWORD dwID = 0;
|
|
CXTPCalendarEvent* pEvent = m_EventsStorage.GetNextElement(pos, dwID);
|
|
if (pEvent)
|
|
{
|
|
ptrArray->Add(pEvent, TRUE);
|
|
}
|
|
}
|
|
|
|
ptrArray->CloneEvents();
|
|
|
|
return ptrArray;
|
|
}
|
|
|
|
CXTPCalendarEventsPtr CXTPCalendarMemoryDataProvider::DoGetUpcomingEvents(
|
|
COleDateTime dtFrom, COleDateTimeSpan spPeriod)
|
|
{
|
|
UNREFERENCED_PARAMETER(dtFrom); UNREFERENCED_PARAMETER(spPeriod);
|
|
return DoGetAllEvents_raw();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Internal search algorithms and structures
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DSTNode
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CXTPCalendarMemoryDataProvider::DSTNode::DSTNode() :
|
|
m_pMapEvents(NULL), pLeft(NULL), pRight(NULL)
|
|
{}
|
|
|
|
CXTPCalendarMemoryDataProvider::DSTNode::~DSTNode()
|
|
{
|
|
if (m_pMapEvents)
|
|
delete m_pMapEvents;
|
|
if (pLeft)
|
|
delete pLeft;
|
|
if (pRight)
|
|
delete pRight;
|
|
}
|
|
void CXTPCalendarMemoryDataProvider::DSTNode::Mark(CXTPCalendarEvent* pEvent)
|
|
{
|
|
if (!m_pMapEvents)
|
|
{
|
|
m_pMapEvents = new EventsMap;
|
|
|
|
if (!m_pMapEvents) {
|
|
return;
|
|
}
|
|
}
|
|
m_pMapEvents->SetAt(pEvent, TRUE);
|
|
}
|
|
void CXTPCalendarMemoryDataProvider::DSTNode::Unmark(CXTPCalendarEvent* pEvent)
|
|
{
|
|
if (m_pMapEvents)
|
|
{
|
|
m_pMapEvents->RemoveKey(pEvent);
|
|
}
|
|
}
|
|
BOOL CXTPCalendarMemoryDataProvider::DSTNode::IsMarked(CXTPCalendarEvent* pEvent)
|
|
{
|
|
if (m_pMapEvents)
|
|
{
|
|
BOOL bValue;
|
|
return m_pMapEvents->Lookup(pEvent, bValue);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void CXTPCalendarMemoryDataProvider::DSTNode::AppendAll(CMapIDtoEvent* pMapEvents)
|
|
{
|
|
if (!pMapEvents || !m_pMapEvents)
|
|
return;
|
|
|
|
// enumerate all elements of the map
|
|
POSITION pos = m_pMapEvents->GetStartPosition();
|
|
BOOL bMark;
|
|
CXTPCalendarEvent* pEvent = NULL;
|
|
while (pos != NULL)
|
|
{
|
|
m_pMapEvents->GetNextAssoc(pos, pEvent, bMark);
|
|
if (bMark && pEvent)
|
|
{
|
|
pMapEvents->SetAt(pEvent->GetEventID(), pEvent);
|
|
}
|
|
}
|
|
|
|
}
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// DST
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const int xtpBitsScan = sizeof(DWORD) * 8 - 1;
|
|
|
|
CXTPCalendarMemoryDataProvider::DST::DST() :
|
|
tmp_mapEvents(64)
|
|
{
|
|
pHead = new DSTNode();
|
|
|
|
tmp_mapEvents.InitHashTable(XTP_MEMDP_TMP_HASH_TABLE_SIZE, FALSE);
|
|
}
|
|
|
|
CXTPCalendarMemoryDataProvider::DST::~DST()
|
|
{
|
|
if (pHead)
|
|
delete pHead;
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::Insert(CXTPCalendarEvent* pEvent)
|
|
{
|
|
MarkRange(pEvent, dstScanMark);
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::Remove(CXTPCalendarEvent* pEvent)
|
|
{
|
|
MarkRange(pEvent, dstScanUnmark);
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::Clear()
|
|
{
|
|
if (pHead)
|
|
delete pHead;
|
|
|
|
pHead = new DSTNode();
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::MarkRange(CXTPCalendarEvent* pEvent, const DSTScanType eScanType)
|
|
{
|
|
DWORD dwStartDay = (DWORD)pEvent->GetStartTime();
|
|
DWORD dwEndDay = (DWORD)pEvent->GetEndTime();
|
|
|
|
ScanRange(pHead, xtpBitsScan - 1, 0, (DWORD)(1 << xtpBitsScan),
|
|
dwStartDay, dwEndDay,
|
|
pEvent, NULL, eScanType);
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::SearchForEvents(DWORD dwStart, DWORD dwEnd, CXTPCalendarEvents* pEvents)
|
|
{
|
|
if (!pEvents)
|
|
return;
|
|
|
|
tmp_mapEvents.RemoveAll();
|
|
|
|
ScanRange(pHead, xtpBitsScan - 1, 0, (DWORD)(1 << xtpBitsScan),
|
|
dwStart, dwEnd,
|
|
NULL, &tmp_mapEvents, dstScanFind);
|
|
|
|
|
|
// move events from temp map to array
|
|
int nCount = (int)tmp_mapEvents.GetCount();
|
|
if (nCount)
|
|
{
|
|
int nIndex = pEvents->GetCount();
|
|
pEvents->SetSize(nIndex + nCount); // to avoid multi-reallocks
|
|
|
|
DWORD dwKey;
|
|
CXTPCalendarEvent* pEvent;
|
|
POSITION pos = tmp_mapEvents.GetStartPosition();
|
|
while (pos)
|
|
{
|
|
tmp_mapEvents.GetNextAssoc(pos, dwKey, pEvent);
|
|
ASSERT(pEvent);
|
|
if (pEvent)
|
|
pEvents->SetAt(nIndex, pEvent, TRUE);
|
|
|
|
nIndex++;
|
|
}
|
|
ASSERT(nIndex == pEvents->GetCount());
|
|
|
|
tmp_mapEvents.RemoveAll();
|
|
}
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DST::ScanRange(
|
|
DSTNode* const pNode, const int nDepth,
|
|
const DWORD dwMinValue, const DWORD dwMaxValue,
|
|
const DWORD dwStart, const DWORD dwEnd,
|
|
CXTPCalendarEvent* const pEvent, CMapIDtoEvent* pMapEvents,
|
|
const DSTScanType eScanType)
|
|
{
|
|
DWORD dwMediumValue = dwMinValue | (nDepth >= 0 ? 1 << nDepth : 0);
|
|
|
|
switch (eScanType)
|
|
{
|
|
case dstScanMark:
|
|
case dstScanUnmark:
|
|
// check if range contained in the min-max range
|
|
if (dwStart <= dwMinValue && dwEnd >= dwMaxValue - 1)
|
|
{
|
|
switch (eScanType)
|
|
{
|
|
case dstScanMark:
|
|
// Add this event to this entire range node.
|
|
pNode->Mark(pEvent);
|
|
return;
|
|
case dstScanUnmark:
|
|
// Delete this event from this entire range node.
|
|
pNode->Unmark(pEvent);
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
case dstScanFind:
|
|
if (dwEnd >= dwMinValue && dwStart < dwMaxValue)
|
|
{
|
|
pNode->AppendAll(pMapEvents);
|
|
}
|
|
break;
|
|
}
|
|
|
|
// check for end recursion
|
|
if (nDepth < 0)
|
|
return;
|
|
|
|
// run left search
|
|
if (dwStart <= dwMediumValue)
|
|
{
|
|
if (!pNode->pLeft && eScanType == dstScanMark)
|
|
pNode->pLeft = new DSTNode();
|
|
|
|
if (pNode->pLeft)
|
|
{
|
|
ScanRange(pNode->pLeft, nDepth - 1,
|
|
dwMinValue, dwMediumValue,
|
|
dwStart, dwEnd,
|
|
pEvent, pMapEvents,
|
|
eScanType);
|
|
}
|
|
}
|
|
|
|
// run right search
|
|
if (dwEnd >= dwMediumValue)
|
|
{
|
|
if (!pNode->pRight && eScanType == dstScanMark)
|
|
pNode->pRight = new DSTNode;
|
|
|
|
if (pNode->pRight)
|
|
{
|
|
ScanRange(pNode->pRight, nDepth - 1,
|
|
dwMediumValue, dwMaxValue,
|
|
dwStart, dwEnd,
|
|
pEvent, pMapEvents,
|
|
eScanType);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
void CXTPCalendarMemoryDataProvider::Serialize(CArchive& ar)
|
|
{
|
|
CXTPPropExchangeArchive px(ar);
|
|
DoPropExchange(&px);
|
|
}
|
|
void CXTPCalendarMemoryDataProvider::DoPropExchange(CXTPPropExchange* pPX)
|
|
{
|
|
if (pPX->IsLoading())
|
|
{
|
|
VERIFY(_Load(pPX));
|
|
}
|
|
else
|
|
{
|
|
VERIFY(_Save(pPX));
|
|
}
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::_Load(CXTPPropExchange* pPX)
|
|
{
|
|
//------------------------------------
|
|
// - File data ver
|
|
//
|
|
// ..... - Events one by one
|
|
//
|
|
// a) MasterEvent
|
|
// b) RecurrencePttern
|
|
// c) DWORD - Exceptions count
|
|
// d) ..... - RecurrencePttern_Exceptions one by one
|
|
//
|
|
// ..... - Events one by one
|
|
//
|
|
|
|
CXTPAutoResetValue<BOOL> autoReset(m_bDisableNotificationsSending, FALSE);
|
|
m_bDisableNotificationsSending = TRUE;
|
|
|
|
long nSchema = 0;
|
|
|
|
PX_Long(pPX, _T("Version"), (long&)nSchema);
|
|
pPX->ExchangeLocale();
|
|
|
|
if (nSchema != XTP_MEM_DP_DATA_VER)
|
|
{
|
|
//AfxMessageBox(_T("Unsupported data file version."));
|
|
TRACE(_T("ERROR! MemoryDataProvider: Unsupported data file version. (%d) \n"), nSchema);
|
|
return FALSE;
|
|
}
|
|
|
|
CXTPPropExchangeSection secOptions(pPX->GetSection(_T("Options")));
|
|
if (m_pCalendarOptions)
|
|
{
|
|
m_pCalendarOptions->DoPropExchange(&secOptions);
|
|
}
|
|
|
|
CXTPPropExchangeSection sec(pPX->GetSection(_T("Events")));
|
|
CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
|
|
POSITION pos = pEnumerator->GetPosition();
|
|
|
|
DWORD dwMinEventID = (DWORD)-1;
|
|
|
|
while (pos)
|
|
{
|
|
CXTPCalendarEventPtr ptrEvent = CreateNewEvent();
|
|
if (!ptrEvent)
|
|
{
|
|
return FALSE;
|
|
}
|
|
CXTPPropExchangeSection secEvent(pEnumerator->GetNext(pos));
|
|
ptrEvent->DoPropExchange(&secEvent);
|
|
|
|
dwMinEventID = min(dwMinEventID, ptrEvent->GetEventID());
|
|
|
|
int nRecState = ptrEvent->GetRecurrenceState();
|
|
ASSERT(nRecState == xtpCalendarRecurrenceMaster || nRecState == xtpCalendarRecurrenceNotRecurring);
|
|
|
|
if (nRecState == xtpCalendarRecurrenceMaster)
|
|
{
|
|
CXTPCalendarRecurrencePatternPtr ptrPattern = ptrEvent->GetRecurrencePattern();
|
|
if (!ptrPattern || !ptrPattern)
|
|
{
|
|
ASSERT(FALSE);
|
|
continue;
|
|
}
|
|
|
|
CXTPPropExchangeSection secPattern(secEvent->GetSection(_T("Pattern")));
|
|
ptrPattern->DoPropExchange(&secPattern);
|
|
|
|
DWORD dwPatternID = ptrPattern->GetPatternID();
|
|
dwMinEventID = min(dwMinEventID, dwPatternID);
|
|
|
|
CXTPPropExchangeEnumeratorPtr pEnumeratorExc(secPattern->GetEnumerator(_T("Exception")));
|
|
POSITION posExc = pEnumeratorExc->GetPosition();
|
|
|
|
while (posExc)
|
|
{
|
|
CXTPCalendarEventPtr ptrExcept = CreateNewEvent();
|
|
if (!ptrExcept)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
CXTPPropExchangeSection secExceptEvent(pEnumeratorExc->GetNext(posExc));
|
|
ptrExcept->DoPropExchange(&secExceptEvent);
|
|
dwMinEventID = min(dwMinEventID, ptrExcept->GetEventID());
|
|
|
|
nRecState = ptrExcept->GetRecurrenceState();
|
|
ASSERT(nRecState == xtpCalendarRecurrenceException);
|
|
|
|
ptrPattern->SetException(ptrExcept);
|
|
}
|
|
|
|
//=======================================================
|
|
ptrEvent->UpdateRecurrence(ptrPattern);
|
|
}
|
|
|
|
VERIFY(AddEvent(ptrEvent));
|
|
}
|
|
|
|
//-----------------------------------------
|
|
ms_dwNextFreeTempID = dwMinEventID;
|
|
GetNextFreeTempID();
|
|
|
|
//=========================================
|
|
if (m_pSchedules)
|
|
{
|
|
CXTPPropExchangeSection secSchedules(pPX->GetSection(_T("EventsSchedules")));
|
|
m_pSchedules->DoPropExchange(&secSchedules);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::_Save(CXTPPropExchange* pPX)
|
|
{
|
|
//------------------------------------
|
|
// - File data ver
|
|
//
|
|
// ..... - Events one by one
|
|
//
|
|
// a) MasterEvent
|
|
// b) RecurrencePttern
|
|
// c) DWORD - Exceptions count
|
|
// d) ..... - RecurrencePttern_Exceptions one by one
|
|
//
|
|
// ..... - Events one by one
|
|
//
|
|
|
|
long nSchema = XTP_MEM_DP_DATA_VER;
|
|
PX_Long(pPX, _T("Version"), (long&)nSchema);
|
|
pPX->ExchangeLocale();
|
|
|
|
CXTPPropExchangeSection secOptions(pPX->GetSection(_T("Options")));
|
|
secOptions->EmptySection();
|
|
if (m_pCalendarOptions)
|
|
{
|
|
m_pCalendarOptions->DoPropExchange(&secOptions);
|
|
}
|
|
|
|
CXTPPropExchangeSection sec(pPX->GetSection(_T("Events")));
|
|
sec->EmptySection();
|
|
|
|
CXTPPropExchangeEnumeratorPtr pEnumerator(sec->GetEnumerator(_T("Event")));
|
|
POSITION posEnum = pEnumerator->GetPosition(m_EventsStorage.GetCount());
|
|
|
|
POSITION pos = m_EventsStorage.GetStartPosition();
|
|
while (pos)
|
|
{
|
|
DWORD dwId = 0;
|
|
CXTPCalendarEvent* pEvent = m_EventsStorage.GetNextElement(pos, dwId);
|
|
|
|
int nRecState = pEvent->GetRecurrenceState();
|
|
ASSERT(nRecState == xtpCalendarRecurrenceMaster || nRecState == xtpCalendarRecurrenceNotRecurring);
|
|
|
|
CXTPCalendarRecurrencePatternPtr ptrPattern;
|
|
if (nRecState == xtpCalendarRecurrenceMaster)
|
|
{
|
|
ptrPattern = pEvent->GetRecurrencePattern();
|
|
ASSERT(ptrPattern);
|
|
if (ptrPattern == NULL)
|
|
continue;
|
|
}
|
|
|
|
CXTPPropExchangeSection secEvent(pEnumerator->GetNext(posEnum));
|
|
pEvent->DoPropExchange(&secEvent);
|
|
|
|
if (nRecState == xtpCalendarRecurrenceMaster)
|
|
{
|
|
CXTPPropExchangeSection secPattern(secEvent->GetSection(_T("Pattern")));
|
|
ptrPattern->DoPropExchange(&secPattern);
|
|
|
|
CXTPCalendarEventsPtr ptrExceptions = ptrPattern->GetExceptions();
|
|
|
|
DWORD dwExcCount = ptrExceptions ? ptrExceptions->GetCount() : 0;
|
|
|
|
CXTPPropExchangeEnumeratorPtr pEnumeratorExc(secPattern->GetEnumerator(_T("Exception")));
|
|
POSITION posExc = pEnumeratorExc->GetPosition(dwExcCount);
|
|
|
|
for (int n = 0; n < (int)dwExcCount; n++)
|
|
{
|
|
CXTPCalendarEvent* pExcept = ptrExceptions->GetAt(n, FALSE);
|
|
ASSERT(pExcept->GetRecurrenceState() == xtpCalendarRecurrenceException);
|
|
|
|
CXTPPropExchangeSection secExceptEvent(pEnumeratorExc->GetNext(posExc));
|
|
pExcept->DoPropExchange(&secExceptEvent);
|
|
}
|
|
}
|
|
}
|
|
|
|
//=========================================
|
|
if (m_pSchedules)
|
|
{
|
|
CXTPPropExchangeSection secSchedules(pPX->GetSection(_T("EventsSchedules")));
|
|
m_pSchedules->DoPropExchange(&secSchedules);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPCalendarMemoryDataProvider::DoRemoveAllEvents()
|
|
{
|
|
m_EventsStorage.RemoveAll();
|
|
m_mapPatterns.RemoveAll();
|
|
|
|
m_tree.Clear();
|
|
}
|
|
|
|
CXTPCalendarEventPtr CXTPCalendarMemoryDataProvider::DoRead_Event(DWORD dwEventID)
|
|
{
|
|
CXTPCalendarEvent* pEvent = m_EventsStorage.Get(dwEventID);
|
|
if (!pEvent)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return pEvent->CloneEvent();
|
|
}
|
|
|
|
CXTPCalendarRecurrencePatternPtr CXTPCalendarMemoryDataProvider::DoRead_RPattern(DWORD dwPatternID)
|
|
{
|
|
CXTPCalendarRecurrencePattern* pPattern = m_mapPatterns.Get(dwPatternID);
|
|
if (!pPattern)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
CXTPCalendarRecurrencePatternPtr ptrPattern2 = pPattern->ClonePattern();
|
|
if (ptrPattern2)
|
|
{
|
|
VERIFY( pPattern->GetOccReminders()->Save(ptrPattern2->GetCustomProperties(), NULL) );
|
|
}
|
|
return ptrPattern2;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoCreate_Event(CXTPCalendarEvent* pEvent, DWORD& rdwNewEventID)
|
|
{
|
|
if (!pEvent)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
DWORD dwEventID = pEvent->GetEventID();
|
|
|
|
int nRState = pEvent->GetRecurrenceState();
|
|
if (nRState == xtpCalendarRecurrenceException)
|
|
{
|
|
rdwNewEventID = _UniqueID_Event(dwEventID);
|
|
return TRUE;
|
|
}
|
|
|
|
ASSERT(nRState == xtpCalendarRecurrenceMaster || nRState == xtpCalendarRecurrenceNotRecurring);
|
|
|
|
CXTPCalendarEventPtr ptrEvent2 = pEvent->CloneEvent();
|
|
if (!ptrEvent2)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
rdwNewEventID = _UniqueID_Event(dwEventID);
|
|
|
|
ptrEvent2->SetEventID(rdwNewEventID);
|
|
pEvent->SetEventID(rdwNewEventID);
|
|
|
|
dwEventID = rdwNewEventID;
|
|
|
|
// add to storage
|
|
m_EventsStorage.Add(dwEventID, ptrEvent2);
|
|
|
|
// add to search tree
|
|
m_tree.Insert(ptrEvent2);
|
|
|
|
//- Process recurrence event -------------------------
|
|
if (nRState == xtpCalendarRecurrenceMaster)
|
|
{
|
|
CXTPCalendarEvent* pEvent2Ex = (CXTPCalendarEvent*)ptrEvent2;
|
|
CXTPCalendarRecurrencePattern* pPatternRef = pEvent2Ex->GetRPatternRef();
|
|
ASSERT(pPatternRef);
|
|
if (pPatternRef)
|
|
{
|
|
DWORD dwPatternID = ptrEvent2->GetRecurrencePatternID();
|
|
DWORD dwPatternIDnew = _UniqueID_Patern(dwPatternID);
|
|
|
|
ptrEvent2->SetRecurrencePatternID(dwPatternIDnew);
|
|
pEvent->SetRecurrencePatternID(dwPatternIDnew);
|
|
|
|
m_mapPatterns.Add(dwPatternID, pPatternRef);
|
|
}
|
|
}
|
|
//----------------------------------------------------
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoUpdate_Event(CXTPCalendarEvent* pEvent)
|
|
{
|
|
DWORD dwEventID = pEvent->GetEventID();
|
|
|
|
ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
|
|
|
//- new recurrence state ---------------------------
|
|
int nRState = pEvent->GetRecurrenceState();
|
|
|
|
if (nRState == xtpCalendarRecurrenceException ||
|
|
nRState == xtpCalendarRecurrenceOccurrence)
|
|
{
|
|
ASSERT(nRState == xtpCalendarRecurrenceException);
|
|
return TRUE;
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
CXTPCalendarEventPtr ptrMainEvent(m_EventsStorage.Get(dwEventID), TRUE);
|
|
if (!ptrMainEvent)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
// update event in search tree
|
|
m_tree.Remove(ptrMainEvent);
|
|
|
|
VERIFY( m_EventsStorage.Remove(dwEventID) );
|
|
if (ptrMainEvent->GetRecurrenceState() == xtpCalendarRecurrenceMaster)
|
|
{
|
|
DWORD dwPatternID = ptrMainEvent->GetRecurrencePatternID();
|
|
m_mapPatterns.Remove(dwPatternID);
|
|
}
|
|
//******************************
|
|
DWORD dwNewID;
|
|
BOOL bRes = DoCreate_Event(pEvent, dwNewID);
|
|
ASSERT(dwNewID == dwEventID);
|
|
|
|
return bRes;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoDelete_Event(CXTPCalendarEvent* pEvent)
|
|
{
|
|
DWORD dwEventID = pEvent->GetEventID();
|
|
ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
|
|
|
//- new recurrence state ---------------------------
|
|
int nRState = pEvent->GetRecurrenceState();
|
|
|
|
if (nRState == xtpCalendarRecurrenceException ||
|
|
nRState == xtpCalendarRecurrenceOccurrence)
|
|
{
|
|
ASSERT(nRState == xtpCalendarRecurrenceException);
|
|
return TRUE;
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
CXTPCalendarEventPtr ptrEvent(m_EventsStorage.Get(dwEventID), TRUE);
|
|
if (!ptrEvent)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
// remove event from storage
|
|
BOOL bRes = m_EventsStorage.Remove(dwEventID);
|
|
|
|
if (!bRes)
|
|
{
|
|
return FALSE;
|
|
}
|
|
// remove event from search tree
|
|
m_tree.Remove(ptrEvent);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoCreate_RPattern(CXTPCalendarRecurrencePattern* pPattern, DWORD& rdwNewPatternID)
|
|
{
|
|
if (!pPattern)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
rdwNewPatternID = pPattern->GetPatternID();
|
|
|
|
CXTPCalendarRecurrencePattern* pPatternRef = m_mapPatterns.Get(rdwNewPatternID);
|
|
if (pPatternRef)
|
|
{
|
|
VERIFY( pPatternRef->Update(pPattern) );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoUpdate_RPattern(CXTPCalendarRecurrencePattern* pPattern)
|
|
{
|
|
if (!pPattern)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
DWORD dwPatternID = pPattern->GetPatternID();
|
|
|
|
ASSERT(m_mapPatterns.IsExist(dwPatternID));
|
|
|
|
CXTPCalendarRecurrencePattern* pPatternRef = m_mapPatterns.Get(dwPatternID);
|
|
ASSERT(pPatternRef);
|
|
if (pPatternRef)
|
|
{
|
|
VERIFY( pPatternRef->Update(pPattern) );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPCalendarMemoryDataProvider::DoDelete_RPattern(CXTPCalendarRecurrencePattern* pPattern)
|
|
{
|
|
if (!pPattern)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
DWORD dwPatternID = pPattern->GetPatternID();
|
|
|
|
return m_mapPatterns.Remove(dwPatternID);
|
|
}
|
|
|
|
DWORD CXTPCalendarMemoryDataProvider::_UniqueID_Event(DWORD dwID)
|
|
{
|
|
if (dwID == XTP_CALENDAR_UNKNOWN_EVENT_ID)
|
|
{
|
|
dwID = GetNextFreeTempID();
|
|
}
|
|
for (int i = 0; i < 1000 && m_EventsStorage.IsExist(dwID); i++)
|
|
{
|
|
dwID = GetNextFreeTempID();
|
|
}
|
|
ASSERT(m_EventsStorage.IsExist(dwID) == FALSE);
|
|
return dwID;
|
|
}
|
|
|
|
DWORD CXTPCalendarMemoryDataProvider::_UniqueID_Patern(DWORD dwID)
|
|
{
|
|
if (dwID == XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID)
|
|
{
|
|
dwID = GetNextFreeTempID();
|
|
}
|
|
for (int i = 0; i < 1000 && m_mapPatterns.IsExist(dwID); i++)
|
|
{
|
|
dwID = GetNextFreeTempID();
|
|
}
|
|
ASSERT(m_mapPatterns.IsExist(dwID) == FALSE);
|
|
return dwID;
|
|
}
|