predictivesearch/adapters/contacts/src/cpcscontactstore.cpp
changeset 0 e686773b3f54
child 15 e8e3147d53eb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/predictivesearch/adapters/contacts/src/cpcscontactstore.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,890 @@
+/*
+* Copyright (c) 2007 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:  Active object to read all the contacts from a 
+*                particular data store. Handles add/ modify/ delete of contacts.
+*
+*/
+
+// SYSTEM INCLUDES
+#include <barsread.h>
+#include <coemain.h>
+#include <utf.h>
+#include <e32std.h>
+#include <badesca.h>
+#include <CVPbkContactManager.h>
+#include <CVPbkContactStoreUriArray.h>
+#include <CVPbkContactFieldIterator.h>
+#include <CVPbkFieldTypeRefsList.h>
+#include <CVPbkContactLinkArray.h>
+#include <TVPbkContactStoreUriPtr.h>
+#include <MVPbkContactOperationBase.h>
+#include <MVPbkContactStoreList.h>
+#include <MVPbkContactStore.h>
+#include <MVPbkStoreContact.h>
+#include <MVPbkContactFieldData.h>
+#include <MVPbkContactFieldTextData.h>
+#include <MVPbkContactStoreProperties.h>
+#include <MVPbkContactLink.h>
+#include <VPbkEng.rsg>
+#include <VPbkContactStoreUris.h>
+#include <CVPbkContactViewDefinition.h>
+#include <MVPbkContactViewBase.h>
+#include <VPbkContactView.hrh>
+#include <CVPbkContactIdConverter.h>
+#include <centralrepository.h>
+#include <MVPbkContactGroup.h>
+#include <CVPbkFieldTypeSelector.h>
+#include <CVPbkContactLinkArray.h>
+#include <CVPbkSortOrder.h>
+#include <data_caging_path_literals.hrh>
+#include <bautils.h>
+
+// USER INCLUDES
+#include "cpcscontactstore.h"
+#include "CPsData.h"
+#include "CPcsDebug.h" 
+#include "CPcsDefs.h"
+#include <contactsort.rsg>
+
+// CONSTANTS
+const TInt KSimStoreOffset            = -5000;
+
+_LIT(KResourceFileName, "contactsort.rsc");
+_LIT(KPcsViewPrefix,"PCSView_");
+
+// FORWARD DECLARATION
+
+// ============================== MEMBER FUNCTIONS ================================
+
+// ---------------------------------------------------------------------------------
+// 2 phase construction
+// ---------------------------------------------------------------------------------
+CPcsContactStore* CPcsContactStore::NewL(CVPbkContactManager&  aContactManager,
+                                         MDataStoreObserver& aObserver,
+                                         const TDesC& aUri)
+{
+	PRINT ( _L("Enter CPcsContactStore::NewL") );
+
+	CPcsContactStore* self = new ( ELeave ) CPcsContactStore( );
+	CleanupStack::PushL( self );
+	
+	self->ConstructL(aContactManager,aObserver,aUri);
+	CleanupStack::Pop( self );
+	
+	PRINT ( _L("End CPcsContactStore::NewL") );
+	return self;
+}
+
+// ---------------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------------
+CPcsContactStore::CPcsContactStore():
+	CActive( CActive::EPriorityLow),
+    iAllContactLinksCount(0),
+    iFetchedContactCount(0),
+    iContactViewReady(EFalse)
+{
+    PRINT ( _L("Enter CPcsContactStore::CPcsContactStore") );
+    CActiveScheduler::Add( this );
+	PRINT ( _L("End CPcsContactStore::CPcsContactStore") );
+}
+
+
+// ---------------------------------------------------------------------------------
+// CPcsContactStore::ConstructL() 
+// 2nd phase constructor
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::ConstructL(CVPbkContactManager&  aContactManager,
+                                  MDataStoreObserver& aObserver,
+                                  const TDesC& aUri)
+{
+    PRINT ( _L("Enter CPcsContactStore::ConstructL") );
+    
+	iContactManager  = &aContactManager;
+	iObserver = &aObserver;
+	
+	iUri = HBufC::NewL(aUri.Length());
+	iUri->Des().Copy(aUri);
+	
+	// create containers for holding the sim data      
+    iSimContactItems = CVPbkContactLinkArray::NewL();
+   
+	
+	// for creating sort order
+	iSortOrder = CVPbkFieldTypeRefsList::NewL();
+	
+	// Read the fields to cache from the central repository
+	ReadFieldsToCacheFromCenrepL();
+	
+    // Local timer for block fetch delay
+    iTimer.CreateLocal();
+    
+    // Initial state
+	iNextState = ECreateView;
+	IssueRequest();
+	
+	PRINT ( _L("End CPcsContactStore::ConstructL") );
+}
+
+// ---------------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------------
+CPcsContactStore::~CPcsContactStore() 
+{
+	PRINT ( _L("Enter CPcsContactStore::~CPcsContactStore") );
+	
+	delete iContactViewBase;
+	iContactViewBase = NULL;
+	
+	delete iSortOrder;
+	iSortOrder = NULL;
+	
+    delete iSimContactItems;
+    iSimContactItems = NULL ;
+     
+	delete iWait;
+	iWait = NULL;
+	
+	delete iUri;
+	iUri = NULL;
+		
+	iTimer.Cancel();
+    iTimer.Close();
+	iFieldsToCache.Close();	
+	
+	iFs.Close();
+	
+	if(IsActive())
+	{
+		Deque();
+	}
+	
+	PRINT ( _L("End CPcsContactStore::~CPcsContactStore") );
+}
+
+
+// ---------------------------------------------------------------------------------
+// Handles addition/deletion/modification of contacts
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::HandleStoreEventL(MVPbkContactStore& aContactStore, 
+                TVPbkContactStoreEvent aStoreEvent)
+{
+   	PRINT ( _L("Enter CPcsContactStore::HandleStoreEventL") );
+
+	switch (aStoreEvent.iEventType) 
+	{
+		case TVPbkContactStoreEvent::EContactAdded:
+		{
+		    PRINT ( _L("Add contact/group event received") );
+		    iContactManager->RetrieveContactL( *(aStoreEvent.iContactLink),
+	                                           *this);
+			break;
+		}
+		
+        case TVPbkContactStoreEvent::EUnknownChanges:
+            {
+            iObserver->RemoveAll( *iUri );
+            iContactViewReady = EFalse;
+            iContactViewBase->AddObserverL(*this);
+            }
+            break;
+
+		case TVPbkContactStoreEvent::EContactDeleted:
+		case TVPbkContactStoreEvent::EContactChanged:
+		case TVPbkContactStoreEvent::EGroupDeleted:
+		case TVPbkContactStoreEvent::EGroupChanged:
+		{
+		    if ( aStoreEvent.iEventType == TVPbkContactStoreEvent::EContactChanged ) 
+		    {
+		    	PRINT ( _L("Change contact/group event received") );
+		    }
+		    else 
+		    {
+		    	PRINT ( _L("Delete contact/group event received") );
+		    }
+			
+			CVPbkContactIdConverter* converter = NULL;
+			
+		    TRAPD ( err, converter = CVPbkContactIdConverter::NewL( aContactStore ) );
+
+	        TInt32 contactId(-1);
+	        
+	        if ( err == KErrNotSupported )
+	        {
+	            // sim domain  
+	            // Pass the sim observer string in the next line
+	            TInt contactLocation =  iSimContactItems->Find(*aStoreEvent.iContactLink);	
+				if( KErrNotFound != contactLocation)
+				{
+				    // We are not removing from the array cache. If you try to fetch, 
+				    // then it will give an error			       
+				    TInt index = CreateCacheIDfromSimArrayIndex (contactLocation);
+				    
+	                iObserver->RemoveData(*iUri,index );
+		       	} 	               	           
+		               	           
+	        }
+	        else
+	        {
+	           // cntdb domain
+	           // Get contact id by mapping the link
+	           contactId = converter->LinkToIdentifier(*(aStoreEvent.iContactLink));
+	           
+	           // Remove the contact
+		       iObserver->RemoveData(*iUri, contactId);
+		    }
+		    
+		    delete converter;
+		    converter = NULL;
+		    
+	        if (( aStoreEvent.iEventType == TVPbkContactStoreEvent::EContactChanged ) ||
+	            ( aStoreEvent.iEventType == TVPbkContactStoreEvent::EGroupChanged ) )
+	        {
+	  		    // Add the contact
+	  		   iContactManager->RetrieveContactL( *(aStoreEvent.iContactLink),
+	  		                                                           *this );
+	        }
+	        	  		  
+			break;
+		}
+	}
+
+	PRINT ( _L("End CPcsContactStore::HandleStoreEventL") );
+}
+
+// ---------------------------------------------------------------------------
+//  Returns ths database URI
+// ---------------------------------------------------------------------------
+TDesC& CPcsContactStore::GetStoreUri()
+{
+  return *iUri;
+}
+
+// ---------------------------------------------------------------------------
+//  Callback Method. Called when one Retrieve operation is complete
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::VPbkSingleContactOperationComplete(
+        MVPbkContactOperationBase& aOperation, MVPbkStoreContact* aContact)
+{    
+    iFetchedContactCount++;
+
+			       
+	// Handle the fetched contact....
+	TRAPD(err, HandleRetrievedContactL(aContact) );
+	if( err != KErrNone)
+	{
+		iObserver->UpdateCachingStatus(*iUri, err);
+	}
+	
+	MVPbkContactOperationBase* Opr = &aOperation;
+	if ( Opr )
+	{
+		delete Opr;
+		Opr = NULL;
+	}
+	
+	// Update the iNextState variable to proper state
+	if( iFetchedContactCount == iAllContactLinksCount )
+	{
+	    // Fetch complete
+	    // Update the caching status
+		iObserver->UpdateCachingStatus(*iUri, ECachingComplete);
+		iNextState = EComplete;
+		IssueRequest();
+	}
+	else if ( (iFetchedContactCount % KLinksToFetchInOneGo) == 0 )
+	{
+	    // Fetch next block
+		iNextState = EFetchContactBlock;
+		IssueRequest();
+	}
+	
+}
+    
+// ---------------------------------------------------------------------------
+//  Callback Method.Called when one Retrieve operation fails.
+// ---------------------------------------------------------------------------
+void CPcsContactStore::VPbkSingleContactOperationFailed(
+        MVPbkContactOperationBase& /*aOperation*/, TInt /*aError*/ )
+{
+  	PRINT ( _L("Enter CPcsContactStore::VPbkSingleContactOperationFailed") );
+	iFetchedContactCount++;
+
+	// Update the iNextState variable to proper state
+	if( iFetchedContactCount == iAllContactLinksCount )
+	{
+		// Fetch complete
+		iObserver->UpdateCachingStatus(*iUri, ECachingComplete);
+		iNextState = EComplete;
+		IssueRequest();
+	}
+	else if ( (iFetchedContactCount % KLinksToFetchInOneGo) == 0 ) 
+	{
+		// Fetch next block
+		iNextState = EFetchContactBlock;
+		IssueRequest();
+	}
+	
+	PRINT ( _L("End CPcsContactStore::VPbkSingleContactOperationFailed") );
+}
+
+// ---------------------------------------------------------------------------
+// Handles the operations for a single contact after it is fetched
+// ---------------------------------------------------------------------------
+void CPcsContactStore::HandleRetrievedContactL(MVPbkStoreContact* aContact)
+{    
+    // Fill the contact link
+	MVPbkContactLink* tmpLink = aContact->CreateLinkLC();
+		
+    // If the link is null, then it is not put on the cleanup stack,
+    // so we need not pop in such a case
+    if( NULL == tmpLink )
+    {
+        delete aContact;
+        aContact = NULL;
+    	return;
+    }
+   
+    // Recover the URI
+    HBufC* storeUri = HBufC::NewL(aContact->ParentStore().StoreProperties().Uri().UriDes().Length());
+    storeUri->Des().Copy(aContact->ParentStore().StoreProperties().Uri().UriDes());
+        			
+	CPsData *phoneContact = CPsData::NewL();
+
+	
+	// Fill the contact id
+	CVPbkContactIdConverter* converter = NULL;
+	TRAPD ( err, converter = CVPbkContactIdConverter::NewL( aContact->ParentStore() ) );
+	
+	if ( err == KErrNotSupported )
+	{
+		// simdb domain	
+		PRINT ( _L("SIM domain data received") );
+			
+		TInt tempIndex =  iSimContactItems->Find(*tmpLink);	
+		
+		if( KErrNotFound == tempIndex)
+
+		    {
+		    	tempIndex = iSimContactItems->Count();
+	        iSimContactItems->AppendL(tmpLink);
+	      }
+	    //Create a dummy sim index and set it
+	    TInt simIndex = CreateCacheIDfromSimArrayIndex(tempIndex);
+	    phoneContact->SetId(simIndex);
+	    
+	    // Set the contact link 
+	    HBufC8* extnInfo = tmpLink->PackLC();
+	    phoneContact->SetDataExtension(extnInfo);
+	    CleanupStack::Pop();//extnInfo		      
+	    CleanupStack::Pop(); // tmpLink
+	}
+	else 
+	{
+	    // cntdb domain
+		TInt32 contactId = converter->LinkToIdentifier(*tmpLink);
+		phoneContact->SetId(contactId);		
+		CleanupStack::PopAndDestroy(); // tmpLink
+	}
+   	 
+	// Take the ownership
+	aContact->PushL();
+
+	MVPbkContactGroup* myContactGroup= aContact->Group();
+	
+	// The retrieved contact can be a contact item or a contact group, Handle accordingly
+	if ( NULL == myContactGroup )
+	{
+		// The fetched contact item (and not a contact group.)
+		GetDataForSingleContactL( *aContact, phoneContact );
+		//Add the data to the relevent cache through the observer
+		iObserver->AddData(*storeUri, phoneContact);
+	}
+	else
+	{  
+	    // Fetch the group name 
+	    HBufC* groupName = HBufC::NewL(myContactGroup->GroupLabel().Length());
+	    groupName->Des().Copy(myContactGroup->GroupLabel());
+	    TInt grpArrayIndex = -1; 
+	    for(TInt i =0; i  <iFieldsToCache.Count(); i++)
+	    {
+	    	if(iFieldsToCache[i] == R_VPBK_FIELD_TYPE_LASTNAME)
+         
+			 {
+			 grpArrayIndex = i;
+			 	
+			 }
+			 phoneContact->SetDataL(i,KNullDesC);
+	    }
+	    if(grpArrayIndex != -1)
+	    {
+	    	phoneContact->SetDataL(grpArrayIndex,groupName->Des());
+	    	storeUri->Des().Copy(KVPbkDefaultGrpDbURI);	    
+	    
+	
+	    
+	    
+        // Check for the contact in the group.
+	    MVPbkContactLinkArray* contactsContainedInGroup = myContactGroup->ItemsContainedLC();
+        for(TInt i = 0; i < contactsContainedInGroup->Count(); i++)
+		{
+			TInt grpContactId = converter->LinkToIdentifier(contactsContainedInGroup->At(i));
+			phoneContact->AddIntDataExtL(grpContactId);
+		}
+		CleanupStack::PopAndDestroy(); // contactsContainedInGroup
+ 
+ 		
+ 		//Add the data to the relevent cache through the observer
+	    iObserver->AddData(*storeUri, phoneContact);
+	 	}
+	    else
+	    {
+	    	//We do not add anything here since Lastname does not exists in cenrep
+	    	delete 	phoneContact;
+	    	phoneContact = NULL;
+	    }
+	    delete groupName;
+	    groupName = NULL;
+	}
+	
+	delete converter;
+	converter = NULL;
+
+	delete storeUri;
+    storeUri = NULL;
+    
+	CleanupStack::PopAndDestroy(aContact); // aContact
+}
+ 
+    
+// ---------------------------------------------------------------------------
+// Fetches the data from a particular contact 
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::GetDataForSingleContactL( MVPbkBaseContact& aContact,
+                                                 CPsData* aPhoneData )
+{      
+
+    for(TInt i =0; i < iFieldsToCache.Count(); i++)
+    {
+	    aPhoneData->SetDataL(i, KNullDesC);
+		AddContactFieldsL( aContact, iFieldsToCache[i], aPhoneData);			
+    }
+	
+}
+
+// ---------------------------------------------------------------------------
+// Add the data from contact fields
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::AddContactFieldsL( MVPbkBaseContact& aContact,
+                                          TInt afieldtype,
+                                          CPsData *aPhoneData)
+{
+	const MVPbkFieldType*  myContactDataField = 
+		iContactManager->FieldTypes().Find( afieldtype );
+
+	CVPbkBaseContactFieldTypeIterator* itr = 
+		CVPbkBaseContactFieldTypeIterator::NewLC( *myContactDataField, 
+		aContact.Fields() );	
+			
+	// Iterate through each of the data fields
+	while ( itr->HasNext() )
+	{
+		const MVPbkBaseContactField* field = itr->Next();
+
+	    if ( ( field->FieldData()).DataType() == EVPbkFieldStorageTypeText )
+		{
+			const MVPbkContactFieldTextData& data = 
+				MVPbkContactFieldTextData::Cast( field->FieldData() );
+			
+			//If the field exist in iFieldsToCache, then set it
+			for( TInt i = 0 ; i< iFieldsToCache.Count(); i++)
+			{
+				if(afieldtype == iFieldsToCache[i])
+				{	
+                    // Check if the field has any data entry. If so
+                    // concatenate the next data to the existing one.
+                    // A unit seperator is used to show that these are
+                    // two entries.
+                    HBufC* previousData = aPhoneData->Data(i);
+                    if( (previousData != NULL) && (previousData->Des().Length()> 1) )
+                    {
+                        HBufC* newData = HBufC::NewLC(data.Text().Length() + previousData->Des().Length() + 5);
+                        TPtr newDataPtr(newData->Des());
+                        newDataPtr.Append(previousData->Des());
+                        newDataPtr.Append(KSpaceCharacter);
+                        newDataPtr.Append(KUnitSeparator);
+                        newDataPtr.Append(KSpaceCharacter);
+                        newDataPtr.Append(data.Text());
+                        aPhoneData->SetDataL(i,*newData);
+                        CleanupStack::PopAndDestroy(); // newData
+                    }
+                    else
+                    {
+                        aPhoneData->SetDataL(i,data.Text());
+                    }
+				}			
+			}					
+		}
+	}
+	
+	CleanupStack::PopAndDestroy( itr ); 
+}
+
+// ---------------------------------------------------------------------------
+// Fetches the data from the vpbk using the contact links 
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::FetchlinksL()
+{		
+
+	PRINT1 ( _L("CPcsContactStore::Total contacts downloaded = %d"),
+	          iFetchedContactCount );
+	          						
+    TInt blockCount = iFetchedContactCount + KLinksToFetchInOneGo;
+    
+    if( blockCount >= iAllContactLinksCount)
+    	blockCount = iAllContactLinksCount;
+    
+	for(int cnt = iFetchedContactCount; cnt < blockCount; cnt++)
+	{	
+		// Retrieve the contact 
+		MVPbkContactLink* tempLink =iContactViewBase->CreateLinkLC(cnt);
+		iContactManager->RetrieveContactL( *tempLink, *this );
+		CleanupStack::PopAndDestroy();
+	}				
+
+}
+
+// ---------------------------------------------------------------------------
+// Implements the view ready function of MVPbkContactViewObserver
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::ContactViewReady(
+                MVPbkContactViewBase& aView ) 
+{
+    PRINT ( _L("Enter CPcsContactStore::ContactViewReady") );
+    iFs.Close();
+    aView.RemoveObserver(*this);
+    // Get the total number of contacts for this view
+    TRAPD(err,iAllContactLinksCount = aView.ContactCountL());
+    
+    if(err != KErrNone)
+    {
+    	PRINT( _L("CPcsContactStore::ContactViewReady - Unable to obtain contact count"));
+    	iNextState = EComplete;
+   		IssueRequest();
+   		return;
+    }
+    
+    PRINT1 ( _L("Total number of contacts for this view: %d"), iAllContactLinksCount);
+    if( iAllContactLinksCount == 0)
+    {
+        // No Contactsb to cache, hence update the status accordingly
+    	iObserver->UpdateCachingStatus(*iUri, ECachingComplete);
+    	iNextState = EComplete;
+   		IssueRequest();
+   		return;
+    }
+    iFetchedContactCount = 0;
+    
+    // Change the iNextState to fetch the contacts 
+    if( iContactViewReady == EFalse)
+    {
+    	iObserver->UpdateCachingStatus(*iUri, ECachingInProgress);
+    	iContactViewReady = ETrue;
+    	iNextState = EFetchContactBlock;
+   		IssueRequest();
+    }
+	
+	PRINT ( _L("End CPcsContactStore::ContactViewReady") );
+}
+
+// ---------------------------------------------------------------------------
+// Implements the view unavailable function of MVPbkContactViewObserver
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::ContactViewUnavailable(
+                MVPbkContactViewBase& /*aView*/ )  
+{
+    PRINT ( _L("Enter CPcsContactStore::ContactViewUnavailable") );
+    // Update the caching status to complete
+	iObserver->UpdateCachingStatus(*iUri, ECachingComplete);
+    iFs.Close();
+	PRINT ( _L("End CPcsContactStore::ContactViewUnavailable") );
+}
+
+// ---------------------------------------------------------------------------
+// Implements the add contact function of MVPbkContactViewObserver
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::ContactAddedToView(
+            MVPbkContactViewBase& /*aView*/, 
+            TInt /*aIndex*/, 
+            const MVPbkContactLink& /*aContactLink*/ ) 
+{
+}
+
+// ---------------------------------------------------------------------------
+// Implements the remove contact function of MVPbkContactViewObserver
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::ContactRemovedFromView(
+                MVPbkContactViewBase& /*aView*/, 
+                TInt /*aIndex*/, 
+                const MVPbkContactLink& /*aContactLink*/ )  
+{
+}
+
+// ---------------------------------------------------------------------------
+// Implements the view error function of MVPbkContactViewObserver
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::ContactViewError(
+            MVPbkContactViewBase& /*aView*/, 
+            TInt /*aError*/, 
+            TBool /*aErrorNotified*/ )  
+{
+}
+
+// ---------------------------------------------------------------------------
+// Creates the contact view to fetch data from this store
+// --------------------------------------------------------------------------- 
+void CPcsContactStore::CreateContactFetchViewL()
+{
+	PRINT ( _L("Enter CPcsContactStore::CreateContactFetchViewL") );
+	
+	// Create the view definition
+    CVPbkContactViewDefinition* viewDef = CVPbkContactViewDefinition::NewL();
+	CleanupStack::PushL( viewDef );
+
+  // Create the View Name for the view
+  // The views are named as PCSView_<uri>		
+	HBufC* viewName = HBufC::NewL(KBufferMaxLen);
+	viewName->Des().Append(KPcsViewPrefix);
+	viewName->Des().Append(iUri->Des());
+	CleanupStack::PushL(viewName);
+
+	// Set the Uri
+	if ( iUri->Des().CompareC(KVPbkDefaultGrpDbURI) == 0)
+	{	    
+		// Special Handling required for Groups Data Store
+		// Read the resource file and create the sort order
+		// The sort order created is used in view creation.
+		
+		User::LeaveIfError( iFs.Connect() );
+		TPtrC driveLetter = TParsePtrC( RProcess().FileName() ).Drive();
+		TBuf<KMaxFileName> resourceFileName;
+		RResourceFile iResourceFile;
+		
+		//Read the path of the resource file
+		resourceFileName.Copy( driveLetter );
+		resourceFileName.Append( KDC_RESOURCE_FILES_DIR );
+		resourceFileName.Append( KResourceFileName );
+		
+		//Open the resource file
+	  	BaflUtils::NearestLanguageFile( iFs, resourceFileName );
+	    iResourceFile.OpenL( iFs, resourceFileName );
+	  	iResourceFile.ConfirmSignatureL(0);
+	
+
+        //Read resource	             
+        HBufC8* textbuffer = iResourceFile.AllocReadL(R_SORTORDER_LASTNAME);
+        CleanupStack::PushL(textbuffer);
+        
+        // Set the resource information into the reader
+        TResourceReader reader;
+        reader.SetBuffer(textbuffer);
+	
+	    // Create sort order with only last name
+	    CVPbkSortOrder* sortOrder = CVPbkSortOrder::NewL( reader, 
+	                                                      iContactManager->FieldTypes() );
+
+	    CleanupStack::PushL(sortOrder);
+		
+		// Set the groups type
+		viewDef->SetUriL(KVPbkDefaultCntDbURI);
+		viewDef->SetType( EVPbkGroupsView );
+
+		// Set name for the view
+		viewDef->SetNameL( *viewName );	
+		
+		// Create the contact view
+		iContactViewBase = iContactManager->CreateContactViewLC( 
+		                         *this, 
+		                         *viewDef, 
+		                         *sortOrder);
+
+        CleanupStack::Pop(); // iContactViewBase
+        CleanupStack::PopAndDestroy(sortOrder);	
+        CleanupStack::PopAndDestroy(textbuffer);
+    
+    	// Close the resouce File
+        iResourceFile.Close();                        
+	
+	}
+	else
+	{
+	
+		// Create sort order with the fields from cenrep
+		CreateSortOrderL(iContactManager->FieldTypes());
+		
+		CVPbkSortOrder* sortOrderPhone = CVPbkSortOrder::NewL(*iSortOrder);
+	    CleanupStack::PushL(sortOrderPhone);
+	    
+		// set contacts type
+		viewDef->SetUriL(iUri->Des());
+		viewDef->SetType( EVPbkContactsView );
+			
+		// Set name for the view
+		viewDef->SetNameL( *viewName );	
+		__LATENCY_MARK ( _L("CPcsContactStore::CreateContactFetchViewL===== create view start") );
+    	iContactViewBase = iContactManager->CreateContactViewLC( 
+		                         *this, 
+		                         *viewDef, 
+		                         *sortOrderPhone );
+		__LATENCY_MARKEND ( _L("CPcsContactStore::CreateContactFetchViewL ==== create view end") );	                         
+        
+        CleanupStack::Pop(); // iContactViewBase	
+        CleanupStack::PopAndDestroy(sortOrderPhone);	
+	}		 
+		                             
+    CleanupStack::PopAndDestroy( viewName );	
+    CleanupStack::PopAndDestroy( viewDef );	
+    
+    PRINT ( _L("End CPcsContactStore::CreateContactFetchViewL") );
+}
+
+// ---------------------------------------------------------------------------------
+// Implements cancellation of an outstanding request.
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::DoCancel() 
+{    
+}
+
+// ---------------------------------------------------------------------------------
+// The function is called by the active scheduler 
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::RunL() 
+{
+	TRequestStatus timerStatus;
+	iTimer.Cancel();
+	
+    switch( iNextState)
+    {
+	   	case ECreateView :
+			CreateContactFetchViewL();
+		    break;
+   					      	
+	   	case EFetchContactBlock:
+	   		PRINT ( _L("Issuing the fetch request for next block") );
+			FetchlinksL();
+			
+			// Delay the next fetch since contact fetch is CPU intensive,
+			// this will give other threads a chance to use CPU
+			iTimer.After( timerStatus, 100000); // 100 milliseconds
+			User::WaitForRequest( timerStatus );
+			break;
+	   						
+	   	case EComplete:
+		    PRINT ( _L("Contacts Caching FINISHED") );
+		    break;
+    }
+}
+
+// ---------------------------------------------------------------------------------
+// Called in case of any errros 
+// ---------------------------------------------------------------------------------
+TInt CPcsContactStore::RunError(TInt /*aError*/) 
+{
+	 PRINT ( _L(" Enter CPcsContactStore:: CPcsContactStore::RunError()") );
+
+	 PRINT1 ( _L(" CPcsContactStore:: RunError().  Completing caching in contacts store %S with status ECachingCompleteWithErrors "), &(iUri->Des()));
+   iObserver->UpdateCachingStatus(*iUri, ECachingCompleteWithErrors);
+ 	 PRINT ( _L(" End CPcsContactStore:: CPcsContactStore::RunError()") );
+	return KErrNone;
+}
+
+// ---------------------------------------------------------------------------------
+// Read the fields to cache from the central repository
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::ReadFieldsToCacheFromCenrepL()
+{
+	CRepository *repository = CRepository::NewL( KCRUidPSContacts );
+
+    // Read the data fields from cenrep
+    for (TInt i(KCenrepFieldsStartKey); i < KCenrepFieldsStartKey + KCenrepNumberOfFieldsCount; i++ )
+    {
+	TInt fieldToCache (-1);
+	    TInt err = repository->Get(i, fieldToCache );
+	    
+	    if ( KErrNone != err )
+	    {
+		    break;
+	    }
+	    if ( fieldToCache != 0 )
+	    {
+		    iFieldsToCache.Append(fieldToCache);
+	    }
+	    		
+    }
+    
+    delete repository;
+    
+}
+
+// ---------------------------------------------------------------------------------
+// Creates a dummy id for the cache
+// ---------------------------------------------------------------------------------
+
+TInt CPcsContactStore::CreateCacheIDfromSimArrayIndex(TInt aSimId)
+{
+	return (KSimStoreOffset + aSimId);
+}
+
+// ---------------------------------------------------------------------------------
+// Issues request to active object to call RunL method
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::IssueRequest()
+{
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete( status, KErrNone );
+	SetActive();
+}
+// Creates a sort order depending on the fields specified in the cenrep
+// when calling this function pass the masterList (i.e list containing all the
+// vpbk fields)
+// ---------------------------------------------------------------------------------
+void CPcsContactStore::CreateSortOrderL(const MVPbkFieldTypeList& aMasterList)
+{
+		
+	TInt count = aMasterList.FieldTypeCount();
+	
+	// loop through the master list and find the types that are supported
+	for(TInt i = 0; i < count; i++)
+	{
+		const MVPbkFieldType& fieldType = aMasterList.FieldTypeAt(i);
+		TInt resourceId = fieldType.FieldTypeResId();
+		// if the field type is supported
+		// then append MVPbkFieldType to sortOrder
+		for(TInt j =0; j < iFieldsToCache.Count(); j++)
+		{
+			if(iFieldsToCache[j] == resourceId)
+			{
+				iSortOrder->AppendL(fieldType);
+			}
+		}
+		
+		if(iSortOrder->FieldTypeCount() == iFieldsToCache.Count())
+		{
+			break;
+		}
+	}
+	
+}
+
+// End of file