phonebookengines/contactsmodel/cntplsql/src/rpplicccontactstore.cpp
changeset 0 e686773b3f54
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/rpplicccontactstore.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,391 @@
+// Copyright (c) 2007-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:
+//
+
+/**
+ @file
+ @internalComponent
+ @released
+*/
+
+#include "rpplicccontactstore.h"
+#include "clplcontactproperties.h"
+#include <phbksync.h>
+
+/**
+RPplIccContactStore constructor.
+*/
+RPplIccContactStore::RPplIccContactStore(CLplContactProperties& aContactProperties)
+	:
+	iProperties(aContactProperties)	
+	{
+	}
+
+
+/**
+Close the ICC contacts store.
+*/
+void RPplIccContactStore::Close()
+	{
+	iTransactionOps.Close();
+	}
+
+
+/**
+Marks the start of a transaction.  If a transaction is already in progress
+leaves with KErrAlreadyExists.
+
+This method is part of the MLplTransactionManager interface.
+*/
+void RPplIccContactStore::StartTransactionL()
+	{
+	// If transaction already active then leave.
+	if (iTransactionActive)
+		{
+		User::Leave(KErrAlreadyExists);
+		}
+
+	iTransactionActive = ETrue;
+	}
+
+
+/**
+Commits the current transaction.  If no transaction is in progress leaves with
+KErrNotFound.
+
+This method is part of the MLplTransactionManager interface.
+
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::CommitCurrentTransactionL(TUint aSessionId)
+	{
+	// If no transaction active then leave.
+	if (!iTransactionActive)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	ExecuteTransactionL(aSessionId);
+	// Clear operation cache.
+	iTransactionOps.Reset();
+
+	iTransactionActive = EFalse;
+	}
+
+
+/**
+Rolls back the current transaction.  If no transaction is in progress then
+returns.
+
+This method is part of the MLplTransactionManager interface.
+
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::RollbackCurrentTransaction(TUint aSessionId)
+	{
+	if (!iTransactionActive)
+		{
+		return;
+		}
+
+	RollbackTransactionL(aSessionId);
+	// Clear operation cache.
+	iTransactionOps.Reset();
+
+	iTransactionActive = EFalse;
+	}
+
+
+TBool RPplIccContactStore::IsTransactionActive() const 
+	{
+	return iTransactionActive;
+	}
+
+
+/**
+Creates an ICC entry for the given contact item.
+
+Transactions are handled differently when creating ICC contacts.  We need to
+actually write the ICC contact before the transaction is commited.  Update and
+Delete operations can be done at commit time.
+
+@param aItem Contact item for which to create ICC entry.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+TContactItemId RPplIccContactStore::CreateInDbL(CContactItem& aItem, TUint aSessionId)
+	{
+	#if defined(__PROFILE_DEBUG__)
+		RDebug::Print(_L("[CNTMODEL] MTD: RPplIccContactStore::CreateInDbL"));
+	#endif 
+		
+	// Make sure the contact is a CContactICCEntry.  If it isn't then don't do
+	// anything.
+	if (aItem.Type() != KUidContactICCEntry)
+		{
+		return KNullContactId;
+		}
+
+	// If in transaction then add to cache.
+	if (iTransactionActive)
+		{
+		TIccContactOperation op(aItem, EIccContactCreate);
+		iTransactionOps.AppendL(op);
+		}
+	
+	// Perform operation.
+	CreateIccContactL(aItem, aSessionId);
+	
+	// Obtain the ID of the ICC group.
+	TContactItemId groupId = KNullContactId;
+	const CContactItemFieldSet& fieldset = aItem.CardFields();
+	const TInt n = fieldset.Find(KUidContactFieldICCPhonebook);
+	if(n!=KErrNotFound) // Is KUidContactFieldICCPhonebook field supplied?
+		{
+		TPtrC phonebookField = fieldset[n].TextStorage()->Text();
+		TLex lex(phonebookField);
+		TUid phonebookUid;
+		lex.Val(phonebookUid.iUid);
+		groupId = iProperties.ContactSynchroniserL(aSessionId).GroupIdL(phonebookUid);
+		}
+	else
+		{
+		// Client hasn't supplied the KUidContactFieldICCPhonebook field.
+		// The Phonebook Synchroniser will provide the group ID for the
+		// Global/GSM ADN phonebook group as a default.
+		groupId = iProperties.ContactSynchroniserL(aSessionId).GroupIdL(KUidIccGlobalAdnPhonebook);
+		}
+
+    return groupId;	
+	}
+
+
+/**
+Validate the entry to make sure it can be read from the ICC.
+
+@param aItem Contact item to be validated for reading from the ICC.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+@param aIccOpenCheck ETrue if validation for open for edit should also be done.
+*/
+void RPplIccContactStore::ReadL(CContactItem& aItem, TInt /*aInfoToRead*/, TUint aSessionId, TBool aIccOpenCheck) const
+	{
+	// Make sure the contact is a CContactICCEntry.  If it isn't then don't do
+	// anything.
+	if (aItem.Type() != KUidContactICCEntry)
+		{
+		return;
+		}
+	
+	ValidateIccContactL(MContactSynchroniser::ERead, aItem, aSessionId);
+
+	if(aIccOpenCheck)
+		{
+		ValidateIccContactL(MContactSynchroniser::EEdit, aItem, aSessionId);	
+		}
+	}
+
+
+/**
+Update an ICC entry using the given contact item.  If in a transaction then just
+add the operation to the cache, otherwise do the update directly.
+
+@param aNewItem The contact to be updated.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::UpdateL(CContactItem& aNewItem, TUint aSessionId)
+	{
+	// Make sure the contact is a CContactICCEntry.  If it isn't then don't do
+	// anything.
+	if (aNewItem.Type() != KUidContactICCEntry)
+		{
+		return;
+		}
+
+	// If in transaction then add to cache.
+	// Otherwise perform operation.
+	if (iTransactionActive)
+		{
+		TIccContactOperation op(aNewItem, EIccContactUpdate);
+		iTransactionOps.AppendL(op);
+		}
+	else
+	    {
+        if (aNewItem.IsDeleted() && (aNewItem.AccessCount() == 0))
+            {
+            DeleteL(aNewItem, aSessionId);
+            }
+    	else
+    		{
+    		UpdateIccContactL(aNewItem, aSessionId);
+    		}
+	    }	
+	}
+
+
+/**
+Delete the ICC entry associated with the given contact item.
+
+@param aItem Contact item whose associated ICC entry is to be deleted.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::DeleteL(const CContactItem& aItem, TUint aSessionId)
+	{
+	// Make sure the contact is a CContactICCEntry and that it can be deleted.
+	// If not then don't do anything.
+	if (aItem.Type() != KUidContactICCEntry ||
+		!const_cast<CContactItem&>(aItem).IsDeletable())
+		{
+		return;
+		}
+	DeleteIccContactL(aItem, aSessionId);
+	}
+
+
+void RPplIccContactStore::PersistorChangeTypeL(TContactItemId /*aItemId*/, TUid /*aNewType*/)
+	{
+	// Do nothing.
+	}
+
+
+/**
+Perform the operations stored in the cache.
+
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::ExecuteTransactionL(TUint aSessionId)
+	{
+	for (TInt i = 0; i < iTransactionOps.Count(); i++)
+		{
+		TIccContactOperation op = iTransactionOps[i];
+		switch (op.iType)
+			{
+			case EIccContactCreate:
+				// Nothing to do since create operations are executed
+				// immediately, even in transactions.
+				break;
+			case EIccContactUpdate:
+				UpdateIccContactL(op.iContact, aSessionId);
+				break;
+			case EIccContactDelete:
+				DeleteIccContactL(op.iContact, aSessionId);
+				break;
+			default:
+				User::Leave(KErrNotSupported);
+				break;
+			}
+		}
+	}
+
+	
+/**
+Rollback the cached operations.  Only Create operations need special attention
+since we need to remove those ICC entries that were created during the
+transaction.
+
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+
+@leave KErrNoMemory Out of memory.
+@leave KErrGeneral
+@leave [other system-wide leave codes]
+*/
+void RPplIccContactStore::RollbackTransactionL(TUint aSessionId)
+	{
+	for (TInt i = 0; i < iTransactionOps.Count(); i++)
+		{
+		TIccContactOperation op = iTransactionOps[i];
+		switch (op.iType)
+			{
+			case EIccContactCreate:
+				// Delete the ICC entry.
+				DeleteIccContactL(op.iContact, aSessionId);
+				break;
+			case EIccContactUpdate:
+			case EIccContactDelete:
+				// Nothing to do.
+				break;
+			default:
+				// Give up.
+				return;
+			}
+		}
+	}
+
+
+/**
+Write a contact using the Phonebook Synchroniser.  We can call the
+UpdatePostWriteL() method right after ValidateWriteContact() because we make the
+assumption that by the time this function is called the contact item has already
+had a UID assigned to it.
+
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::CreateIccContactL(CContactItem& aItem, TUint aSessionId)
+	{
+	iProperties.ContactSynchroniserL(aSessionId).UpdatePostWriteL(static_cast<CContactICCEntry&>(aItem));
+	}
+
+
+/**
+Update a contact using the Phonebook Synchroniser.
+
+@param aItem Contact item whose associated ICC entry is to be updated.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::UpdateIccContactL(CContactItem& aCurrItem, TUint aSessionId)
+	{
+	TInt ret = iProperties.ContactSynchroniserL(aSessionId).ValidateWriteContact(static_cast<CContactICCEntry&>(aCurrItem));
+	User::LeaveIfError(ret);			
+	}
+
+
+/**
+Delete a contact using the Phonebook Synchroniser.
+
+@param aItem Contact item whose associated ICC entry is to be deleted.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+
+@leave KErrNoMemory Out of memory.
+@leave KErrGeneral
+*/
+void RPplIccContactStore::DeleteIccContactL(const CContactItem& aItem, TUint aSessionId)
+	{
+	TInt ret = iProperties.ContactSynchroniserL(aSessionId).DeleteContact(aItem.Id());
+	User::LeaveIfError(ret);	
+	}
+
+
+/**
+Validate a contact using the Phonebook Synchroniser.
+
+@param aOp Validate operation.
+@param aItem Contact item for which the operation is to be validated.
+@param aSessionId The ID of the session that issued the request.  Used to
+prevent Phonebook Synchroniser deadlock.
+*/
+void RPplIccContactStore::ValidateIccContactL(MContactSynchroniser::TValidateOperation aOp,
+	CContactItem& aItem, TUint aSessionId) const
+	{
+	TInt ret = iProperties.ContactSynchroniserL(aSessionId).ValidateContact(aOp, aItem.Id());
+	User::LeaveIfError(ret);
+	}