--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/harvesterplugins/calendar/src/ccalendarplugin.cpp Mon Apr 19 14:40:05 2010 +0300
@@ -0,0 +1,538 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+ *
+*/
+
+#include "ccalendarplugin.h"
+#include "harvesterserverlogger.h"
+#include <common.h>
+#include <csearchdocument.h>
+
+#include <ccpixindexer.h>
+#include <e32base.h>
+#include <calsession.h>
+#include <calentry.h>
+#include <caliterator.h>
+#include <calentryview.h>
+#include <mmfcontrollerpluginresolver.h> // CleanupResetAndDestroyPushL
+
+_LIT(KMimeTypeField, CPIX_MIMETYPE_FIELD);
+_LIT(KMimeTypeCalendar, CALENDAR_MIMETYPE);
+
+_LIT(KExcerptDelimiter, " ");
+
+/** The delay between harvesting chunks. */
+const TInt KHarvestingDelay = 2000;
+
+_LIT(KCalendarTimeFormat,"%F%/0%Y%M%D%H%T"); // Locale independent YYYYMMDDHHSS
+
+// ---------------------------------------------------------------------------
+// CMessagePlugin::NewL
+// ---------------------------------------------------------------------------
+//
+CCalendarPlugin* CCalendarPlugin::NewL()
+ {
+ CCalendarPlugin* instance = CCalendarPlugin::NewLC();
+ CleanupStack::Pop(instance);
+ return instance;
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::NewLC
+// ---------------------------------------------------------------------------
+//
+CCalendarPlugin* CCalendarPlugin::NewLC()
+ {
+ CCalendarPlugin* instance = new (ELeave) CCalendarPlugin();
+ CleanupStack::PushL(instance);
+ instance->ConstructL();
+ return instance;
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::CCalendarPlugin
+// ---------------------------------------------------------------------------
+//
+CCalendarPlugin::CCalendarPlugin()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::~CCalendarPlugin
+// ---------------------------------------------------------------------------
+//
+CCalendarPlugin::~CCalendarPlugin()
+ {
+ if (iAsynchronizer)
+ iAsynchronizer->CancelCallback();
+ delete iAsynchronizer;
+ delete iIndexer;
+
+ delete iEntryView;
+ delete iCalIterator;
+ if( iSession )
+ {
+ iSession->StopChangeNotification();
+ }
+ delete iSession;
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::ConstructL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::ConstructL()
+ {
+ iAsynchronizer = CDelayedCallback::NewL( CActive::EPriorityIdle );
+ iSession = CCalSession::NewL();
+ TRAPD ( err , iSession->OpenL( iSession->DefaultFileNameL() ) );
+ if ( err == KErrNotFound)
+ {
+ iSession->CreateCalFileL( iSession->DefaultFileNameL() );
+ iSession->OpenL( iSession->DefaultFileNameL() );
+ }
+ iCalIterator = CCalIter::NewL( *iSession );
+ iEntryView = CCalEntryView::NewL( *iSession, *this );
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::StartPluginL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::StartPluginL()
+ {
+ // Define this base application class, use default location
+ User::LeaveIfError(iSearchSession.DefineVolume( _L(CALENDAR_QBASEAPPCLASS), KNullDesC ));
+
+ // Open the database
+ iIndexer = CCPixIndexer::NewL(iSearchSession);
+ iIndexer->OpenDatabaseL( _L(CALENDAR_QBASEAPPCLASS) );
+
+ // Start harvester for this plugin
+ iObserver->AddHarvestingQueue(this, iIndexer->GetBaseAppClass());
+
+ // Start monitoring calendar events
+ TTime startTime( TDateTime( 1980, EJanuary, 0, 0, 0, 0, 0 ) );
+ TTime endTime( startTime + TTimeIntervalYears( 40 ) );
+ TCalTime startTimeCal;
+ TCalTime endTimeCal;
+ startTimeCal.SetTimeUtcL( startTime );
+ endTimeCal.SetTimeUtcL( endTime );
+ CCalChangeNotificationFilter* filter = CCalChangeNotificationFilter::NewL( MCalChangeCallBack2::EChangeEntryAll, ETrue, CalCommon::TCalTimeRange( startTimeCal, endTimeCal ) );
+ iSession->StartChangeNotification( *this, *filter );
+ delete filter;
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::StartHarvestingL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::StartHarvestingL(const TDesC& /*aQualifiedBaseAppClass*/)
+ {
+ iIndexer->ResetL();
+ iStartHarvesting = ETrue;
+#ifdef __PERFORMANCE_DATA
+ iStartTime.UniversalTime();
+#endif
+ if (iFirstEntry)
+ {
+ iAsynchronizer->Start( 0, this, KHarvestingDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCalendarPlugin::Progress
+// -----------------------------------------------------------------------------
+//
+void CCalendarPlugin::Progress( TInt /*aPercentageCompleted*/ )
+ {
+ // No implementation needed
+ }
+
+// -----------------------------------------------------------------------------
+// CCalendarPlugin::Completed
+// -----------------------------------------------------------------------------
+//
+void CCalendarPlugin::Completed( TInt aError )
+ {
+ // No error code and harvesting is needed star harvesting.
+ iFirstEntry = ETrue;
+ if (aError == KErrNone && iStartHarvesting)
+ {
+ // Calendar entry view constructed successfully, start harvesting
+ iAsynchronizer->Start( 0, this, KHarvestingDelay );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CCalendarPlugin::NotifyProgress
+// -----------------------------------------------------------------------------
+//
+TBool CCalendarPlugin::NotifyProgress()
+ {
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CContactsPlugin::DelayedCallbackL
+// -----------------------------------------------------------------------------
+//
+void CCalendarPlugin::DelayedCallbackL( TInt /*aCode*/ )
+ {
+ // Harvest items on each call
+ TPtrC8 uid( KNullDesC8 );
+
+ if( iFirstEntry )
+ {
+ uid.Set( iCalIterator->FirstL() );
+ iFirstEntry = EFalse;
+ }
+ else
+ {
+ uid.Set( iCalIterator->NextL() );
+ }
+
+ if( uid != KNullDesC8 )
+ {
+ RPointerArray<CCalEntry> entryArray;
+ CleanupResetAndDestroyPushL(entryArray);
+ iEntryView->FetchL( uid, entryArray );
+ // Handle only the first (i.e. parent entry)
+ if( entryArray.Count() > 0 )
+ {
+ CCalEntry* entry = (CCalEntry*)entryArray[ 0 ];
+ CPIXLOGSTRING2("CCalendarPlugin::DelayedCallbackL(): Harvesting id=%d.", entry->LocalUidL());
+ CreateEntryL( entry->LocalUidL(), ECPixAddAction );
+ }
+ CleanupStack::PopAndDestroy(&entryArray);
+
+ // Request next entry.
+ iAsynchronizer->Start( 0, this, KHarvestingDelay );
+ }
+ else
+ {
+ // Harvesting was successfully completed
+ iFirstEntry = ETrue; // Make sure we can harvest next time as well...
+ Flush(*iIndexer);
+#ifdef __PERFORMANCE_DATA
+ UpdatePerformaceDataL();
+#endif
+ iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), KErrNone);
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::DelayedError
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::DelayedError(TInt aError)
+ {
+ // Harvesting was completed
+ iFirstEntry = ETrue; // Make sure we can harvest next time as well...
+ Flush(*iIndexer);
+ iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), aError);
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::CalChangeNotification
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::CalChangeNotification( RArray< TCalChangeEntry >& aChangeItems )
+ {
+ const TInt count(aChangeItems.Count());
+ CPIXLOGSTRING2("CCalendarPlugin::CalChangeNotification(): changed item count =%d.", count);
+ for( TInt i = 0; i < count; ++i )
+ {
+ TCalChangeEntry changedEntry = aChangeItems[ i ];
+ TRAP_IGNORE(HandleChangedEntryL(changedEntry));
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::HandleChangedEntryL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::HandleChangedEntryL(const TCalChangeEntry& changedEntry)
+ {
+ switch( changedEntry.iChangeType )
+ {
+ case EChangeAdd:
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::HandleChangedEntryL(): Monitored add id=%d.", changedEntry.iEntryId);
+#ifdef __PERFORMANCE_DATA
+ iStartTime.UniversalTime();
+ CreateEntryL( changedEntry.iEntryId, ECPixAddAction );
+ UpdatePerformaceDataL(ECPixAddAction);
+#else
+ CreateEntryL( changedEntry.iEntryId, ECPixAddAction );
+#endif
+ break;
+ }
+
+ case EChangeDelete:
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::HandleChangedEntryL(): Monitored delete id=%d.", changedEntry.iEntryId);
+#ifdef __PERFORMANCE_DATA
+ iStartTime.UniversalTime();
+ CreateEntryL( changedEntry.iEntryId, ECPixAddAction );
+ UpdatePerformaceDataL(ECPixAddAction);
+#else
+ CreateEntryL( changedEntry.iEntryId, ECPixRemoveAction );
+#endif
+ break;
+ }
+
+ case EChangeModify:
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::HandleChangedEntryL(): Monitored update id=%d.", changedEntry.iEntryId);
+#ifdef __PERFORMANCE_DATA
+ iStartTime.UniversalTime();
+ CreateEntryL( changedEntry.iEntryId, ECPixUpdateAction );
+ UpdatePerformaceDataL(ECPixUpdateAction);
+#else
+ CreateEntryL( changedEntry.iEntryId, ECPixUpdateAction );
+#endif
+ break;
+ }
+
+ /* TCalChangeEntry documentation:
+ If iChangeType is EChangeUndefined or EChangeOverflowError, iEntryId and
+ iEntryType are undefined and should not be used by clients.
+ */
+ case EChangeUndefined:
+ {
+ CPIXLOGSTRING("CCalendarPlugin::HandleChangedEntryL(): EChangeUndefined.");
+ // This event could be related to synchronization.
+ // Mark harvesting as cancelled.
+ // Remove it from the harvesting queue to cause it to enter
+ // EHarvesterStatusHibernate state.
+ // Now add it to the harvesting queue and force a reharvest.
+
+ iFirstEntry = ETrue; // Make sure we can harvest next time as well...
+ Flush(*iIndexer);
+ iObserver->HarvestingCompleted(this, iIndexer->GetBaseAppClass(), KErrCancel);
+ iObserver->RemoveHarvestingQueue(this, iIndexer->GetBaseAppClass());
+ iObserver->AddHarvestingQueue(this, iIndexer->GetBaseAppClass(), ETrue);
+ break;
+ }
+ default:
+ // Ignore other events
+ break;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::CreateEntryL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::CreateEntryL( const TCalLocalUid& aLocalUid, TCPixActionType aActionType )
+ {
+ if (!iIndexer)
+ return;
+
+ CPIXLOGSTRING2("CCalendarPlugin::CreateEntryL(): Uid = %d.", aLocalUid);
+
+ // creating CSearchDocument object with unique ID for this application
+ TBuf<20> docid_str;
+ docid_str.AppendNum(aLocalUid);
+
+ if (aActionType == ECPixAddAction || aActionType == ECPixUpdateAction)
+ {
+ CSearchDocument* index_item = CSearchDocument::NewLC(docid_str, _L(CALENDARAPPCLASS));
+
+ // Return the entry that has been fetched, this will be NULL if there are
+ // no entries with the cal unique id
+ CCalEntry* entry = iEntryView->FetchL(aLocalUid);
+ // TODO leave if entry is NULL
+ CleanupStack::PushL(entry);
+ // TODO Uncomment below portion of code when the latest Organiser code in MCL
+ if( CCalEntry::ENote == entry->EntryTypeL() )
+ {
+ CleanupStack::PopAndDestroy(entry);
+ CleanupStack::PopAndDestroy(index_item);
+ CPIXLOGSTRING("CCalendarPlugin::CreateEntryL(): Donot harvest Note item.");
+ return;
+ }
+
+ // Add fields
+ index_item->AddFieldL(KCalendarSummaryField, entry->SummaryL());
+ index_item->AddFieldL(KCalendarDescriptionField, entry->DescriptionL());
+ index_item->AddFieldL(KCalendarLocationField, entry->LocationL());
+
+ TBuf<30> dateString;
+
+ TTime startTime = entry->StartTimeL().TimeUtcL();
+ startTime.FormatL(dateString, KCalendarTimeFormat);
+ index_item->AddFieldL(KCalendarStartTimeField, dateString, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);
+
+ TTime endTime = entry->EndTimeL().TimeUtcL();
+ endTime.FormatL(dateString, KCalendarTimeFormat);
+ index_item->AddFieldL(KCalendarEndTimeField, dateString, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);
+
+ index_item->AddFieldL(KMimeTypeField, KMimeTypeCalendar, CDocumentField::EStoreYes | CDocumentField::EIndexUnTokenized);
+
+ TInt excerptLength = 3 + entry->SummaryL().Length() + entry->DescriptionL().Length() + entry->LocationL().Length();
+ HBufC* excerpt = HBufC::NewLC(excerptLength);
+ TPtr excerptDes = excerpt->Des();
+ excerptDes.Copy(entry->SummaryL());
+ excerptDes.Append(KExcerptDelimiter);
+ excerptDes.Append(entry->DescriptionL());
+ excerptDes.Append(KExcerptDelimiter);
+ excerptDes.Append(entry->LocationL());
+
+ index_item->AddExcerptL(*excerpt);
+ CleanupStack::PopAndDestroy(excerpt);
+ CleanupStack::PopAndDestroy(entry);
+
+ /*
+ RPointerArray<CCalAttendee>& attendees = iEntry.AttendeesL();
+ for( TInt i = 0; i < attendees.Count(); i++ )
+ {
+ CCalAttendee* attendee = (CCalAttendee*)attendees[ i ];
+ TInt err = KErrNone;
+ TRAP( err, AddContent( CIndexContent::NewL( attendee->CommonName(), ECalendarAttendee ) ) );
+ }
+ attendees.ResetAndDestroy();
+ */
+
+ // Send for indexing
+ if (aActionType == ECPixAddAction)
+ {
+ TRAPD(err, iIndexer->AddL(*index_item));
+ if (err == KErrNone)
+ {
+ CPIXLOGSTRING("CCalendarPlugin::CreateEntryL(): Added.");
+ }
+ else
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::CreateEntryL(): Error %d in adding.", err);
+ }
+ }
+ else if (aActionType == ECPixUpdateAction)
+ {
+ TRAPD(err, iIndexer->UpdateL(*index_item));
+ if (err == KErrNone)
+ {
+ CPIXLOGSTRING("CCalendarPlugin::CreateEntryL(): Updated.");
+ }
+ else
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::CreateEntryL(): Error %d in updating.", err);
+ }
+ }
+ CleanupStack::PopAndDestroy(index_item);
+ }
+ else if (aActionType == ECPixRemoveAction)
+ {
+ TRAPD(err, iIndexer->DeleteL(docid_str));
+ if (err == KErrNone)
+ {
+ CPIXLOGSTRING("CCalendarPlugin::CreateEntryL(): Deleted.");
+ }
+ else
+ {
+ CPIXLOGSTRING2("CCalendarPlugin::CreateEntryL(): Error %d in deleting.", err);
+ }
+ }
+
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::UpdatePerformaceDataL
+// ---------------------------------------------------------------------------
+//
+#ifdef __PERFORMANCE_DATA
+void CCalendarPlugin::UpdatePerformaceDataL()
+ {
+ TTime now;
+
+
+ iCompleteTime.UniversalTime();
+ TTimeIntervalMicroSeconds timeDiff = iCompleteTime.MicroSecondsFrom(iStartTime);
+
+ RFs fileSession;
+ RFile perfFile;
+ User::LeaveIfError( fileSession.Connect () );
+
+
+ /* Open file if it exists, otherwise create it and write content in it */
+
+ if(perfFile.Open(fileSession, _L("c:\\data\\CalenderPerf.txt"), EFileWrite))
+ User::LeaveIfError(perfFile.Create (fileSession, _L("c:\\data\\CalenderPerf.txt"), EFileWrite));
+
+ HBufC8 *heap = HBufC8::NewL(100);
+ TPtr8 ptr = heap->Des();
+ now.HomeTime();
+ TBuf<50> timeString;
+
+ _LIT(KOwnTimeFormat,"%:0%H%:1%T%:2%S");
+ now.FormatL(timeString,KOwnTimeFormat);
+ ptr.AppendNum(now.DateTime().Day());
+ ptr.Append(_L("/"));
+ ptr.AppendNum(now.DateTime().Month());
+ ptr.Append(_L("/"));
+ ptr.AppendNum(now.DateTime().Year());
+ ptr.Append(_L(":"));
+ ptr.Append(timeString);
+ ptr.Append( _L("Time taken for Harvesting Calendar is : "));
+ ptr.AppendNum(timeDiff.Int64()/1000) ;
+ ptr.Append(_L(" MilliSeonds \n"));
+ TInt myInt = 0;
+ perfFile.Seek(ESeekEnd,myInt);
+ perfFile.Write (ptr);
+ perfFile.Close ();
+ fileSession.Close ();
+ delete heap;
+ }
+
+// ---------------------------------------------------------------------------
+// CCalendarPlugin::UpdatePerformaceDataL
+// ---------------------------------------------------------------------------
+//
+void CCalendarPlugin::UpdatePerformaceDataL(TCPixActionType action)
+ {
+
+ iCompleteTime.UniversalTime();
+ TTimeIntervalMicroSeconds timeDiff = iCompleteTime.MicroSecondsFrom(iStartTime);
+
+ RFs fileSession;
+ RFile perfFile;
+ User::LeaveIfError( fileSession.Connect () );
+
+
+ /* Open file if it exists, otherwise create it and write content in it */
+
+ if(perfFile.Open(fileSession, _L("c:\\data\\CalenderPerf.txt"), EFileWrite))
+ User::LeaveIfError(perfFile.Create (fileSession, _L("c:\\data\\CalenderPerf.txt"), EFileWrite));
+
+ HBufC8 *heap = HBufC8::NewL(100);
+ TPtr8 ptr = heap->Des();
+
+ switch (action) {
+ case ECPixAddAction: ptr.Append( _L("add "));break;
+ case ECPixUpdateAction: ptr.Append( _L("upd "));break;
+ case ECPixRemoveAction: ptr.Append( _L("del "));break;
+ }
+ ptr.AppendNum(timeDiff.Int64()/1000) ;
+ ptr.Append(_L("\n"));
+ TInt myInt = 0;
+ perfFile.Seek(ESeekEnd,myInt);
+ perfFile.Write (ptr);
+ perfFile.Close ();
+ fileSession.Close ();
+ delete heap;
+ }
+#endif
+// End of file