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.
1563 lines
36 KiB
C++
1563 lines
36 KiB
C++
2 years ago
|
// XTPCalendarData.cpp: implementation of the CXTPCalendarData 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/XTPNotifyConnection.h"
|
||
|
#include "Common/XTPColorManager.h"
|
||
|
#include "Common/XTPSmartPtrInternalT.h"
|
||
|
|
||
|
#include "XTPCalendarDefines.h"
|
||
|
#include "XTPCalendarUtils.h"
|
||
|
#include "XTPCalendarNotifications.h"
|
||
|
#include "XTPCalendarOptions.h"
|
||
|
#include "XTPCalendarPtrCollectionT.h"
|
||
|
|
||
|
#include "XTPCalendarEvent.h"
|
||
|
#include "XTPCalendarEvents.h"
|
||
|
#include "XTPCalendarRecurrencePattern.h"
|
||
|
|
||
|
#include "XTPCalendarCustomProperties.h"
|
||
|
|
||
|
#include "XTPCalendarEventLabel.h"
|
||
|
#include "XTPCalendarResource.h"
|
||
|
|
||
|
#include "XTPCalendarData.h"
|
||
|
#include "XTPCalendarMemoryDataProvider.h"
|
||
|
|
||
|
#include "XTPCalendarADO.h"
|
||
|
#include "XTPCalendarDatabaseDataProvider.h"
|
||
|
|
||
|
#include "XTPCalendarMAPIWrapper.h"
|
||
|
#include "XTPCalendarMAPIDataProvider.h"
|
||
|
#include "XTPCalendarCustomDataProvider.h"
|
||
|
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define DBG_CACHE_ASSERT ASSERT
|
||
|
|
||
|
#ifndef DBG_CACHE_ASSERT
|
||
|
#define DBG_CACHE_ASSERT
|
||
|
#endif
|
||
|
|
||
|
//===========================================================================
|
||
|
// Summary:
|
||
|
// Define data provider cache hash table size. Should be a prime number!
|
||
|
// like: 503, 1021, 1511, 2003, 3001, 4001, 5003, 6007, 8009, 12007,
|
||
|
// 16001, 32003, 48017, 64007
|
||
|
// See Also: CMap overview
|
||
|
//===========================================================================
|
||
|
#define XTP_DP_CACHE_HASH_TABLE_SIZE 1021
|
||
|
|
||
|
long VAR2long(const COleVariant& oleVar)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
_variant_t vtValue((const VARIANT*)&oleVar);
|
||
|
|
||
|
return (long)vtValue;
|
||
|
}
|
||
|
//catch(_com_error e)
|
||
|
catch(...)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
CXTPCalendarData::CXTPDPCache::CXTPDPCache()
|
||
|
{
|
||
|
m_pCacheDP = NULL;
|
||
|
m_eCacheMode = xtpCalendarDPCacheModeOff;
|
||
|
|
||
|
m_mapIsDayInCache.InitHashTable(XTP_DP_CACHE_HASH_TABLE_SIZE, FALSE);
|
||
|
}
|
||
|
|
||
|
CXTPCalendarData::CXTPDPCache::~CXTPDPCache()
|
||
|
{
|
||
|
SafeClose();
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::SafeClose()
|
||
|
{
|
||
|
if (m_pCacheDP)
|
||
|
{
|
||
|
if (m_pCacheDP->IsOpen())
|
||
|
{
|
||
|
m_pCacheDP->Close();
|
||
|
}
|
||
|
}
|
||
|
CMDTARGET_RELEASE(m_pCacheDP);
|
||
|
|
||
|
m_eCacheMode = xtpCalendarDPCacheModeOff;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::SafeRemoveAll()
|
||
|
{
|
||
|
if (m_pCacheDP)
|
||
|
{
|
||
|
m_pCacheDP->RemoveAllEvents();
|
||
|
}
|
||
|
m_mapIsDayInCache.RemoveAll();
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::CXTPDPCache::IsDayInCache(COleDateTime dtDay)
|
||
|
{
|
||
|
BOOL bIs = FALSE;
|
||
|
return m_mapIsDayInCache.Lookup((DWORD)(DATE)dtDay, bIs) && bIs;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::SetDayInCache(COleDateTime dtDay, BOOL bSet)
|
||
|
{
|
||
|
if (bSet)
|
||
|
{
|
||
|
m_mapIsDayInCache.SetAt((DWORD)(DATE)dtDay, TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_mapIsDayInCache.RemoveKey((DWORD)(DATE)dtDay);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::CXTPDPCache::IsEventInCache(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
if (!pEvent || !m_pCacheDP)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int nRState = pEvent->GetRecurrenceState();
|
||
|
|
||
|
if (nRState == xtpCalendarRecurrenceNotRecurring ||
|
||
|
nRState == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
DWORD dwEventID = pEvent->GetEventID();
|
||
|
CXTPCalendarEventPtr ptrEvInCache = m_pCacheDP->GetEvent(dwEventID);
|
||
|
|
||
|
return ptrEvInCache != NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(nRState == xtpCalendarRecurrenceOccurrence || nRState == xtpCalendarRecurrenceException);
|
||
|
|
||
|
DWORD dwRPatternID = pEvent->GetRecurrencePatternID();
|
||
|
CXTPCalendarRecurrencePatternPtr ptrRPattern = m_pCacheDP->GetRecurrencePattern(dwRPatternID);
|
||
|
return ptrRPattern != NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::_AddToCacheIfNeed(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
ASSERT(pPattern);
|
||
|
if (!pPattern || !m_pCacheDP)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DWORD dwRPatternID = pPattern->GetPatternID();
|
||
|
CXTPCalendarRecurrencePatternPtr ptrRPattern = m_pCacheDP->GetRecurrencePattern(dwRPatternID);
|
||
|
|
||
|
if (ptrRPattern)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
{
|
||
|
DWORD dwMasterEventID = pPattern->GetMasterEventID();
|
||
|
CXTPCalendarEventPtr ptrMasterEvent = m_pCacheDP->GetEvent(dwMasterEventID);
|
||
|
ASSERT(ptrMasterEvent == NULL);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
CXTPCalendarEventPtr ptrMasterEvent = pPattern->GetMasterEvent(); // this call also add master event to cache
|
||
|
ASSERT(ptrMasterEvent);
|
||
|
|
||
|
if (ptrMasterEvent)
|
||
|
{
|
||
|
// Must be added to cache in call: pPattern->GetMasterEvent();
|
||
|
//
|
||
|
DWORD dwMasterEventID = ptrMasterEvent->GetEventID();
|
||
|
CXTPCalendarEventPtr ptrEvInCache = m_pCacheDP->GetEvent(dwMasterEventID);
|
||
|
DBG_CACHE_ASSERT(ptrEvInCache);
|
||
|
|
||
|
if (!ptrEvInCache)
|
||
|
{
|
||
|
// this strange, but add if it is still not here
|
||
|
VERIFY(m_pCacheDP->AddEvent(ptrMasterEvent));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::AddToCacheIfNeed(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
ASSERT(pEvent);
|
||
|
if (!pEvent || !m_pCacheDP)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int nRState = pEvent->GetRecurrenceState();
|
||
|
|
||
|
if (nRState == xtpCalendarRecurrenceNotRecurring ||
|
||
|
nRState == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
DWORD dwEventID = pEvent->GetEventID();
|
||
|
CXTPCalendarEventPtr ptrEvInCache = m_pCacheDP->GetEvent(dwEventID);
|
||
|
if (!ptrEvInCache)
|
||
|
{
|
||
|
VERIFY(m_pCacheDP->AddEvent(pEvent));
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// From previous version.
|
||
|
// Non-Optimal. Should not be called.
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::CXTPDPCache::AddToCache(CXTPCalendarEvents* pEvents, COleDateTime dtDay)
|
||
|
{
|
||
|
if (!pEvents)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int nCount = pEvents->GetCount();
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pEvent = pEvents->GetAt(i ,FALSE);
|
||
|
AddToCacheIfNeed(pEvent);
|
||
|
}
|
||
|
|
||
|
SetDayInCache(dtDay, TRUE);
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::SetCacheMode(int eCacheMode, CXTPCalendarData* pCacheDataProvider)
|
||
|
{
|
||
|
if (eCacheMode == xtpCalendarDPCacheModeOff)
|
||
|
{
|
||
|
m_cache.SafeClose();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!m_cache.m_pCacheDP && !pCacheDataProvider)
|
||
|
{
|
||
|
m_cache.m_pCacheDP = new CXTPCalendarMemoryDataProvider();
|
||
|
}
|
||
|
else if (!m_cache.m_pCacheDP && pCacheDataProvider)
|
||
|
{
|
||
|
m_cache.m_pCacheDP = pCacheDataProvider;
|
||
|
}
|
||
|
else if (m_cache.m_pCacheDP && pCacheDataProvider)
|
||
|
{
|
||
|
m_cache.SafeClose();
|
||
|
m_cache.m_pCacheDP = pCacheDataProvider;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP && !pCacheDataProvider);
|
||
|
}
|
||
|
|
||
|
if (!m_cache.m_pCacheDP)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
if (!m_cache.m_pCacheDP->IsOpen())
|
||
|
{
|
||
|
VERIFY( m_cache.m_pCacheDP->Open() );
|
||
|
}
|
||
|
m_cache.SafeRemoveAll();
|
||
|
|
||
|
m_cache.m_eCacheMode = eCacheMode;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::ClearCache()
|
||
|
{
|
||
|
m_cache.SafeRemoveAll();
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::RemoveAllEvents()
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_cache.SafeRemoveAll();
|
||
|
|
||
|
DoRemoveAllEvents();
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////
|
||
|
DWORD CXTPCalendarData::ms_dwNextFreeTempID = DWORD(-1);
|
||
|
//===========================================================================
|
||
|
IMPLEMENT_DYNAMIC(CXTPCalendarData, CCmdTarget)
|
||
|
|
||
|
CXTPCalendarData::CXTPCalendarData()
|
||
|
{
|
||
|
m_pCalendarOptions = NULL;
|
||
|
m_bOwnershipMode = FALSE;
|
||
|
|
||
|
m_bOpened = FALSE;
|
||
|
m_pConnection = new CXTPNotifyConnection();
|
||
|
m_bDisableNotificationsSending = FALSE;
|
||
|
|
||
|
m_pLabelList = new CXTPCalendarEventLabels();
|
||
|
m_pLabelList->InitDefaultValues();
|
||
|
|
||
|
m_typeProvider = xtpCalendarDataProviderUnknown;
|
||
|
|
||
|
m_pCustomProperties = new CXTPCalendarCustomProperties();
|
||
|
m_pSchedules = new CXTPCalendarSchedules();
|
||
|
|
||
|
m_pEventCategories = new CXTPCalendarEventCategories();
|
||
|
m_pEventCategories->InitDefaultValues();
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
CXTPCalendarData::~CXTPCalendarData()
|
||
|
{
|
||
|
if (m_pCalendarOptions)
|
||
|
{
|
||
|
m_pCalendarOptions->SetDataProvider(NULL);
|
||
|
}
|
||
|
ASSERT(!m_pCalendarOptions);
|
||
|
//CMDTARGET_RELEASE(m_pCalendarOptions);
|
||
|
|
||
|
CMDTARGET_RELEASE(m_pLabelList);
|
||
|
CMDTARGET_RELEASE(m_pConnection);
|
||
|
CMDTARGET_RELEASE(m_pCustomProperties);
|
||
|
CMDTARGET_RELEASE(m_pSchedules);
|
||
|
CMDTARGET_RELEASE(m_pEventCategories);
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::SetLabelList(CXTPCalendarEventLabels* pLabelList)
|
||
|
{
|
||
|
CMDTARGET_RELEASE(m_pLabelList);
|
||
|
|
||
|
m_pLabelList = pLabelList;
|
||
|
|
||
|
CMDTARGET_ADDREF(m_pLabelList);
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr CXTPCalendarData::CreateNewEvent(DWORD dwEventID)
|
||
|
{
|
||
|
CXTPCalendarEventPtr ptrEvent = new CXTPCalendarEvent(this);
|
||
|
|
||
|
if (ptrEvent)
|
||
|
{
|
||
|
DWORD dwTempID = dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID ? dwEventID: GetNextFreeTempID();
|
||
|
ptrEvent->SetEventID(dwTempID);
|
||
|
}
|
||
|
|
||
|
return ptrEvent;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr CXTPCalendarData::CreateNewRecurrencePattern(DWORD dwPatternID)
|
||
|
{
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern = new CXTPCalendarRecurrencePattern(this);
|
||
|
if (ptrPattern)
|
||
|
{
|
||
|
DWORD dwTempID = dwPatternID != XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID? dwPatternID : GetNextFreeTempID();
|
||
|
ptrPattern->SetPatternID(dwTempID);
|
||
|
}
|
||
|
return ptrPattern;
|
||
|
}
|
||
|
|
||
|
CString CXTPCalendarData::GetDataSource()
|
||
|
{
|
||
|
return DataSourceFromConStr(m_strConnectionString);
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::RetrieveDayEvents(COleDateTime dtDay)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
DBG_DATA_ASSERT(FALSE);
|
||
|
return NULL;
|
||
|
}
|
||
|
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
|
||
|
|
||
|
CXTPCalendarEventsPtr ptrResult = NULL;
|
||
|
|
||
|
if ((m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask) &&
|
||
|
m_cache.IsDayInCache(dtDay))
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
ptrResult = m_cache.m_pCacheDP->RetrieveDayEvents(dtDay);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ptrResult = DoRetrieveDayEvents(dtDay);
|
||
|
if (!ptrResult)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
_PostProcessRecurrenceIfNeed(ptrResult);
|
||
|
|
||
|
if (m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
m_cache.AddToCache(ptrResult, dtDay);
|
||
|
}
|
||
|
|
||
|
_PostProcessOccurrencesFromMaster(dtDay, ptrResult);
|
||
|
|
||
|
_FilterDayEventsInstancesByEndTime(dtDay, ptrResult);
|
||
|
}
|
||
|
|
||
|
return ptrResult;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::AddEvents(CXTPCalendarEvents* pEvents)
|
||
|
{
|
||
|
BOOL bResult = TRUE;
|
||
|
int nEventsCount = pEvents->GetCount();
|
||
|
for (int i = 0; i < nEventsCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pEvent = pEvents->GetAt(i, FALSE);
|
||
|
if (!AddEvent(pEvent))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::AddEvent(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pEvent->ClearIntermediateData();
|
||
|
|
||
|
COleDateTime dtNow = CXTPCalendarUtils::GetCurrentTime();
|
||
|
pEvent->SetLastModificationTime(dtNow);
|
||
|
|
||
|
DWORD dwNewEventID = pEvent->GetEventID();
|
||
|
|
||
|
if (!DoCreate_Event(pEvent, dwNewEventID))
|
||
|
{
|
||
|
DBG_DATA_ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
ASSERT(dwNewEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
pEvent->SetEventID(dwNewEventID);
|
||
|
|
||
|
int nRState = (long)pEvent->GetRecurrenceState();
|
||
|
|
||
|
BOOL bSendPatternAddedEvent = FALSE;
|
||
|
DWORD dwPatternID = XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID;
|
||
|
|
||
|
//- Process Recurrence Pattern for Master event -------------------------
|
||
|
if (nRState == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
CXTPCalendarRecurrencePattern* pPatternRef = pEvent->GetRPatternRef();
|
||
|
if (!pPatternRef)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pPatternRef->SetMasterEventID(dwNewEventID);
|
||
|
|
||
|
//pPatternRef->ResetReminderForOccFromThePast(pEvent);
|
||
|
|
||
|
VERIFY( pPatternRef->GetOccReminders()->Save(pPatternRef->GetCustomProperties(), pPatternRef) );
|
||
|
|
||
|
BOOL bRes = DoCreate_RPattern(pPatternRef, dwPatternID);
|
||
|
DBG_DATA_ASSERT(bRes);
|
||
|
|
||
|
pPatternRef->GetOccReminders()->ClearProperties(pPatternRef->GetCustomProperties());
|
||
|
|
||
|
if (!bRes)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
ASSERT(dwPatternID != XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID);
|
||
|
|
||
|
DWORD dwPatternID_prev = pEvent->GetRecurrencePatternID();
|
||
|
pEvent->SetRecurrencePatternID(dwPatternID);
|
||
|
|
||
|
if (dwPatternID_prev != dwPatternID)
|
||
|
{
|
||
|
bRes = DoUpdate_Event(pEvent);
|
||
|
DBG_DATA_ASSERT(bRes);
|
||
|
if (!bRes)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bSendPatternAddedEvent = TRUE;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnRepeat)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.m_pCacheDP) VERIFY( m_cache.m_pCacheDP->AddEvent(pEvent) );
|
||
|
}
|
||
|
else if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnClear)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
//m_cache.m_pCacheDP->RemoveAllEvents();
|
||
|
m_cache.SafeRemoveAll();
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
SendNotification(XTP_NC_CALENDAREVENTWASADDED, (WPARAM)pEvent->GetEventID(), (LPARAM)pEvent);
|
||
|
if (bSendPatternAddedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASADDED, dwPatternID, 0);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::ChangeEvent(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pEvent->ClearIntermediateData();
|
||
|
|
||
|
COleDateTime dtNow = CXTPCalendarUtils::GetCurrentTime();
|
||
|
pEvent->SetLastModificationTime(dtNow);
|
||
|
|
||
|
DWORD dwEventID = pEvent->GetEventID();
|
||
|
ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
|
||
|
//- new recurrence state ---------------------------
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern_new;
|
||
|
|
||
|
int nRState_new = pEvent->GetRecurrenceState();
|
||
|
|
||
|
// - Add/Update/Remove Recurrence Exception --------------------
|
||
|
if (nRState_new == xtpCalendarRecurrenceException ||
|
||
|
nRState_new == xtpCalendarRecurrenceOccurrence)
|
||
|
{
|
||
|
return _ChangeRExceptionOccurrence_nf(pEvent, FALSE);
|
||
|
}
|
||
|
//===========================================================================
|
||
|
|
||
|
//CXTPCalendarEventPtr ptrEventPrev = _GetEvent_UseCache(dwEventID);
|
||
|
CXTPCalendarEventPtr ptrEventPrev = GetEvent(dwEventID);
|
||
|
if (!ptrEventPrev)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//************************************************************
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern_prev;
|
||
|
|
||
|
BOOL bSendPatternAddedEvent = FALSE;
|
||
|
BOOL bSendPatternChangedEvent = FALSE;
|
||
|
BOOL bSendPatternDeletedEvent = FALSE;
|
||
|
DWORD dwPatternID = XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID;
|
||
|
|
||
|
//- previous recurrence state ---------------------
|
||
|
int nRState_prev = ptrEventPrev->GetRecurrenceState();
|
||
|
|
||
|
//=== Update Event Recurrence Properties. IF NEED.
|
||
|
//
|
||
|
// 1.Event become recurrence
|
||
|
if (nRState_prev == xtpCalendarRecurrenceNotRecurring &&
|
||
|
nRState_new == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
ptrPattern_new.SetPtr(pEvent->GetRPatternRef(), TRUE);
|
||
|
|
||
|
// ptrPattern_new->ResetReminderForOccFromThePast(pEvent);
|
||
|
|
||
|
if (!_AddRPatternWithExceptions(ptrPattern_new))
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
dwPatternID = ptrPattern_new->GetPatternID();
|
||
|
ASSERT(dwPatternID != XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID);
|
||
|
|
||
|
pEvent->SetRecurrencePatternID(dwPatternID);
|
||
|
|
||
|
bSendPatternAddedEvent = TRUE;
|
||
|
}
|
||
|
// 2.Event become Not Recurrence
|
||
|
else if (nRState_prev == xtpCalendarRecurrenceMaster &&
|
||
|
nRState_new == xtpCalendarRecurrenceNotRecurring)
|
||
|
{
|
||
|
ptrPattern_prev.SetPtr(ptrEventPrev->GetRPatternRef(), TRUE);
|
||
|
|
||
|
dwPatternID = ptrPattern_prev->GetPatternID();
|
||
|
bSendPatternDeletedEvent = TRUE;
|
||
|
|
||
|
if (!_RemoveRPatternWithExceptions(ptrPattern_prev))
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
// 3. Update Recurrence Event
|
||
|
else if (nRState_prev == xtpCalendarRecurrenceMaster &&
|
||
|
nRState_new == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
ptrPattern_new.SetPtr(pEvent->GetRPatternRef(), TRUE);
|
||
|
|
||
|
//ptrPattern_new->ResetReminderForOccFromThePast(pEvent);
|
||
|
|
||
|
if (!_ChangeRPatternWithExceptions(ptrPattern_new))
|
||
|
{
|
||
|
DBG_DATA_ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
dwPatternID = ptrPattern_new->GetPatternID();
|
||
|
bSendPatternChangedEvent = TRUE;
|
||
|
}
|
||
|
|
||
|
// Update Event properties
|
||
|
BOOL bRes = DoUpdate_Event(pEvent);
|
||
|
DBG_DATA_ASSERT(bRes);
|
||
|
if (!bRes)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnRepeat)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.IsEventInCache(pEvent))
|
||
|
{
|
||
|
if (m_cache.m_pCacheDP) VERIFY( m_cache.m_pCacheDP->ChangeEvent(pEvent) );
|
||
|
}
|
||
|
}
|
||
|
else if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnClear)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
//m_cache.m_pCacheDP->RemoveAllEvents();
|
||
|
m_cache.SafeRemoveAll();
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
SendNotification(XTP_NC_CALENDAREVENTWASCHANGED, (WPARAM)pEvent->GetEventID(), (LPARAM)pEvent);
|
||
|
|
||
|
if (bSendPatternAddedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASADDED, dwPatternID, 0);
|
||
|
}
|
||
|
else if (bSendPatternChangedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASCHANGED, dwPatternID, 0);
|
||
|
}
|
||
|
else if (bSendPatternDeletedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASDELETED, dwPatternID, 0);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DeleteEvent(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwEventID = pEvent->GetEventID();
|
||
|
ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
|
||
|
BOOL bRes = TRUE;
|
||
|
BOOL bSendPatternDeletedEvent = FALSE;
|
||
|
DWORD dwPatternID = XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID;
|
||
|
|
||
|
//- recurrence state ---------------------
|
||
|
int nRState = pEvent->GetRecurrenceState();
|
||
|
|
||
|
//1. remove occurrence (set deleted property to exception)
|
||
|
if (nRState == xtpCalendarRecurrenceOccurrence || nRState == xtpCalendarRecurrenceException)
|
||
|
{
|
||
|
CXTPCalendarEventPtr ptrException = pEvent->CloneEvent();
|
||
|
if (!ptrException)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (nRState == xtpCalendarRecurrenceOccurrence)
|
||
|
{
|
||
|
// make exception from Occurrence
|
||
|
ptrException->MakeAsRException();
|
||
|
}
|
||
|
ptrException->SetRExceptionDeleted(TRUE);
|
||
|
|
||
|
return _ChangeRExceptionOccurrence_nf(ptrException, TRUE);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!DoDelete_Event(pEvent))
|
||
|
{
|
||
|
bRes = FALSE;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------
|
||
|
if (nRState == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
dwPatternID = pEvent->GetRecurrencePatternID();
|
||
|
|
||
|
CXTPCalendarRecurrencePattern* pPattern = pEvent->GetRPatternRef();
|
||
|
if (!_RemoveRPatternWithExceptions(pPattern))
|
||
|
{
|
||
|
bRes = FALSE;
|
||
|
}
|
||
|
bSendPatternDeletedEvent = bRes;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnRepeat)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.IsEventInCache(pEvent))
|
||
|
{
|
||
|
if (m_cache.m_pCacheDP) VERIFY( m_cache.m_pCacheDP->DeleteEvent(pEvent) );
|
||
|
}
|
||
|
}
|
||
|
else if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnClear)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
//m_cache.m_pCacheDP->RemoveAllEvents();
|
||
|
m_cache.SafeRemoveAll();
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
if (bRes)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDAREVENTWASDELETED, (WPARAM)pEvent->GetEventID(), (LPARAM)pEvent);
|
||
|
}
|
||
|
if (bSendPatternDeletedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASDELETED, dwPatternID, 0);
|
||
|
}
|
||
|
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr CXTPCalendarData::GetEvent(DWORD dwEventID)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr ptrEvent;
|
||
|
if ((m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask))
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.m_pCacheDP) ptrEvent = m_cache.m_pCacheDP->GetEvent(dwEventID);
|
||
|
}
|
||
|
|
||
|
if (!ptrEvent)
|
||
|
{
|
||
|
ptrEvent = _GetEvent_raw(dwEventID);
|
||
|
if (!ptrEvent)
|
||
|
return NULL;
|
||
|
|
||
|
if (ptrEvent->GetRecurrenceState() != xtpCalendarRecurrenceNotRecurring &&
|
||
|
ptrEvent->GetRecurrenceState() != xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
if (m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
m_cache.AddToCacheIfNeed(ptrEvent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ptrEvent;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::_PostProcessRecurrenceIfNeed(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
COleVariant varRState;
|
||
|
COleVariant varRPatternID;
|
||
|
|
||
|
BOOL bRState_prop = pEvent->GetCustomProperties()->GetProperty(cszProcess_RecurrenceState, varRState);
|
||
|
BOOL bRPatternID_prop = pEvent->GetCustomProperties()->GetProperty(cszProcess_RecurrencePatternID, varRPatternID);
|
||
|
|
||
|
pEvent->GetCustomProperties()->RemoveProperty(cszProcess_RecurrenceState);
|
||
|
pEvent->GetCustomProperties()->RemoveProperty(cszProcess_RecurrencePatternID);
|
||
|
|
||
|
if (!bRState_prop)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
int nRState = VAR2long(varRState);
|
||
|
if (xtpCalendarRecurrenceMaster == nRState)
|
||
|
{
|
||
|
if (!bRPatternID_prop)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
DWORD dwRPatternID = (DWORD)VAR2long(varRPatternID);
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern = _GetRecurrencePattern_raw(dwRPatternID);
|
||
|
if (!ptrPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
VERIFY( pEvent->MakeEventAsRecurrence() );
|
||
|
pEvent->SetRecurrencePatternID(dwRPatternID);
|
||
|
VERIFY( pEvent->UpdateRecurrence(ptrPattern) );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
else if (xtpCalendarRecurrenceException == nRState)
|
||
|
{
|
||
|
DWORD dwRPatternID = bRPatternID_prop ? (DWORD)VAR2long(varRPatternID) : 0;
|
||
|
pEvent->SetRecurrencePatternID(dwRPatternID);
|
||
|
|
||
|
if (pEvent->GetRecurrenceState() != xtpCalendarRecurrenceException)
|
||
|
{
|
||
|
pEvent->MakeAsRException(dwRPatternID);
|
||
|
}
|
||
|
}
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::_PostProcessRecurrenceIfNeed(CXTPCalendarEvents* pEvents)
|
||
|
{
|
||
|
int nCount = pEvents ? pEvents->GetCount() : 0;
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pEvent = pEvents->GetAt(i, FALSE);
|
||
|
ASSERT(pEvent);
|
||
|
if (pEvent)
|
||
|
{
|
||
|
_PostProcessRecurrenceIfNeed(pEvent);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr CXTPCalendarData::_GetEvent_raw(DWORD dwEventID)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr ptrEvent = DoRead_Event(dwEventID);
|
||
|
if (!ptrEvent)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
_PostProcessRecurrenceIfNeed(ptrEvent);
|
||
|
|
||
|
return ptrEvent;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr CXTPCalendarData::_GetRecurrencePattern_raw(DWORD dwPatternID)
|
||
|
{
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern = DoRead_RPattern(dwPatternID);
|
||
|
|
||
|
if (ptrPattern)
|
||
|
{
|
||
|
VERIFY( ptrPattern->GetOccReminders()->Load(ptrPattern->GetCustomProperties()) );
|
||
|
ptrPattern->GetOccReminders()->ClearProperties(ptrPattern->GetCustomProperties());
|
||
|
}
|
||
|
return ptrPattern;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr CXTPCalendarData::GetRecurrencePattern(DWORD dwPatternID)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern;
|
||
|
if ((m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask))
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.m_pCacheDP) ptrPattern = m_cache.m_pCacheDP->GetRecurrencePattern(dwPatternID);
|
||
|
}
|
||
|
|
||
|
if (!ptrPattern)
|
||
|
{
|
||
|
ptrPattern = _GetRecurrencePattern_raw(dwPatternID);
|
||
|
|
||
|
if (ptrPattern && (m_cache.m_eCacheMode & xtpCalendarDPCacheModeOnMask))
|
||
|
{
|
||
|
m_cache._AddToCacheIfNeed(ptrPattern);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ptrPattern;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::_AddRPatternWithExceptions(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
VERIFY( pPattern->GetOccReminders()->Save(pPattern->GetCustomProperties(), pPattern) );
|
||
|
|
||
|
DWORD dwNewPatternID = XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID;
|
||
|
BOOL bRes = DoCreate_RPattern(pPattern, dwNewPatternID);
|
||
|
DBG_DATA_ASSERT(bRes);
|
||
|
|
||
|
pPattern->GetOccReminders()->ClearProperties(pPattern->GetCustomProperties());
|
||
|
|
||
|
if (!bRes)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
ASSERT(dwNewPatternID != XTP_CALENDAR_UNKNOWN_RECURRENCE_PATTERN_ID);
|
||
|
pPattern->SetPatternID(dwNewPatternID);
|
||
|
|
||
|
BOOL bResult = TRUE;
|
||
|
//-- Process exceptions ---------------------------------------------------
|
||
|
CXTPCalendarEventsPtr prtExceptions = pPattern->GetExceptions();
|
||
|
pPattern->RemoveAllExceptions();
|
||
|
|
||
|
int nCount = prtExceptions ? prtExceptions->GetCount() : 0;
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pExc = prtExceptions->GetAt(i);
|
||
|
ASSERT(pExc);
|
||
|
if (!pExc)
|
||
|
continue;
|
||
|
|
||
|
DWORD dwNewEventID = XTP_CALENDAR_UNKNOWN_EVENT_ID;
|
||
|
if (!DoCreate_Event(pExc, dwNewEventID))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
continue;
|
||
|
}
|
||
|
ASSERT(dwNewEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
pExc->SetEventID(dwNewEventID);
|
||
|
|
||
|
pPattern->SetException(pExc);
|
||
|
}
|
||
|
//-------------------------------------------
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::_RemoveRPatternWithExceptions(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!pPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL bResult = TRUE;
|
||
|
//-- Process exceptions ---------------------------------------------------
|
||
|
CXTPCalendarEventsPtr prtExceptions = pPattern->GetExceptions();
|
||
|
|
||
|
int nCount = prtExceptions ? prtExceptions->GetCount() : 0;
|
||
|
for (int i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent *pExc = prtExceptions->GetAt(i);
|
||
|
ASSERT(pExc);
|
||
|
if (!DoDelete_Event(pExc))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
//-------------------------------------------
|
||
|
if (!DoDelete_RPattern(pPattern))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------------
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::_ChangeRPatternWithExceptions(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
if (!IsOpen())
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!pPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwPatternID = pPattern->GetPatternID();
|
||
|
//CXTPCalendarRecurrencePatternPtr ptrPatternPrev = _GetRecurrencePattern_UseCache(dwPatternID);
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPatternPrev = GetRecurrencePattern(dwPatternID);
|
||
|
|
||
|
if (!ptrPatternPrev)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------
|
||
|
VERIFY( pPattern->GetOccReminders()->Save(pPattern->GetCustomProperties(), pPattern) );
|
||
|
|
||
|
BOOL bRes = DoUpdate_RPattern(pPattern);
|
||
|
|
||
|
pPattern->GetOccReminders()->ClearProperties(pPattern->GetCustomProperties());
|
||
|
|
||
|
if (!bRes)
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
//-------------------------------------
|
||
|
|
||
|
BOOL bResult = TRUE;
|
||
|
//-- Process exceptions ---------------------------------------------------
|
||
|
CXTPCalendarEventsPtr prtExceptions_prev = ptrPatternPrev->GetExceptions();
|
||
|
CXTPCalendarEventsPtr prtExceptions_new = pPattern->GetExceptions();
|
||
|
|
||
|
//-- find deleted exceptions and remove them from DB
|
||
|
int nCount = (prtExceptions_prev && prtExceptions_new) ? prtExceptions_prev->GetCount() : 0;
|
||
|
int i;
|
||
|
for (i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pExc = prtExceptions_prev->GetAt(i);
|
||
|
DWORD dwExcID = pExc ? pExc->GetEventID() : XTP_CALENDAR_UNKNOWN_EVENT_ID;
|
||
|
int nFIndex = prtExceptions_new->Find(dwExcID);
|
||
|
if (nFIndex < 0)
|
||
|
{
|
||
|
if (!DoDelete_Event(pExc))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-- update existing or add new exceptions (int DB)
|
||
|
nCount = (prtExceptions_prev && prtExceptions_new) ? prtExceptions_new->GetCount() : 0;
|
||
|
for (i = 0; i < nCount; i++)
|
||
|
{
|
||
|
CXTPCalendarEvent* pExc = prtExceptions_new->GetAt(i);
|
||
|
if (!pExc)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
DWORD dwExcID = pExc->GetEventID();
|
||
|
|
||
|
int nFIndex = prtExceptions_prev->Find(dwExcID);
|
||
|
|
||
|
if (nFIndex < 0)
|
||
|
{
|
||
|
// Add new exception
|
||
|
DWORD dwNewEventID = XTP_CALENDAR_UNKNOWN_EVENT_ID;
|
||
|
if (!DoCreate_Event(pExc, dwNewEventID))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
continue;
|
||
|
}
|
||
|
ASSERT(dwNewEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
pExc->SetEventID(dwNewEventID);
|
||
|
|
||
|
VERIFY( pPattern->RemoveException(pExc) );
|
||
|
if (!pPattern->SetException(pExc))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Update existing exception
|
||
|
if (!DoUpdate_Event(pExc))
|
||
|
{
|
||
|
bResult = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::_ChangeRExceptionOccurrence_nf(CXTPCalendarEvent* pExcOcc, BOOL bSend_EventDeleted)
|
||
|
{
|
||
|
if (!pExcOcc)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pExcOcc->ClearIntermediateData();
|
||
|
|
||
|
DWORD dwEventID = pExcOcc->GetEventID();
|
||
|
ASSERT(dwEventID != XTP_CALENDAR_UNKNOWN_EVENT_ID);
|
||
|
|
||
|
//- new recurrence state ---------------------------
|
||
|
CXTPCalendarRecurrencePatternPtr ptrPattern;
|
||
|
|
||
|
int nRState_new = pExcOcc->GetRecurrenceState();
|
||
|
|
||
|
// - Add/Update/Remove Recurrence Exception --------------------
|
||
|
if (nRState_new != xtpCalendarRecurrenceException &&
|
||
|
nRState_new != xtpCalendarRecurrenceOccurrence)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwPatternID_new = pExcOcc->GetRecurrencePatternID();
|
||
|
//ptrPattern = _GetRecurrencePattern_UseCache(dwPatternID_new);
|
||
|
ptrPattern = GetRecurrencePattern(dwPatternID_new);
|
||
|
if (!ptrPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
DWORD dwMasterEventID = ptrPattern->GetMasterEventID();
|
||
|
//CXTPCalendarEventPtr ptrMasterEvent = _GetEvent_UseCache(dwMasterEventID);
|
||
|
CXTPCalendarEventPtr ptrMasterEvent = GetEvent(dwMasterEventID);
|
||
|
if (!ptrMasterEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
ptrPattern.SetPtr(ptrMasterEvent->GetRPatternRef(), TRUE);
|
||
|
|
||
|
if (!ptrPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
BOOL bSendPatternChangedEvent = FALSE;
|
||
|
BOOL bRes = FALSE;
|
||
|
if (nRState_new == xtpCalendarRecurrenceException)
|
||
|
{
|
||
|
bRes = ptrPattern->SetException(pExcOcc, ptrMasterEvent);
|
||
|
}
|
||
|
else if (nRState_new == xtpCalendarRecurrenceOccurrence)
|
||
|
{
|
||
|
bRes = ptrPattern->RemoveException(pExcOcc, ptrMasterEvent);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
if (bRes)
|
||
|
{
|
||
|
bRes = _ChangeRPatternWithExceptions(ptrPattern);
|
||
|
bSendPatternChangedEvent = bRes;
|
||
|
}
|
||
|
if (bRes)
|
||
|
{
|
||
|
bRes = DoUpdate_Event(ptrMasterEvent);
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------
|
||
|
if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnRepeat)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
if (m_cache.IsEventInCache(ptrMasterEvent))
|
||
|
{
|
||
|
if (m_cache.m_pCacheDP) VERIFY( m_cache.m_pCacheDP->ChangeEvent(ptrMasterEvent) );
|
||
|
}
|
||
|
}
|
||
|
else if (m_cache.m_eCacheMode == xtpCalendarDPCacheModeOnClear)
|
||
|
{
|
||
|
ASSERT(m_cache.m_pCacheDP);
|
||
|
//m_cache.m_pCacheDP->RemoveAllEvents();
|
||
|
m_cache.SafeRemoveAll();
|
||
|
}
|
||
|
//---------------------------------------------------------------------------
|
||
|
|
||
|
if (bRes)
|
||
|
{
|
||
|
XTP_NOTIFY_CODE nfCode = bSend_EventDeleted ?
|
||
|
XTP_NC_CALENDAREVENTWASDELETED : XTP_NC_CALENDAREVENTWASCHANGED;
|
||
|
SendNotification(nfCode, (WPARAM)pExcOcc->GetEventID(), (LPARAM)pExcOcc);
|
||
|
|
||
|
}
|
||
|
if (bSendPatternChangedEvent)
|
||
|
{
|
||
|
SendNotification(XTP_NC_CALENDARPATTERNWASCHANGED, ptrPattern->GetPatternID(), 0);
|
||
|
}
|
||
|
|
||
|
return bRes;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::_PostProcessOccurrencesFromMaster(COleDateTime dtDay, CXTPCalendarEvents* pEvents)
|
||
|
{
|
||
|
_PostProcessOccurrencesFromMaster2(dtDay, dtDay, pEvents);
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::_PostProcessOccurrencesFromMaster2(COleDateTime dtDayFrom, COleDateTime dtDayTo, CXTPCalendarEvents* pEvents)
|
||
|
{
|
||
|
if (!pEvents)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
int nCount = pEvents->GetCount();
|
||
|
for (int i = nCount - 1; i >= 0; i--)
|
||
|
{
|
||
|
CXTPCalendarEventPtr ptrEvent = pEvents->GetAt(i, TRUE);
|
||
|
if (!ptrEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
int nRState = ptrEvent->GetRecurrenceState();
|
||
|
if (xtpCalendarRecurrenceMaster == nRState)
|
||
|
{
|
||
|
pEvents->RemoveAt(i);
|
||
|
|
||
|
CXTPCalendarRecurrencePattern* pPattern = ptrEvent->GetRPatternRef();
|
||
|
if (!pPattern)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
VERIFY(pPattern->GetOccurrences(pEvents, dtDayFrom, dtDayTo, ptrEvent));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::_FilterDayEventsInstancesByEndTime(COleDateTime dtDay,
|
||
|
CXTPCalendarEvents* pEvents)
|
||
|
{
|
||
|
ASSERT(pEvents);
|
||
|
if (!pEvents)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
dtDay = CXTPCalendarUtils::ResetTime(dtDay);
|
||
|
|
||
|
// filter events;
|
||
|
int nCount = pEvents->GetCount();
|
||
|
for (int i = nCount-1; i >= 0; i--)
|
||
|
{
|
||
|
CXTPCalendarEvent* pEvent = pEvents->GetAt(i);
|
||
|
if (!pEvent)
|
||
|
{
|
||
|
ASSERT(FALSE);
|
||
|
continue;
|
||
|
}
|
||
|
if (pEvent->GetRecurrenceState() == xtpCalendarRecurrenceMaster)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (CXTPCalendarUtils::ResetTime(pEvent->GetStartTime()) < dtDay &&
|
||
|
CXTPCalendarUtils::IsEqual(pEvent->GetEndTime(), dtDay) )
|
||
|
{
|
||
|
pEvents->RemoveAt(i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CXTPCalendarData::SendNotification(XTP_NOTIFY_CODE EventCode, WPARAM wParam , LPARAM lParam)
|
||
|
{
|
||
|
if (m_pConnection && !m_bDisableNotificationsSending)
|
||
|
{
|
||
|
m_pConnection->SendEvent(EventCode, wParam, lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::GetUpcomingEvents(COleDateTime dtFrom, COleDateTimeSpan spPeriod)
|
||
|
{
|
||
|
CXTPCalendarEventsPtr ptrEvents = DoGetUpcomingEvents(dtFrom, spPeriod);
|
||
|
|
||
|
_PostProcessRecurrenceIfNeed(ptrEvents);
|
||
|
return ptrEvents;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::GetAllEvents_raw()
|
||
|
{
|
||
|
CXTPCalendarEventsPtr ptrEvents = DoGetAllEvents_raw();
|
||
|
|
||
|
_PostProcessRecurrenceIfNeed(ptrEvents);
|
||
|
return ptrEvents;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::SetOptionsToUpdate(CXTPCalendarOptions* pOptions)
|
||
|
{
|
||
|
CMDTARGET_ADDREF(pOptions);
|
||
|
CMDTARGET_RELEASE(m_pCalendarOptions);
|
||
|
m_pCalendarOptions = pOptions;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::DoGetAllEvents_raw()
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::DoGetUpcomingEvents(
|
||
|
COleDateTime dtFrom, COleDateTimeSpan spPeriod)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(dtFrom); UNREFERENCED_PARAMETER(spPeriod);
|
||
|
//return DoRetrieveAllEvents_raw();
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventsPtr CXTPCalendarData::DoRetrieveDayEvents(COleDateTime dtDay)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(dtDay);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
void CXTPCalendarData::DoRemoveAllEvents()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
CXTPCalendarEventPtr CXTPCalendarData::DoRead_Event(DWORD dwEventID)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(dwEventID);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarRecurrencePatternPtr CXTPCalendarData::DoRead_RPattern(DWORD dwPatternID)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(dwPatternID);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoCreate_Event(CXTPCalendarEvent* pEvent, DWORD& rdwNewEventID)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pEvent);
|
||
|
UNREFERENCED_PARAMETER(rdwNewEventID);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoUpdate_Event(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pEvent);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoDelete_Event(CXTPCalendarEvent* pEvent)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pEvent);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoCreate_RPattern(CXTPCalendarRecurrencePattern* pPattern, DWORD& rdwNewPatternID)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pPattern);
|
||
|
UNREFERENCED_PARAMETER(rdwNewPatternID);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoUpdate_RPattern(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pPattern);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL CXTPCalendarData::DoDelete_RPattern(CXTPCalendarRecurrencePattern* pPattern)
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(pPattern);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
CString CXTPCalendarData::DataSourceFromConStr(LPCTSTR lpszConnectionString)
|
||
|
{
|
||
|
ASSERT(lpszConnectionString);
|
||
|
|
||
|
if (!lpszConnectionString || 0 == _tcslen(lpszConnectionString))
|
||
|
return _T("");
|
||
|
|
||
|
CString strConnStr_lower = lpszConnectionString;
|
||
|
strConnStr_lower.MakeLower();
|
||
|
|
||
|
int nIndex = strConnStr_lower.Find(_T("data source="));
|
||
|
if (nIndex != -1)
|
||
|
{
|
||
|
CString strDataSource = strConnStr_lower.Mid(nIndex + 12);
|
||
|
if (strDataSource.IsEmpty())
|
||
|
return _T("");
|
||
|
|
||
|
if ((strDataSource[0] == _T('\'') || strDataSource[0] == _T('"')) && strDataSource.GetLength() > 2)
|
||
|
{
|
||
|
TCHAR chQuot = strDataSource[0];
|
||
|
|
||
|
strDataSource.Delete(0);
|
||
|
|
||
|
int nQuot2Idx = strDataSource.Find(chQuot, 0);
|
||
|
|
||
|
if (nQuot2Idx >= 0)
|
||
|
{
|
||
|
strDataSource.Delete(nQuot2Idx, strDataSource.GetLength() - nQuot2Idx);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return strDataSource;
|
||
|
}
|
||
|
|
||
|
return strConnStr_lower;
|
||
|
}
|
||
|
|
||
|
XTPCalendarDataProvider CXTPCalendarData::DataProviderTypeFromConStr(
|
||
|
LPCTSTR lpszConnectionString,
|
||
|
XTPCalendarDataProvider eDPDefault)
|
||
|
{
|
||
|
ASSERT(lpszConnectionString);
|
||
|
|
||
|
if (!lpszConnectionString)
|
||
|
{
|
||
|
return eDPDefault;
|
||
|
}
|
||
|
|
||
|
CString strConnStr_lower(lpszConnectionString);
|
||
|
strConnStr_lower.MakeLower();
|
||
|
|
||
|
BOOL bProviderCustom = strConnStr_lower.Find(_T("provider=custom")) != -1;
|
||
|
if (bProviderCustom)
|
||
|
{
|
||
|
return xtpCalendarDataProviderCustom;
|
||
|
}
|
||
|
|
||
|
BOOL bProviderMAPI = strConnStr_lower.Find(_T("provider=mapi")) != -1;
|
||
|
if (bProviderMAPI)
|
||
|
{
|
||
|
return xtpCalendarDataProviderMAPI;
|
||
|
}
|
||
|
|
||
|
BOOL bProviderXML = strConnStr_lower.Find(_T("provider=xml")) != -1;
|
||
|
if (bProviderXML)
|
||
|
{
|
||
|
return xtpCalendarDataProviderMemory;
|
||
|
}
|
||
|
|
||
|
BOOL bProvider = strConnStr_lower.Find(_T("provider=")) != -1;
|
||
|
BOOL bDSN = strConnStr_lower.Find(_T("dsn=")) != -1;
|
||
|
if (bProvider || bDSN)
|
||
|
{
|
||
|
return xtpCalendarDataProviderDatabase;
|
||
|
}
|
||
|
|
||
|
return eDPDefault;
|
||
|
}
|
||
|
|
||
|
CXTPCalendarData* CXTPCalendarData::CreateDataProvider(LPCTSTR lpszConnectionString)
|
||
|
{
|
||
|
ASSERT(lpszConnectionString);
|
||
|
|
||
|
if (!lpszConnectionString)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
XTPCalendarDataProvider eDPType = DataProviderTypeFromConStr(lpszConnectionString, xtpCalendarDataProviderMemory);
|
||
|
|
||
|
CXTPCalendarData* pDataProvider = CreateDataProvider(eDPType);
|
||
|
|
||
|
if (pDataProvider)
|
||
|
{
|
||
|
pDataProvider->SetConnectionString(lpszConnectionString);
|
||
|
}
|
||
|
return pDataProvider;
|
||
|
}
|
||
|
|
||
|
|
||
|
CXTPCalendarData* CXTPCalendarData::CreateDataProvider(XTPCalendarDataProvider eDataProvider)
|
||
|
{
|
||
|
CXTPCalendarData* pDataProvider = NULL;
|
||
|
switch (eDataProvider)
|
||
|
{
|
||
|
case xtpCalendarDataProviderMemory:
|
||
|
pDataProvider = new CXTPCalendarMemoryDataProvider();
|
||
|
break;
|
||
|
case xtpCalendarDataProviderDatabase:
|
||
|
pDataProvider = new CXTPCalendarDatabaseDataProvider();
|
||
|
break;
|
||
|
case xtpCalendarDataProviderMAPI:
|
||
|
pDataProvider = new CXTPCalendarMAPIDataProvider();
|
||
|
break;
|
||
|
case xtpCalendarDataProviderCustom:
|
||
|
pDataProvider = new CXTPCalendarCustomDataProvider();
|
||
|
break;
|
||
|
default:
|
||
|
ASSERT(FALSE);
|
||
|
}
|
||
|
|
||
|
return pDataProvider;
|
||
|
}
|
||
|
|