sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #ifndef OPERATIONS_H
sl@0: #define OPERATIONS_H
sl@0: 
sl@0: #include <e32debug.h>
sl@0: #include <e32std.h>
sl@0: #include "datatype.h"
sl@0: 
sl@0: /**
sl@0: This class encapsulates the operation logic used in both the client-server and the PC side library. The MOperationLogic
sl@0: defines a set of pure virtual functions to be implemented. Currently the two classes responsible for performing operations
sl@0: respectively are the CServerRepository and the CPcRepImpl
sl@0: @internalTechnology
sl@0: */
sl@0: class MOperationLogic
sl@0: 	{
sl@0: 	public:
sl@0: 
sl@0: /** DELETE RANGE
sl@0: Delete a settings from a source list. Settings are marked as deleted rather than deleted immediately
sl@0: @param aSourceList the source array of settings's pointer matching the partial key and mask
sl@0: @param aPartialKey the partialKey of the settings to be delted
sl@0: @param aErrorKey to hold the error encountered during the Delete operation
sl@0: */
sl@0: void DeleteSettingsRangeL(RSettingPointerArray& aSourceList,TUint32 aPartialKey,TUint32& aErrorKey)
sl@0: 	{
sl@0: 	if (aSourceList.Count()==0)	
sl@0: 		{
sl@0: 		aErrorKey=aPartialKey;		
sl@0: 		User::Leave(KErrNotFound);
sl@0: 		}
sl@0: 		
sl@0: 	aErrorKey = KUnspecifiedKey;
sl@0: 	TInt numSettings = aSourceList.Count();
sl@0: 	TInt error=KErrNone;		
sl@0: 	for (TInt i = 0; (i < numSettings) && (error == KErrNone); i++)
sl@0: 		{
sl@0: 		ASSERT(aSourceList[i]);
sl@0: 		TServerSetting& settingToDelete = *(aSourceList[i]);
sl@0: 		TUint32 key = settingToDelete.Key();
sl@0: 		// delete it Ensure there is a delete placeholder at the location
sl@0: 		if (GetWritableSettingList().Find(key) == &settingToDelete)
sl@0: 			{
sl@0: 			// we are deleting a setting that is already in the transaction list: Flag it as deleted
sl@0: 			settingToDelete.Reset();
sl@0: 			settingToDelete.SetDeleted();
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			// create a new placeholder and set as deleted
sl@0: 			TServerSetting newSetting(key);
sl@0: 			newSetting.SetMeta(settingToDelete.Meta());
sl@0: 			newSetting.SetDeleted();
sl@0: 			GetWritableSettingList().OrderedInsertL(newSetting);
sl@0: 			}
sl@0: 		}	
sl@0: 	}
sl@0: 
sl@0: /** DELETE
sl@0: Mark a setting in the source list as deleted if found
sl@0: @param aId the setting Id to be deleted
sl@0: @param aSettingList the list of source setting to look for
sl@0: */
sl@0: void DeleteSettingL(TUint32 aId)
sl@0: 	{
sl@0: 	TServerSetting* ts=GetWritableSettingList().Find(aId);
sl@0: 	if (ts)
sl@0: 		{
sl@0: 		if (ts->IsDeleted())
sl@0: 			User::Leave(KErrNotFound);
sl@0: 		else
sl@0: 			{
sl@0: 			ts->Reset();
sl@0: 			ts->SetDeleted();	
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		TServerSetting* s=GetSetting(aId);
sl@0: 		if (!s)	
sl@0: 			User::Leave(KErrNotFound);
sl@0: 		else
sl@0: 			{
sl@0: 			TServerSetting newSetting(aId);
sl@0: 			newSetting.SetMeta(s->Meta());
sl@0: 			newSetting.SetDeleted();
sl@0: 			GetWritableSettingList().OrderedInsertL(newSetting);
sl@0: 			}
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** SET
sl@0: Set a setting to a new value, create the setting if it does not exist yet
sl@0: @param aKey the id of the setting
sl@0: @param aVal the new value of the setting
sl@0: */
sl@0: template <class T>
sl@0: void SetSettingL(TUint32 aKey,const T& aVal)
sl@0: 	{
sl@0: 	TServerSetting* s = GetWritableSettingList().Find(aKey);
sl@0: 	if (s)
sl@0: 		{
sl@0: 		if (s->IsDeleted())
sl@0: 			{
sl@0: 	 		// replace the deleted entry with the new values
sl@0: 			s->CopyValueL(aVal);
sl@0: 			s->SetAccessPolicy(GetFallbackAccessPolicy(aKey)); 			
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			User::LeaveIfError(s->AssignValueFrom(aVal));	
sl@0: 			s->SetMeta(s->Meta() & (~KMetaDefaultValue));	
sl@0: 			}		
sl@0: 		}
sl@0: 	else	
sl@0: 		{
sl@0: 		TServerSetting* ns=GetSetting(aKey);
sl@0: 		TServerSetting newSetting(aKey);
sl@0: 		newSetting.CopyValueL(aVal);
sl@0: 		newSetting.SetAccessPolicy(GetFallbackAccessPolicy(aKey));
sl@0: 		TUint32 metadata;		
sl@0: 		if (!ns)
sl@0: 			{
sl@0: 			GetSingleMeta(aKey,metadata);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			if (!ns->IsType(aVal))
sl@0: 				{
sl@0: 				User::Leave(KErrArgument);
sl@0: 				}			
sl@0: 			metadata = ~KMetaDefaultValue & ns->Meta();
sl@0: 			}
sl@0: 		newSetting.SetMeta(metadata);			
sl@0: 		newSetting.PushL(); // only needed for strings
sl@0: 		GetWritableSettingList().OrderedInsertL(newSetting);	
sl@0: 		newSetting.Pop();			
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** CREATE
sl@0: Create a setting with a new value with a meta value.If meta value
sl@0: not specified it will attempt to look for the meta in order of single
sl@0: ,range, and finally default meta
sl@0: @param aKey the id of the setting
sl@0: @param aVal the new value of the setting
sl@0: @param aMeta the meta value of the setting
sl@0: @leave KErrAlreadyExists if setting with that id already exist
sl@0: */
sl@0: template <class T>
sl@0: void CreateSettingL(TUint32 aKey, const T& aVal, TUint32* aMeta)
sl@0: 	{
sl@0: 	TServerSetting* s = GetSetting(aKey);
sl@0: 	if (s)
sl@0: 		{
sl@0: 		if (!s->IsDeleted())
sl@0: 			User::Leave(KErrAlreadyExists);
sl@0: 		else
sl@0: 			{
sl@0: 			//previously deleted settings			
sl@0: 			s->CopyValueL(aVal);
sl@0: 			s->SetAccessPolicy(GetFallbackAccessPolicy(aKey));		
sl@0: 			}
sl@0: 		}
sl@0: 	else
sl@0: 		{
sl@0: 		//brand new settings, create this
sl@0: 		TServerSetting newSetting(aKey);
sl@0: 		newSetting.CopyValueL(aVal);
sl@0: 		if (aMeta)		
sl@0: 			{
sl@0: 			newSetting.SetMeta(*aMeta);
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TUint32 singleMeta;
sl@0: 			GetSingleMeta(aKey,singleMeta);
sl@0: 			newSetting.SetMeta(singleMeta);	
sl@0: 			}
sl@0: 		newSetting.SetAccessPolicy(GetFallbackAccessPolicy(aKey));
sl@0: 		newSetting.PushL(); // only needed for strings
sl@0: 		GetWritableSettingList().OrderedInsertL(newSetting);	
sl@0: 		newSetting.Pop();		
sl@0: 		}
sl@0: 	}
sl@0: 
sl@0: /** GETMETA
sl@0: Retrieve the meta associated with a setting
sl@0: @param aId the id of the setting
sl@0: @param aMeta return value for the setting's meta
sl@0: @return KErrNotFound if setting does not exist
sl@0: */
sl@0: TInt GetMeta(TUint32 aId, TUint32& aMeta)
sl@0: 	{
sl@0: 	const TServerSetting* s = GetSetting(aId);
sl@0: 	//if is deleted or cannot be found
sl@0: 	if (s && s->IsDeleted() || !s)
sl@0: 		{
sl@0: 		return KErrNotFound;
sl@0: 		}
sl@0: 	aMeta = ~KMetaDefaultValue & s->Meta();
sl@0: 	return KErrNone;
sl@0: 	}
sl@0: 
sl@0: /** GET
sl@0: Retrieve the value of a setting
sl@0: @param aId the id of the setting
sl@0: @param aVal return value for the setting's value
sl@0: @return KErrNotFound if setting does not exist
sl@0: 		KErrArgument if specified setting type does not match	
sl@0: */
sl@0: template <class T>
sl@0: TInt Get(TUint32 aId, T& aVal)
sl@0: 	{
sl@0: 	const TServerSetting* s = GetSetting(aId);
sl@0: 	//if is deleted or cannot be found
sl@0: 	if (s && s->IsDeleted() || !s)
sl@0: 		{
sl@0: 		return KErrNotFound;
sl@0: 		}
sl@0: 	return s->AssignValueTo(aVal);
sl@0: 	}
sl@0: 
sl@0: /** FIND COMPARE
sl@0: Retrieve a list of settings' id that match the value based on either the equal or not equal comparison
sl@0: @param aInputArray the source array of pointer to the settings
sl@0: @param aVal the value to be compared for the setting
sl@0: @param aEqual the comparison rule to be applied
sl@0: @param aFoundIds the passed in ID array to hold the matching settings
sl@0: */
sl@0: template <class T>
sl@0: void FindCompareL(const RSettingPointerArray& aInputArray,const T& aVal,TComparison aEqual,RArray<TUint32>& aFoundIds) const
sl@0: 	{
sl@0: 	aFoundIds.Reset();
sl@0: 	TInt numSettings=aInputArray.Count();
sl@0: 	for (TInt i=0;i< numSettings;i++)
sl@0: 		{
sl@0: 		ASSERT(aInputArray[i]);
sl@0: 		const TServerSetting& setting = *(aInputArray[i]);
sl@0: 		ASSERT(!setting.IsDeleted());
sl@0: 		TInt error=KErrNone;		
sl@0: 		if(aEqual && setting==aVal || !aEqual && setting!=aVal)
sl@0: 			{
sl@0: 			error = aFoundIds.Append(setting.Key());
sl@0: 			if (error != KErrNone)
sl@0: 				{
sl@0: 				aFoundIds.Reset();
sl@0: 				User::Leave(error);
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	if (aFoundIds.Count() == 0)
sl@0: 		{
sl@0: 		User::Leave(KErrNotFound);
sl@0: 		}
sl@0: 	}
sl@0: 		
sl@0: /** FINDL
sl@0: Retrieve a list of settings that match the partial id and mask
sl@0: @param aSourcePartialKey the partial key to match
sl@0: @param aMask the mask to be used with the partial key for matching
sl@0: @param aFoundIds, the array to hold the found settings id
sl@0: @param aFoundIdsMaxLimit, specify the max id to fit in the aFoundIds
sl@0: @param aExcessIds, the array to hold the remaining settings id
sl@0: */		
sl@0: void FindL(TUint32 aSourcePartialKey,TUint32 aMask,RArray<TUint32>& aFoundIds,TUint aFoundIdsMaxLimit,RArray<TUint32>& aExcessIds)
sl@0: 	{
sl@0: 	RSettingPointerArray settings;
sl@0: 	CleanupClosePushL(settings);
sl@0: 	TInt error = FindSettings(aSourcePartialKey,aMask, settings);
sl@0: 	if (error == KErrNone)
sl@0: 		{
sl@0: 		const TUint numSettings = settings.Count();
sl@0: 		if (numSettings==0)
sl@0: 			{
sl@0: 			User::Leave(KErrNotFound);
sl@0: 			}
sl@0: 		aFoundIds.Reset();
sl@0: 		
sl@0: 		const TUint numInitial = numSettings > aFoundIdsMaxLimit ? aFoundIdsMaxLimit : numSettings;
sl@0: 		const TUint numFinal = numSettings > aFoundIdsMaxLimit ? numSettings - aFoundIdsMaxLimit : 0;
sl@0: 		
sl@0: 		//reserve memory for everything that needs to be added to the array
sl@0: 		aFoundIds.ReserveL(numSettings);
sl@0: 		
sl@0: 		//now append up to aFoundIdsMaxLimit settings
sl@0: 		for(TUint i = 0; i < numInitial; i++)
sl@0: 			{
sl@0: 			ASSERT(settings[i]);
sl@0: 			// all settings flagged as deleted should have been removed by now, but just to be safe:
sl@0: 			ASSERT(!settings[i]->IsDeleted());
sl@0: 			aFoundIds.AppendL(settings[i]->Key());
sl@0: 			}
sl@0: 			
sl@0: 		//fill the aExcessIds array with any remaining settings
sl@0: 		if(numFinal)
sl@0: 			{
sl@0: 			aExcessIds.Reset();
sl@0: 			aExcessIds.ReserveL(numFinal);
sl@0: 			for(TUint i = numInitial; i < numSettings; i++)
sl@0: 				{
sl@0: 				ASSERT(settings[i]);
sl@0: 				// all settings flagged as deleted should have been removed by now, but just to be safe:
sl@0: 				ASSERT(!settings[i]->IsDeleted());
sl@0: 				aExcessIds.AppendL(settings[i]->Key());
sl@0: 				}
sl@0: 			}
sl@0: 		}
sl@0: 	CleanupStack::PopAndDestroy();
sl@0: 	User::LeaveIfError(error);
sl@0: 	}
sl@0: 
sl@0: /** MOVE
sl@0: Move settings that match a given partial key to another target partial key given the mask
sl@0: @param aSourcePartialKey, the source partialKey
sl@0: @param aTargetPartialKey the target partialKey
sl@0: @param aMask the mask to be used with the partial keys
sl@0: @param aErrorKey to hold the error encountered during the move operation
sl@0: @param aSourcePointerArray the array containing the source settings' pointer
sl@0: */
sl@0: TInt MoveL(TUint32 aSourcePartialKey,TUint32 aTargetPartialKey,TUint32 aMask, TUint32& aErrorKey,
sl@0: 			const RSettingPointerArray& aSourcePointerArray)
sl@0: 	{
sl@0: 	// all write operations now done in a transaction
sl@0: 	TInt error = KErrNone;
sl@0: 	aErrorKey = KUnspecifiedKey;
sl@0: 	
sl@0: 	TUint32 maskedSourcePartialKey = aSourcePartialKey & aMask;
sl@0: 	TUint32 maskedTargetPartialKey = aTargetPartialKey & aMask;
sl@0: 	TUint32 sourceToTarget = maskedSourcePartialKey ^ maskedTargetPartialKey;
sl@0: 	if(!sourceToTarget)
sl@0: 		{
sl@0: 		// not moving anywhere: must return now as this trivial case fails with later logic
sl@0: 		return KErrNone;
sl@0: 		}
sl@0: 
sl@0: 	//Validation of the SourcePointerArray whether any item exist
sl@0: 	if (aSourcePointerArray.Count() == 0)
sl@0: 		{
sl@0: 		aErrorKey=aSourcePartialKey;
sl@0: 		return KErrNotFound;
sl@0: 		}
sl@0: 
sl@0: 	// create a local copy of settings as the settings pointed to by RSettingPointerArray 
sl@0: 	// could move and cause CServerRepository to point to the wrong key, added as fix for DEF080104
sl@0: 	RSettingsArray settingsCopy;
sl@0: 	CleanupClosePushL(settingsCopy);
sl@0: 	settingsCopy.CopyFromPointerArrayL(aSourcePointerArray);
sl@0: 			
sl@0: 	for (TInt i = 0; (i < settingsCopy.Count()) && (error == KErrNone); i++)
sl@0: 		{
sl@0: 		ASSERT(&settingsCopy[i]);
sl@0: 		TServerSetting& sourceSetting = settingsCopy[i];
sl@0: 		TUint32 sourceKey = sourceSetting.Key();
sl@0: 		TUint32 targetKey = sourceKey ^ sourceToTarget;
sl@0: 		
sl@0: 		TServerSetting* targetSetting = GetSetting(targetKey);		
sl@0: 		if (targetSetting)
sl@0: 			{
sl@0: 			// must be set as deleted only(for PC side this can never be reached, all setting either exist or not and if exist
sl@0: 			// this will return KErrAlreadyExists and this error already captured earlier
sl@0: 			ASSERT(targetSetting->IsDeleted());
sl@0: 			error = targetSetting->Replace(sourceSetting);
sl@0: 			if (error == KErrNone)
sl@0: 				{
sl@0: 				targetSetting->SetKey(targetKey);
sl@0: 				// setting takes the access policy of the target key
sl@0: 				targetSetting->SetAccessPolicy(GetFallbackAccessPolicy(targetKey));
sl@0: 				}
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			TServerSetting newSetting;
sl@0: 			error = newSetting.Replace(sourceSetting);
sl@0: 			if (error == KErrNone)
sl@0: 				{
sl@0: 				TUint32 metaFromIni;
sl@0: 				newSetting.SetKey(targetKey);
sl@0: 				GetSingleMeta(targetKey,metaFromIni);
sl@0: 				newSetting.SetMeta(metaFromIni);
sl@0: 			
sl@0: 				// setting takes the access policy of the target key
sl@0: 				newSetting.SetAccessPolicy(GetFallbackAccessPolicy(targetKey));
sl@0: 				newSetting.PushL(); // only needed for strings
sl@0: 				GetWritableSettingList().OrderedInsertL(newSetting);
sl@0: 				newSetting.Pop();	// only needed for strings
sl@0: 				}
sl@0: 			}
sl@0: 			
sl@0: 		// ensure there is a delete placeholder at the old location
sl@0: 		TServerSetting* oldSetting=GetWritableSettingList().Find(sourceKey);
sl@0: 		if (oldSetting)
sl@0: 			{
sl@0: 			oldSetting->Reset();
sl@0: 			oldSetting->SetDeleted();
sl@0: 			}
sl@0: 		else
sl@0: 			{
sl@0: 			//this part cannot happen for PC side as the search is on the persistent directly
sl@0: 			TServerSetting newSetting(sourceKey);
sl@0: 			newSetting.SetDeleted();
sl@0: 			GetWritableSettingList().OrderedInsertL(newSetting);			
sl@0: 			}
sl@0: 		}
sl@0: 	// destroy local copy of settings
sl@0: 	settingsCopy.Reset();
sl@0: 	CleanupStack::PopAndDestroy(&settingsCopy);
sl@0: 	return error;		
sl@0: 	}
sl@0: 
sl@0: 
sl@0: 	//pure virtual functions to be implemented by CServerRepository and CPcRepImpl
sl@0: 	
sl@0: 	/**
sl@0: 	Retrieve the meta for a setting, look for the meta in the order of individual setting meta
sl@0: 	range meta and then default meta.
sl@0: 	*/
sl@0: 	virtual void GetSingleMeta(TUint aKey,TUint32& aMeta)=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Retrieve the fall back policy associated with a setting
sl@0: 	*/
sl@0: 	virtual TSettingsAccessPolicy* GetFallbackAccessPolicy(TUint32 aId) const =0;
sl@0: 	
sl@0: 	/**
sl@0: 	Retrieve a pointer to a setting having the key specified in aKey
sl@0: 	*/
sl@0: 	virtual TServerSetting* GetSetting(TUint aKey)=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Retrieve the settings that match the partial key and mask and add it into the settings pointer array
sl@0: 	*/
sl@0: 	virtual TInt FindSettings(TUint32 aSourcePartialKey,TUint32 aMask,RSettingPointerArray& aOutputArray) const=0;
sl@0: 	
sl@0: 	/**
sl@0: 	Get the list of settings array where modification should be made
sl@0: 	*/
sl@0: 	virtual RSettingsArray& GetWritableSettingList() =0;
sl@0: };
sl@0: #endif // OPERATIONS_H
sl@0: