harvesterplugins/calendar/src/ccalendarplugin.cpp
changeset 0 ccd0fd43f247
child 2 208a4ba3894c
--- /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