pimprotocols/pbap/server/pbapfoldernodech.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 10:12:17 +0200
changeset 0 e686773b3f54
permissions -rw-r--r--
Revision: 201003 Kit: 201005

// Copyright (c) 2006-2009 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 "pbapfoldernodech.h"
#include "pbapfolderclient.h"
#include "pbaperrorreporter.h"
#include "pbapappheader.h"
#include "pbapserver.h"
#include "pbapchview.h"
#include "pbapchexporter.h"

#include "btaccesshostlog.h"


// constants
_LIT(KFolderIch, "ich");
_LIT(KFolderOch, "och");
_LIT(KFolderMch, "mch");
_LIT(KFolderCch, "cch");


CFolderNodeCallHistory::CFolderNodeCallHistory(MVirtualFolderClient& aClient, const TDesC& aFolderName, THistoryType aHistoryType)
: CFolderNode(aClient, aFolderName), iHistoryType(aHistoryType), iPendingExport(ENoExport)
	{
	LOG_FUNC
	}

// must be called by any class that inherits from CFolderNodeCallHistory
void CFolderNodeCallHistory::ConstructL()
	{
	LOG_FUNC
	
	// create the view for this folder node
	iFolderView = CPbapChView::NewL(iClient.LogClient(), iHistoryType, *this, KLogNullFlags);	
	}
	
CFolderNodeCallHistory::~CFolderNodeCallHistory()
	{
	LOG_FUNC
	
	delete iAsyncExporter;
	delete iFolderView;
	delete iReadFolderView;
 	}


void CFolderNodeCallHistory::CancelGet()
	{
	LOG_FUNC
 	
	// cancel any asynchronous export operations and avoid iAsyncExporter is deleted
	// by itself
	CPbapChExporter* tmpExporter = iAsyncExporter;
	iAsyncExporter = NULL;
	delete tmpExporter;
	
	delete iAppHeader;
	iAppHeader = NULL;		
	}

void CFolderNodeCallHistory::GetComplete()
	{
	LOG_FUNC
	
	if (iAsyncExporter)
		{
		delete iAsyncExporter;
		iAsyncExporter = NULL;
		}
	}

TInt CFolderNodeCallHistory::DoExport(TExportType aExportType, TInt aHandle)
	{
	LOG_FUNC
	
	if(iAsyncExporter)
		{
		__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderChExportAlreadyExists));
		return KErrAlreadyExists;
		}
	

	TInt err = KErrNone;
		
	if ((aExportType == EExportItem) && (iCallHistoryChanged))
		{
		// the Call History db has been modified since the last get request
		// report precondition failed error to obex until next listing
		// request completes (or new Pbap session initiated)
		iClient.ErrorReporter().SendPreconditionFailedError();
		// error already reported above so don't update error

		delete iAppHeader;
		iAppHeader = NULL;
		}
	else if (iReadyToExport)
		{
		err = StartExport(aExportType, aHandle);
		}
	else
		{
		// views not ready, setup a pending export until they are
		if(iPendingExport != ENoExport)
			{
			__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderExportAlreadyPending));
			return KErrAlreadyExists;
			}

		if (!iFolderView)
			{
			// creating the folder view failed before, try again
			TRAP(err, iFolderView = CPbapChView::NewL(iClient.LogClient(), iHistoryType, *this, KLogNullFlags));
			}
		
		// setup this export as pending until we are ready to export
		if (err == KErrNone)
			{
			iPendingExport = aExportType;
			iPendingHandle = aHandle;
			}
		}
	return err;	
	}

TInt CFolderNodeCallHistory::DoGetItem(TInt aHandle)
	{
	LOG_FUNC
	return DoExport(EExportItem, aHandle);
	}
	
TInt CFolderNodeCallHistory::DoGetListing()
	{
	LOG_FUNC
	return DoExport(EExportListing);
	}

TInt CFolderNodeCallHistory::DoGetCount()
	{
	LOG_FUNC
	return DoExport(EExportCount);
	}

TInt CFolderNodeCallHistory::DoGetFolder()
	{
	LOG_FUNC
	return DoExport(EExportFolder);
	}

 void CFolderNodeCallHistory::HandleExportComplete(TInt aError)
 	{
 	LOG_FUNC
 		
 	if (aError == KErrNotFound && iAppHeader->Operation() == EPullVCard)
 		{
 		// must report not found to client if attempting to pull a vCard which
 		// doesnot exist
 		iClient.ErrorReporter().SendNotFoundError();
 		}
 	else if (aError && iCallHistoryChanged)
 		{
 		iClient.ErrorReporter().SendPreconditionFailedError();
 		}
 	else if (aError)
 		{
 		// error occured during export report service unavailable error to obex 
 		iClient.ErrorReporter().SendServiceUnavailableError();
 		}
 
  	// a successful listing request allows the ch entries to be pulled again
 	// after the database has been modified
 	if (aError == KErrNone && iAppHeader->Operation() == EPullVCardListing)
 		{
 		iCallHistoryChanged = EFalse;
 		}
	
	delete iAppHeader;
	iAppHeader = NULL;
 	}


void CFolderNodeCallHistory::CancelPendingExport(TInt err)
	{
	LOG_FUNC

	if (iPendingExport != ENoExport)
		{
		// complete the export with an error
		HandleExportComplete(err);
		
		// pending export done
		iPendingExport = ENoExport;
		}
	}

TInt CFolderNodeCallHistory::StartExport(TExportType aExportType, TInt aHandle)
	{
	LOG_FUNC
	
	if(iAsyncExporter)
		{
		__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderChExportAlreadyExists));
		return KErrAlreadyExists;
		}
	if(iReadyToExport == EFalse)
		{
		__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderNotReadyToExport));
		return KErrNotReady;
		}
	if(!iFolderView)
		{
		__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderIncompleteViews));
		return KErrNotFound;
		}
	
	TInt err = KErrNone;
	
	switch(aExportType)
		{
		case EExportItem:
			// aHandle is decremented here as the PBAP handles for call histories start at 1 and our event index starts at 0
			TRAP(err, iAsyncExporter = CPbapChSingleItemExporter::NewL(iClient, *this, *iFolderView, aHandle - 1, iAppHeader->VCardVersion(), iAppHeader->Filter()));			
			break;

		case EExportListing:
			TRAP(err, iAsyncExporter = CPbapChListingExporter::NewL(iClient, *this, *iFolderView, iReadFolderView, iAppHeader->ListStartOffset(), iAppHeader->MaxListCount()));
			break;
		
		case EExportCount:
			TRAP(err, iAsyncExporter = CPbapChCountExporter::NewL(iClient, *this, *iFolderView, iReadFolderView));
			break;
			
		case EExportFolder:
			TRAP(err, iAsyncExporter = CPbapChItemExporter::NewL(iClient, *this, *iFolderView, iReadFolderView, iAppHeader->ListStartOffset(), iAppHeader->MaxListCount(), iAppHeader->VCardVersion(), iAppHeader->Filter()));
			break;
			
		case ENoExport:
			// nothing to do
			break;
		default:
			break;			
		}
	return err;
	}
	
// From MPbapChViewObserver.
void CFolderNodeCallHistory::CallHistoryViewReady(TInt aError)
	{
	LOG_FUNC

	if(aError != KErrNone)
		{
		__ASSERT_DEBUG(EFalse, Panic(EVirtualFolderIncompleteViews));
		}

	// assume we are ready to export unless we determine otherwise
	iReadyToExport = ETrue;
	
	// make sure that we have all the view required to be able to export
	if ((aError == KErrNone) && (iHistoryType == EMissed) && (!iReadFolderView))
		{
		// create view of read missed events, used to determine the number of unread events
		TRAP(aError, iReadFolderView  = CPbapChView::NewL(iClient.LogClient(), iHistoryType, *this, KLogEventRead));

		if (aError == KErrNone)
			{
			// we will be notified again when the read missed events view is ready so wait for
			// that notification before we are ready to export
			iReadyToExport = EFalse;
			}
		else
			{
			// log error but still allow exports to take place, they will just not include the
			// new unread event count in any export
			LOG1(_L("Failed to create read missed call view, error: %d"), aError);
			}
		}
	else if (aError != KErrNone)
		{
		if (iReadFolderView)
			{
			// log error but still allow exports to take place, they will just not include the
			// new unread event count in any export
			LOG1(_L("Failed to create read missed call view, error: %d"), aError);
			
			delete iReadFolderView;
			iReadFolderView = NULL;
			}
		else
			{
			// log error and attempt to create views again on next export
			LOG1(_L("Failed to create folder call history view, error: %d"), aError);
			
			delete iFolderView;
			iFolderView = NULL;

			iReadyToExport = EFalse;
			CancelPendingExport(aError);
			}
		}
		
	// check for any pending exports
	if ((iReadyToExport) && (iPendingExport != ENoExport))
		{
		aError = StartExport(iPendingExport, iPendingHandle);
		
		if (aError != KErrNone)
			{
			// complete the export with an error
			HandleExportComplete(aError);
			}
	
		// pending export done
		iPendingExport = ENoExport;
		}
	}
	
void CFolderNodeCallHistory::CallHistoryChangeNotification(TBool aViewReady)
	{
	LOG_FUNC
	
	// Force the PCE to issue a PullvCardListing before we will respond to another
	// PullvCardEntry request for this folder
	iCallHistoryChanged = ETrue;

	// check to see if there is an export in progress
	if (iAsyncExporter)
		{
		// cancel the export and report error according to the error reporting
		// scheme for modified/deleted handles
		CancelGet();
		}
	
	// the view may need refreshing after a change and therefore we are ready to 
	// export if the view is ready to use. If not, then we will get notification
	// via the CallHistoryViewReady callback
	iReadyToExport = aViewReady;
	}


//
// CFolderNodeIch
//
/*static*/ CFolderNodeIch* CFolderNodeIch::NewL(MVirtualFolderClient& aClient)
	{
	LOG_STATIC_FUNC
	CFolderNodeIch* self = new (ELeave) CFolderNodeIch(aClient);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CFolderNodeIch::CFolderNodeIch(MVirtualFolderClient& aClient)
: CFolderNodeCallHistory(aClient, KFolderIch(), EIncoming)
	{
	LOG_FUNC
	}	
	
	
//
// CFolderNodeOch
//
/*static*/ CFolderNodeOch* CFolderNodeOch::NewL(MVirtualFolderClient& aClient)
	{
	LOG_STATIC_FUNC
	CFolderNodeOch* self = new (ELeave) CFolderNodeOch(aClient);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CFolderNodeOch::CFolderNodeOch(MVirtualFolderClient& aClient)
: CFolderNodeCallHistory(aClient, KFolderOch(), EOutgoing)
	{
	LOG_FUNC
	}
	
	
//
// CFolderNodeMch
//
/*static*/ CFolderNodeMch* CFolderNodeMch::NewL(MVirtualFolderClient& aClient)
	{
	LOG_STATIC_FUNC
	CFolderNodeMch* self = new (ELeave) CFolderNodeMch(aClient);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CFolderNodeMch::CFolderNodeMch(MVirtualFolderClient& aClient)
: CFolderNodeCallHistory(aClient, KFolderMch(), EMissed)
	{
	LOG_FUNC
	}
	
			
//
// CFolderNodeCch
//
/*static*/ CFolderNodeCch* CFolderNodeCch::NewL(MVirtualFolderClient& aClient)
	{
	LOG_STATIC_FUNC
	CFolderNodeCch* self = new (ELeave) CFolderNodeCch(aClient);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CFolderNodeCch::CFolderNodeCch(MVirtualFolderClient& aClient)
: CFolderNodeCallHistory(aClient, KFolderCch(), ECombined)
	{
	LOG_FUNC
	}