mtpfws/mtpfw/dataproviders/dputility/src/cmtpknowledgehandler.cpp
author hgs
Thu, 04 Nov 2010 15:31:42 +0800
changeset 60 841f70763fbe
parent 49 c20dd21d1eb4
permissions -rw-r--r--
201044_04

// Copyright (c) 2008-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:
// mw/remoteconn/mtpfws/mtpfw/dataproviders/dputility/src/cmtpknowledgehandler.cpp

#include <bautils.h> 
#include <centralrepository.h>
#include <mtp/cmtptypestring.h>
#include <mtp/cmtpobjectmetadata.h>
#include <mtp/cmtptypeobjectinfo.h>
#include <mtp/cmtptypeobjectproplist.h>
#include <mtp/mmtpdataproviderframework.h>
#include <mtp/mmtpobjectmgr.h>
#include <mtp/cmtptypefile.h>
#include <mtp/mtpdatatypeconstants.h>

#include "cmtpknowledgehandler.h"
#include "mtpdebug.h"
#include "OstTraceDefinitions.h"
#ifdef OST_TRACE_COMPILER_IN_USE
#include "cmtpknowledgehandlerTraces.h"
#endif


const TInt KDateTimeMaxLength = 22;
const TInt KNameMaxLength = 255;

_LIT16(KEmptyContent16, "");
_LIT(KMTPKnowledgeObjDriveLocation, "c:");
_LIT(KMTPNoBackupFolder, "nobackup\\");	
_LIT(KMTPSlash, "\\");
_LIT(KMTPKnowledgeObjFileName, "mtp_knowledgeobj.dat");
_LIT(KMTPKnowledgeObjSwpFileName, "mtp_knowledgeobj.swp");


CKnowledgeObject* CKnowledgeObject::NewL(CRepository& aRepository)
	{
	CKnowledgeObject *self = new (ELeave) CKnowledgeObject(aRepository);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

CKnowledgeObject::CKnowledgeObject(CRepository& aRepository) : iRepository(aRepository)
	{
	
	}
CKnowledgeObject::~CKnowledgeObject()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_CKNOWLEDGEOBJECT_DES_ENTRY );
	iDateModified.Close();
	iName.Close();
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_CKNOWLEDGEOBJECT_DES_EXIT );
	}
void CKnowledgeObject::ConstructL()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_CONSTRUCTL_ENTRY );
	iKnowledgeObjectSize = KObjectSizeNotAvaiable;
	iDateModified.CreateL(KDateTimeMaxLength);
	iName.CreateL(KNameMaxLength);
	iLastAuthorProxyID.Set(KMTPUnInitialized64, KMTPUnInitialized64);
	iDirty = EBitFlagAll;
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_CONSTRUCTL_EXIT );
	}

void CKnowledgeObject::LoadL()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_LOADL_ENTRY );
	// Load ObjectSize
	TInt objSize;
	LEAVEIFERROR(iRepository.Get(ESize, objSize),
	        OstTrace0( TRACE_ERROR, CKNOWLEDGEOBJECT_LOADL, "Can't Load ObjectSize from iRepository!" ));
	iKnowledgeObjectSize = objSize;

	// Load DateModify
	iDateModified.Zero();
	LEAVEIFERROR(iRepository.Get(EDateModified, iDateModified),
	        OstTrace0( TRACE_ERROR, DUP1_CKNOWLEDGEOBJECT_LOADL, "Can't Load DateModify from iRepository!" ));
	
	// Load Name
	iName.Zero();
	LEAVEIFERROR(iRepository.Get(EName, iName),
	        OstTrace0( TRACE_ERROR, DUP2_CKNOWLEDGEOBJECT_LOADL, "Can't Load Name from iRepository!" ));

	// Load LastAuthorProxyID:
	TPtr8 writeBuf(NULL, 0); //walkaroud for the TMTPTypeUint128
	iLastAuthorProxyID.FirstWriteChunk(writeBuf);
	LEAVEIFERROR(iRepository.Get(ELastAuthorProxyID, writeBuf),
	        OstTrace0( TRACE_ERROR, DUP3_CKNOWLEDGEOBJECT_LOADL, "Can't Load LastAuthorProxyID from iRepository!" ));
	iDirty = EBitFlagNone;
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_LOADL_EXIT );
	return;
	}


void CKnowledgeObject::Clear()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_CLEAR_ENTRY );
	iKnowledgeObjectSize = KObjectSizeNotAvaiable;
	iDateModified.Zero();
	iName.Zero();
	iLastAuthorProxyID.Set(KMTPUnInitialized64, KMTPUnInitialized64);
	iDirty = EBitFlagAll;
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_CLEAR_EXIT );
	}

void CKnowledgeObject::SetSize(TUint64 aSize)
	{
	iKnowledgeObjectSize = aSize;
	iDirty |= EBitFlagSize;
	}

void CKnowledgeObject::SetDateModified(const TDesC& /*aDateModified*/)
	{
	/**
	 * DateModifed will be auto updated when commit. If PC set this prop, it will be ignored.
	 * If someday PC want to force the DateModifed be saved, the following code piece should 
	 * be opened, and add check in commit when save DateModified.
	 *iDateModified.Copy(aDateModified);
	 *iDirty |= EBitFlagDateModified;
	**/
	}

void CKnowledgeObject::SetName(const TDesC& aName)
	{
	iName.Copy(aName);
	iDirty |= EBitFlagName;
	}

void CKnowledgeObject::SetLastAuthorProxyID(TUint64 aHigh, TUint64 aLow) 
	{
	iLastAuthorProxyID.Set(aHigh, aLow);
	iDirty |= EBitFlagLastAuthorProxyID;
	}

void CKnowledgeObject::CommitL()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_COMMITL_ENTRY );
	if (EBitFlagSize == (iDirty & EBitFlagSize))
		{
		// TUint64 -> TInt, some capability is lost, 
		// anyway, it's enough for knowledge object.   
		LEAVEIFERROR(iRepository.Set(ESize, (TInt)iKnowledgeObjectSize),
		        OstTrace1( TRACE_ERROR, CKNOWLEDGEOBJECT_COMMITL, "set Size to %d failed against iRepository!", iKnowledgeObjectSize)); 
		}

	if (EBitFlagName == (iDirty & EBitFlagName))
		{
		LEAVEIFERROR(iRepository.Set(EName, iName),
		        OstTraceExt1( TRACE_ERROR, DUP1_CKNOWLEDGEOBJECT_COMMITL, "set name to %S failed against iRepository!", iName)); 
		}
	
	if (EBitFlagLastAuthorProxyID == (iDirty & EBitFlagLastAuthorProxyID))
		{
		if (EMTPRespCodeOK != SetColumnType128Value(ELastAuthorProxyID, iLastAuthorProxyID))
			{
            OstTrace0( TRACE_ERROR, DUP2_CKNOWLEDGEOBJECT_COMMITL, "set LastAuthorProxyID failed!" );
			User::Leave(KErrGeneral);
			}
		}
	
	// update DateModified to be the time of Commit
	RefreshDateModifed();
	LEAVEIFERROR(iRepository.Set(EDateModified, iDateModified),
	        OstTraceExt1( TRACE_ERROR, DUP3_CKNOWLEDGEOBJECT_COMMITL, "set DateModified to %S failed against iRepository!", iDateModified));  

	iDirty = EBitFlagNone;
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_COMMITL_EXIT );
	return;
	}

TMTPResponseCode CKnowledgeObject::SetColumnType128Value(TMTPKnowledgeStoreKeyNum aColumnNum, TMTPTypeUint128& aNewData)
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_SETCOLUMNTYPE128VALUE_ENTRY );
	TInt ret;
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	TBuf8<KMTPTypeINT128Size>  data;
	data.FillZ(data.MaxLength());
	TUint64 upperValue = aNewData.UpperValue();
	TUint64 lowerValue = aNewData.LowerValue();
	
	/**
	Least significant 64-bit buffer offset.
	*/
	const TInt           KMTPTypeUint128OffsetLS = 0;
	/**
	Most significant 64-bit buffer offset.
	*/
	const TInt           KMTPTypeUint128OffsetMS = 8;
	
	memcpy(&data[KMTPTypeUint128OffsetMS], &upperValue, sizeof(upperValue));
	memcpy(&data[KMTPTypeUint128OffsetLS], &lowerValue, sizeof(lowerValue));
	
	ret = iRepository.Set(aColumnNum, data);
	if (KErrNone != ret)
		{
		responseCode = EMTPRespCodeGeneralError;
		}
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_SETCOLUMNTYPE128VALUE_EXIT );
	OstTrace1( TRACE_NORMAL, CKNOWLEDGEOBJECT_SETCOLUMNTYPE128VALUE, "responseCode = 0x%04X", responseCode );
	return responseCode;
	}


void CKnowledgeObject::RefreshDateModifed()
	{
	OstTraceFunctionEntry0( CKNOWLEDGEOBJECT_REFRESHDATEMODIFED_ENTRY );
	//get current time
	TTime now;	
	now.UniversalTime();
	_LIT(KFormat,"%F%Y%M%DT%H%T%SZ");
	iDateModified.Zero();
	now.FormatL(iDateModified, KFormat);
	OstTraceFunctionExit0( CKNOWLEDGEOBJECT_REFRESHDATEMODIFED_EXIT );
	return;
	}

EXPORT_C CMTPKnowledgeHandler* CMTPKnowledgeHandler::NewL(MMTPDataProviderFramework& aFramework, TUint16 aFormatCode, 
												CRepository& aReposotry, const TDesC& aKwgSuid)
	{
	CMTPKnowledgeHandler *self = new (ELeave) CMTPKnowledgeHandler(aFramework, aFormatCode, aReposotry, aKwgSuid);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}

EXPORT_C CMTPKnowledgeHandler::~CMTPKnowledgeHandler()
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_CMTPKNOWLEDGEHANDLER_DES_ENTRY );
	delete iKnowledgeObj;
	delete iKnowledgeSwpBuffer;
	delete iCachedKnowledgeObject;
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_CMTPKNOWLEDGEHANDLER_DES_EXIT );
	}

CMTPKnowledgeHandler::CMTPKnowledgeHandler(MMTPDataProviderFramework& aFramework, TUint16 aFormatCode, 
										CRepository& aReposotry, const TDesC& aKwgSuid) :
	iFramework(aFramework), iRepository(aReposotry), iKnowledgeFormatCode(aFormatCode), iSuid(aKwgSuid)
	{
	}

void CMTPKnowledgeHandler::ConstructL()
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_CONSTRUCTL_ENTRY );
	
	iFramework.Fs().PrivatePath(iKnowObjFileName);
	iKnowObjFileName.Insert(0, KMTPKnowledgeObjDriveLocation);
	iKnowObjFileName.Append(KMTPNoBackupFolder);
	iKnowObjFileName.Append(iSuid);
	iKnowObjFileName.Append(KMTPSlash);

	iKnowObjSwpFileName.Append(iKnowObjFileName);
	iKnowObjSwpFileName.Append(KMTPKnowledgeObjSwpFileName);
	
	iKnowObjFileName.Append(KMTPKnowledgeObjFileName);

	// Create knowledge object file directory if not exist.
	BaflUtils::EnsurePathExistsL(iFramework.Fs(), iKnowObjFileName);

	// Recover for previous failed transaction
	if(BaflUtils::FileExists(iFramework.Fs(), iKnowObjSwpFileName))
		{
		// In case DP received some object content
		LEAVEIFERROR(iFramework.Fs().Delete(iKnowObjSwpFileName),
		        OstTraceExt1( TRACE_ERROR, CMTPKNOWLEDGEHANDLER_CONSTRUCTL, "delete %S failed!", iKnowObjSwpFileName ));
		}

	// create and load knowledge object properties
	iCachedKnowledgeObject = CKnowledgeObject::NewL(iRepository);
	iCachedKnowledgeObject->LoadL();
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_CONSTRUCTL_EXIT );
	}

EXPORT_C void CMTPKnowledgeHandler::SetStorageId(TUint32 aStorageId)
	{
	iStorageID = aStorageId;
	}

void CMTPKnowledgeHandler::CommitL()
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_COMMITL_ENTRY );
	LEAVEIFERROR(iRepository.StartTransaction(CRepository::EReadWriteTransaction),
	        OstTrace0( TRACE_ERROR, CMTPKNOWLEDGEHANDLER_COMMITL, "start readwrite transaction for iRepository failed!"));
	        
	iRepository.CleanupCancelTransactionPushL();
	
	iCachedKnowledgeObject->CommitL();
	
	// Close all knowledge file and reset pointer.
	if (iKnowledgeObj)
		{
		delete iKnowledgeObj;
		iKnowledgeObj = NULL;
		}
	
	if (iKnowledgeSwpBuffer)
		{
		delete iKnowledgeSwpBuffer;
		iKnowledgeSwpBuffer = NULL;
		}

	if(BaflUtils::FileExists(iFramework.Fs(), iKnowObjSwpFileName) && iCachedKnowledgeObject->Size() > 0)
		{
		// In case DP received some object content
		LEAVEIFERROR(iFramework.Fs().Replace(iKnowObjSwpFileName, iKnowObjFileName),
		        OstTraceExt2( TRACE_ERROR, DUP1_CMTPKNOWLEDGEHANDLER_COMMITL, 
		                "replace %S with %S failed!", iKnowObjSwpFileName, iKnowObjFileName));      
		}
	// If swp file isn't exsited, that means 0 sized object received, need do nothing.

	TUint32 keyInfo;
	LEAVEIFERROR(iRepository.CommitTransaction(keyInfo),
	        OstTrace1( TRACE_ERROR, DUP2_CMTPKNOWLEDGEHANDLER_COMMITL, 
	                "Commits transaction failed. The number of keys whose values were modified is %d", keyInfo));
	        
	        
	CleanupStack::Pop(&iRepository);

	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_COMMITL_EXIT );
	}

void CMTPKnowledgeHandler::CommitForNewObjectL(TDes& aSuid)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_COMMITFORNEWOBJECTL_ENTRY );
	aSuid = iSuid;
	CommitL();
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_COMMITFORNEWOBJECTL_EXIT );
	}
	
void CMTPKnowledgeHandler::RollBack()
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_ROLLBACK_ENTRY );
	iCachedKnowledgeObject->Clear();
	TRAP_IGNORE(iCachedKnowledgeObject->LoadL());
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_ROLLBACK_EXIT );
	}

EXPORT_C void CMTPKnowledgeHandler::GetObjectSuidL(TDes& aSuid) const
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETOBJECTSUIDL_ENTRY );
	if(iCachedKnowledgeObject->Size() != KObjectSizeNotAvaiable)
		{
		aSuid.Append(iSuid);
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETOBJECTSUIDL_EXIT );
	}

TMTPResponseCode CMTPKnowledgeHandler::SendObjectInfoL(const CMTPTypeObjectInfo& aObjectInfo, TUint32& aParentHandle, TDes& aSuid)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_SENDOBJECTINFOL_ENTRY );
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	if (aParentHandle != KMTPHandleNone && aParentHandle != KMTPHandleNoParent)
		{
		responseCode = EMTPRespCodeInvalidParentObject;
		}
	else
		{
		//if there's a read error reread
		if(iCachedKnowledgeObject->IsDirty())
			{
			OstTrace0( TRACE_WARNING, CMTPKNOWLEDGEHANDLER_SENDOBJECTINFOL, "The cached knowledge is dirty" );
			iCachedKnowledgeObject->Clear();
			iCachedKnowledgeObject->LoadL();
			}
		//already has a knowledge object
		if(iCachedKnowledgeObject->Size() != KObjectSizeNotAvaiable)
			{
			responseCode = EMTPRespCodeAccessDenied;
			}
		else
			{
			iCachedKnowledgeObject->Clear();
			iCachedKnowledgeObject->SetSize(aObjectInfo.Uint32L(CMTPTypeObjectInfo::EObjectCompressedSize));
			// DateModified will be updated when commit.
			aSuid = iSuid;
			}
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_SENDOBJECTINFOL_EXIT );
	return responseCode;
	}

TMTPResponseCode CMTPKnowledgeHandler::SendObjectPropListL(TUint64 aObjectSize, const CMTPTypeObjectPropList& /*aObjectPropList*/, 
															TUint32& aParentHandle, TDes& aSuid)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_SENDOBJECTPROPLISTL_ENTRY );
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	if (aParentHandle != KMTPHandleNone && aParentHandle != KMTPHandleNoParent)
		{
		responseCode = EMTPRespCodeInvalidParentObject;
		}
	else
		{
		//if there's a read error reread
		aParentHandle = KMTPHandleNoParent;
		if(iCachedKnowledgeObject->IsDirty())
			{
			OstTrace0( TRACE_WARNING, CMTPKNOWLEDGEHANDLER_SENDOBJECTPROPLISTL, "The cached knowledge is dirty" );
			iCachedKnowledgeObject->Clear();
			iCachedKnowledgeObject->LoadL();
			}
		//already has a knowledge object
		if(iCachedKnowledgeObject->Size() != KObjectSizeNotAvaiable)
			{
			responseCode = EMTPRespCodeAccessDenied;
			}
		else
			{
			iCachedKnowledgeObject->Clear();
			iCachedKnowledgeObject->SetSize(aObjectSize);
			aSuid = iSuid;
			}
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_SENDOBJECTPROPLISTL_EXIT );
	return responseCode;
	}

TMTPResponseCode CMTPKnowledgeHandler::GetObjectPropertyL(const CMTPObjectMetaData& aObjectMetaData, 
																TUint16 aPropertyCode, CMTPTypeObjectPropList& aPropList)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETOBJECTPROPERTYL_ENTRY );
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	CMTPTypeObjectPropListElement* propertyElement = NULL;
	TUint32 aHandle = aObjectMetaData.Uint(CMTPObjectMetaData::EHandle);
	
	if(iCachedKnowledgeObject->IsDirty())
		{
		OstTrace0( TRACE_WARNING, CMTPKNOWLEDGEHANDLER_GETOBJECTPROPERTYL, "The cached knowledge is dirty" );
		iCachedKnowledgeObject->LoadL();
		}
	
	switch (aPropertyCode)
		{
		case EMTPGenObjPropCodeParentID:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint32L(CMTPTypeObjectPropListElement::EValue, 0x0000);
			break;
			}
				
		case EMTPGenObjPropCodeName:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			if (iCachedKnowledgeObject->Name().Length() > 0)
				{
				propertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, iCachedKnowledgeObject->Name());
				}
			else
				{
				_LIT(KDefaultKwgObjName, "GenericObject01");
				propertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, KDefaultKwgObjName());	
				}
			break;
			}
			
		case EMTPGenObjPropCodePersistentUniqueObjectIdentifier:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint128L(CMTPTypeObjectPropListElement::EValue,
								iFramework.ObjectMgr().PuidL(aHandle).UpperValue(),
								iFramework.ObjectMgr().PuidL(aHandle).LowerValue());
			break;
			}
			
		case EMTPGenObjPropCodeObjectFormat:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint16L(CMTPTypeObjectPropListElement::EValue, iKnowledgeFormatCode);
			break;
			}

		case EMTPGenObjPropCodeObjectSize:
			{
			if (iCachedKnowledgeObject->Size() != KObjectSizeNotAvaiable)
				{
				propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
				propertyElement->SetUint64L(CMTPTypeObjectPropListElement::EValue, iCachedKnowledgeObject->Size());
				}
			break;
			}

		case EMTPGenObjPropCodeStorageID:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint32L(CMTPTypeObjectPropListElement::EValue, iStorageID);
			break;
			}

		case EMTPGenObjPropCodeObjectHidden:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint16L(CMTPTypeObjectPropListElement::EValue, 0x0001);
			break;
			}

		case EMTPGenObjPropCodeNonConsumable:
			{
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetUint8L(CMTPTypeObjectPropListElement::EValue, 0x01);
			break;
			}

		case EMTPGenObjPropCodeDateModified:
			{
			if(iCachedKnowledgeObject->DateModified().Length() == 0)
				{
				iCachedKnowledgeObject->RefreshDateModifed();
				}
			propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
			propertyElement->SetStringL(CMTPTypeObjectPropListElement::EValue, iCachedKnowledgeObject->DateModified());
			break;
			}
			
		case EMTPSvcObjPropCodeLastAuthorProxyID:
			{
			if ((iCachedKnowledgeObject->LastAuthorProxyID().UpperValue() != KMTPUnInitialized64)
				 && (iCachedKnowledgeObject->LastAuthorProxyID().LowerValue() !=KMTPUnInitialized64))
				{
				propertyElement = &(aPropList.ReservePropElemL(aHandle, aPropertyCode));
				propertyElement->SetUint128L(CMTPTypeObjectPropListElement::EValue,
						iCachedKnowledgeObject->LastAuthorProxyID().UpperValue(),
						iCachedKnowledgeObject->LastAuthorProxyID().LowerValue());
				}
			break;	
			}
			
		default:
			responseCode = EMTPRespCodeInvalidObjectPropCode;
			break;
		}
	if(propertyElement)
		{
		aPropList.CommitPropElemL(*propertyElement);
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETOBJECTPROPERTYL_EXIT );
	return responseCode;
	}

TMTPResponseCode CMTPKnowledgeHandler::SetObjectPropertyL(const TDesC& /*aSuid*/, 
															const CMTPTypeObjectPropListElement& aElement, 
															TMTPOperationCode aOperationCode)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_SETOBJECTPROPERTYL_ENTRY );
	TMTPResponseCode responseCode = CheckGenObjectPropertyL(aElement, aOperationCode);
	if (responseCode == EMTPRespCodeOK)
		{
		TUint16 propertyCode(aElement.Uint16L(CMTPTypeObjectPropListElement::EPropertyCode));
		switch (propertyCode)
			{
			case EMTPGenObjPropCodeObjectSize:
				{
				iCachedKnowledgeObject->SetSize(aElement.Uint64L(CMTPTypeObjectPropListElement::EValue));
				break;
				}
			case EMTPGenObjPropCodeDateModified:
				{
				// DateModified will be updated when Commit
				iCachedKnowledgeObject->SetDateModified(aElement.StringL(CMTPTypeObjectPropListElement::EValue));
				break;
				}
			case EMTPGenObjPropCodeName:
				{
				iCachedKnowledgeObject->SetName(aElement.StringL(CMTPTypeObjectPropListElement::EValue));
				break;
				}
			case EMTPSvcObjPropCodeLastAuthorProxyID:
				{
				TUint64 high_value = 0;
				TUint64 low_value  = 0;
				aElement.Uint128L(CMTPTypeObjectPropListElement::EValue, high_value, low_value);
				iCachedKnowledgeObject->SetLastAuthorProxyID(high_value, low_value);
				break;
				}
				
			default:
				responseCode = EMTPRespCodeObjectPropNotSupported;
				break;
			}
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_SETOBJECTPROPERTYL_EXIT );
	return responseCode;
	}

// Remove the knowledge object
TMTPResponseCode CMTPKnowledgeHandler::DeleteObjectL(const CMTPObjectMetaData& /*aObjectMetaData*/)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_DELETEOBJECTL_ENTRY );

	LEAVEIFERROR(iRepository.StartTransaction(CRepository::EReadWriteTransaction),
	        OstTrace0( TRACE_ERROR, CMTPKNOWLEDGEHANDLER_DELETEOBJECTL, "Start readwrite transaction failed!"));
	iRepository.CleanupCancelTransactionPushL();

	// Delete obejct properties in transaction, if leave, mgr will rollback all properties.
	iCachedKnowledgeObject->Clear();
	iCachedKnowledgeObject->CommitL();
	
	// Reset knowledgeobject pointer and close the file.
	if (iKnowledgeObj)
		{
		delete iKnowledgeObj;
		iKnowledgeObj = NULL;
		}
	
	// Keep file delete is atomic.
	if (BaflUtils::FileExists(iFramework.Fs(), iKnowObjFileName))
		{
		LEAVEIFERROR(iFramework.Fs().Delete(iKnowObjFileName),
		        OstTraceExt1( TRACE_ERROR, DUP1_CMTPKNOWLEDGEHANDLER_DELETEOBJECTL, "delete %S failed!", iKnowObjFileName));   
		}

	TUint32 keyInfo;
	LEAVEIFERROR(iRepository.CommitTransaction(keyInfo),
	           OstTrace1( TRACE_ERROR, DUP2_CMTPKNOWLEDGEHANDLER_DELETEOBJECTL, 
	                    "Commits transaction failed. The number of keys whose values were modified is %d", keyInfo));

	CleanupStack::Pop(&iRepository);

	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_DELETEOBJECTL_EXIT );
	return EMTPRespCodeOK;
	}

// Return the knowledge object content
TMTPResponseCode CMTPKnowledgeHandler::GetObjectL(const CMTPObjectMetaData& /*aObjectMetaData*/, MMTPType** aBuffer)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETOBJECTL_ENTRY );
	if (!BaflUtils::FileExists(iFramework.Fs(), iKnowObjFileName))
		{
		RFile file;
		CleanupClosePushL(file);
		LEAVEIFERROR(file.Create(iFramework.Fs(), iKnowObjFileName, EFileRead),
		        OstTraceExt1( TRACE_ERROR, CMTPKNOWLEDGEHANDLER_GETOBJECTL, "Create readonly %S failed!", iKnowObjFileName));
		CleanupStack::PopAndDestroy(&file);
		}
	
	// iKnowledgeObj will be NULL in four cases: 1. Initialize; 2. The Object has been deleted.
	// 3. it has been commited by SendObject. 4 released by GetObject.
	if (!iKnowledgeObj)
		{
		iKnowledgeObj = CMTPTypeFile::NewL(iFramework.Fs(), iKnowObjFileName, EFileRead);
		}
	*aBuffer = iKnowledgeObj;
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETOBJECTL_EXIT );
	return EMTPRespCodeOK;
	}

TMTPResponseCode CMTPKnowledgeHandler::DeleteObjectPropertyL(const CMTPObjectMetaData& /*aObjectMetaData*/, const TUint16 aPropertyCode)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_DELETEOBJECTPROPERTYL_ENTRY );
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	switch (aPropertyCode)
		{
		case EMTPGenObjPropCodeDateModified:
			// DateModified will be updated when Commit
			iCachedKnowledgeObject->SetDateModified(KEmptyContent16);
			break;
		case EMTPSvcObjPropCodeLastAuthorProxyID:
			{
			iCachedKnowledgeObject->SetLastAuthorProxyID(KMTPUnInitialized64, KMTPUnInitialized64);
			break;
			}
			
		case EMTPObjectPropCodeParentObject:
		case EMTPObjectPropCodeName:
		case EMTPObjectPropCodePersistentUniqueObjectIdentifier:
		case EMTPObjectPropCodeObjectFormat:
		case EMTPObjectPropCodeObjectSize:
		case EMTPObjectPropCodeStorageID:
		case EMTPObjectPropCodeHidden:
		case EMTPObjectPropCodeNonConsumable:
			responseCode = EMTPRespCodeAccessDenied;
			break;
			
		default:
			responseCode = EMTPRespCodeInvalidObjectPropCode;
			break;
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_DELETEOBJECTPROPERTYL_EXIT );
	return responseCode;
	}

TMTPResponseCode CMTPKnowledgeHandler::GetBufferForSendObjectL(const CMTPObjectMetaData& /*aObjectMetaData*/, MMTPType** aBuffer)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETBUFFERFORSENDOBJECTL_ENTRY );
	if (iKnowledgeSwpBuffer)
		{
		delete iKnowledgeSwpBuffer;
		iKnowledgeSwpBuffer = NULL;
		}
	iKnowledgeSwpBuffer = CMTPTypeFile::NewL(iFramework.Fs(), iKnowObjSwpFileName, EFileWrite);
	iKnowledgeSwpBuffer->SetSizeL(0);
	*aBuffer = iKnowledgeSwpBuffer;
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETBUFFERFORSENDOBJECTL_EXIT );
	return EMTPRespCodeOK;
	}

void CMTPKnowledgeHandler::BuildObjectInfoL(CMTPTypeObjectInfo& aObjectInfo) const
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_BUILDOBJECTINFOL_ENTRY );
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EStorageID, iStorageID);	
	aObjectInfo.SetUint16L(CMTPTypeObjectInfo::EObjectFormat, iKnowledgeFormatCode);
	// Not use
	aObjectInfo.SetUint16L(CMTPTypeObjectInfo::EProtectionStatus, 0x0000);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EObjectCompressedSize, iCachedKnowledgeObject->Size());
	aObjectInfo.SetUint16L(CMTPTypeObjectInfo::EThumbFormat, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EThumbCompressedSize, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EThumbPixWidth, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EThumbPixHeight, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EImagePixWidth, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EImagePixHeight, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EImageBitDepth, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EParentObject, KMTPHandleNoParent);
	aObjectInfo.SetUint16L(CMTPTypeObjectInfo::EAssociationType, 0x0000);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::EAssociationDescription, 0);
	aObjectInfo.SetUint32L(CMTPTypeObjectInfo::ESequenceNumber, 0);
	aObjectInfo.SetStringL(CMTPTypeObjectInfo::EFilename, KNullDesC);
	aObjectInfo.SetStringL(CMTPTypeObjectInfo::EDateModified, KNullDesC);
	aObjectInfo.SetStringL(CMTPTypeObjectInfo::EDateCreated, KNullDesC);
	aObjectInfo.SetStringL(CMTPTypeObjectInfo::EKeywords, KNullDesC);
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_BUILDOBJECTINFOL_EXIT );
	}

TMTPResponseCode CMTPKnowledgeHandler::GetObjectInfoL(const CMTPObjectMetaData& /*aObjectMetaData*/, CMTPTypeObjectInfo& aObjectInfo)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETOBJECTINFOL_ENTRY );
	if(iCachedKnowledgeObject->Size() != KObjectSizeNotAvaiable)
		{
		BuildObjectInfoL(aObjectInfo);
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETOBJECTINFOL_EXIT );
	return EMTPRespCodeOK;
	}


void CMTPKnowledgeHandler::ReleaseObjectBuffer()
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_RELEASEOBJECTBUFFER_ENTRY );
	if (iKnowledgeObj)
		{
		delete iKnowledgeObj;
		iKnowledgeObj = NULL;
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_RELEASEOBJECTBUFFER_EXIT );
	}

TMTPResponseCode CMTPKnowledgeHandler::GetObjectSizeL(const TDesC& aSuid, TUint64& aObjectSize)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETOBJECTSIZEL_ENTRY );
	if (aSuid != iSuid)
		{
		OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETOBJECTSIZEL_EXIT );
		return EMTPRespCodeGeneralError;
		}
	aObjectSize = iCachedKnowledgeObject->Size();
	OstTraceFunctionExit0( DUP1_CMTPKNOWLEDGEHANDLER_GETOBJECTSIZEL_EXIT );
	return EMTPRespCodeOK;
	}

TMTPResponseCode CMTPKnowledgeHandler::GetAllObjectPropCodeByGroupL(TUint32 aGroupId, RArray<TUint32>& aPropCodes)
	{
	OstTraceFunctionEntry0( CMTPKNOWLEDGEHANDLER_GETALLOBJECTPROPCODEBYGROUPL_ENTRY );
	TMTPResponseCode responseCode = EMTPRespCodeOK;
	if (0 == aGroupId)
		{
		TInt count = sizeof(KMTPFullEnumSyncKnowledgeObjectProperties) / sizeof(KMTPFullEnumSyncKnowledgeObjectProperties[0]);
		for (TInt i = 0; i < count; i++)
			{
			aPropCodes.AppendL(KMTPFullEnumSyncKnowledgeObjectProperties[i]);
			}
		}
	else if(2 == aGroupId)
		{
		TInt count = sizeof(KMTPKnowledgeObjectPropertiesGroup2) / sizeof(KMTPKnowledgeObjectPropertiesGroup2[0]);
		for (TInt i = 0; i < count; i++)
			{
			aPropCodes.Append(KMTPKnowledgeObjectPropertiesGroup2[i]);
			}
		}
	else if(5 == aGroupId)
		{
		TInt count = sizeof(KMTPKnowledgeObjectPropertiesGroup5) / sizeof(KMTPKnowledgeObjectPropertiesGroup5[0]);
		for (TInt i = 0; i < count; i++)
			{
			aPropCodes.Append(KMTPKnowledgeObjectPropertiesGroup5[i]);
			}
		}
	else
		{
		responseCode = (TMTPResponseCode)0xA805;
		}
	OstTraceFunctionExit0( CMTPKNOWLEDGEHANDLER_GETALLOBJECTPROPCODEBYGROUPL_EXIT );
	return responseCode;
	}