phonebookengines/contactsmodel/cntplsql/src/cntpplviewsession.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookengines/contactsmodel/cntplsql/src/cntpplviewsession.cpp	Wed Sep 01 12:29:52 2010 +0100
@@ -0,0 +1,749 @@
+// 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 "cntpplviewmanager.h"
+#include "dbsqlconstants.h"
+#include "cntpersistenceutility.h"
+#include <cntfldst.h>
+
+const TInt KCachedPrepareTimeOut = 1000000; //1 second
+
+/**
+Object factory method.
+*/
+CCntPplViewSession* CCntPplViewSession::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs)
+	{
+	CCntPplViewSession* viewSession = new (ELeave) CCntPplViewSession(aContactsFile, aContactProperties, aSelectAllFields, aViewId, aViewPrefs);
+	CleanupStack::PushL(viewSession);
+	viewSession->ConstructL(aTextDef);
+	CleanupStack::Pop(viewSession);
+	return viewSession;
+	}
+
+	
+/**
+CCntPplViewSession first phase constructor.
+*/
+CCntPplViewSession::CCntPplViewSession(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, TContactViewPreferences aViewPrefs)
+:  	CTimer(CActive::EPriorityIdle),
+    iViewId(aViewId),
+	iContactProperties(aContactProperties),
+    iContactsFile(aContactsFile),
+	iSqlSmtSelectAllFieldsById(aSelectAllFields),
+	iViewPrefs(aViewPrefs),
+	iRSqlStatementReady(EFalse),
+	iCachedSqlStatementReady(EFalse)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+	
+/**
+CCntPplViewSession destructor.
+*/
+CCntPplViewSession::~CCntPplViewSession()
+	{
+	Deque();
+	iContactsFile.RemoveSqlDBObserverL( *this );
+    if ( iRSqlStatementReady )
+        {
+        iRSqlStatement.Close();
+        iRSqlStatementReady = EFalse;
+        }
+
+    if ( iCachedSqlStatementReady )
+        {
+        iCachedSqlStatement.Close();
+        iCachedSqlStatementReady = EFalse;
+        }
+	
+	delete iCntSqlStatement;
+	delete iTextDef;
+	}
+
+	
+/**
+CCntPplViewSession second phase constructor.
+*/
+void CCntPplViewSession::ConstructL(const CContactTextDef& aTextDef)
+	{
+	//Constructing iCntSqlStatement, iTextDef, and iIsFastAccessFieldsOnly
+	//by simply call ChangeSortOrderL
+	CTimer::ConstructL();
+    iContactsFile.AddSqlDBObserverL( *this );
+    ChangeSortOrderL( aTextDef );
+	}	
+
+	
+/**
+Change the sorting order/text definition. It should be always called when 
+there is not an iteration started in persistence layer.
+
+@param aTextDef the new text definition to be used in the view session.
+*/
+void CCntPplViewSession::ChangeSortOrderL(const CContactTextDef& aTextDef)
+	{
+	//Cleanup the cached Prepare statement as the sort order will be changed
+	Cancel();
+    CleanupCachedPrepareStatement();
+	
+	//Copy the text definition
+	CContactTextDef* textDef = CContactTextDef::NewLC();
+	const TInt KTextDefCount = aTextDef.Count();
+	for (TInt index = 0; index < KTextDefCount; ++index)
+		{
+		textDef->AppendL(TContactTextDefItem(aTextDef.At(index).iFieldType));
+		}
+	
+	// Create select statement on contact table
+	TCntSqlStatementType statementType(ESelect, KSqlContactTableName());
+	CCntSqlStatement* sqlSmt = TSqlProvider::GetSqlStatementL(statementType);
+	CleanupStack::PushL(sqlSmt);
+	
+	// Always select id, type flags.	
+	sqlSmt->SetParamL(KContactId(), KSpace());
+	sqlSmt->SetParamL(KContactTypeFlags(), KSpace());
+	
+	//Go through text definition to construct select statement.
+	TBool isFastAccessOnly = ETrue;
+	for(TInt ii = 0; ii < KTextDefCount; ++ii)
+		{
+		const TDesC& KColunmName = TCntPersistenceUtility::GetFastAccessColumnNameById(aTextDef.At(ii).iFieldType.iUid);
+		if(KColunmName.Length() > 0) 
+			{
+			sqlSmt->SetParamL(KColunmName, KSpace());
+			}
+		else
+			{
+			isFastAccessOnly = EFalse;		
+			}
+		}
+	
+	if(!isFastAccessOnly)
+		{
+		//Fields in text blob are needed, add text fields header and
+        //text blob columns in the select statement.		
+		sqlSmt->SetParamL(KContactTextFieldHeader(), KSpace());
+		sqlSmt->SetParamL(KContactTextFields(), KSpace());
+		}
+
+	CleanupStack::Pop(2, textDef); // sqlSmt, textDef.
+	
+	delete iCntSqlStatement;
+	iCntSqlStatement = sqlSmt;
+	
+	delete iTextDef;
+	iTextDef = textDef;
+	
+	iIsFastAccessFieldsOnly = isFastAccessOnly;
+	}
+	
+
+/**
+Preparing sql statement for the coming iteration requests from upper layer.
+Caller has the responsibilty of controling the lifecycle of the iteration 
+session -- when it starts and stop.  
+*/
+void CCntPplViewSession::BeginIterateL()
+	{
+	if (! iContactsFile.IsOpened())
+		{
+		User::Leave(KErrInUse);
+		}
+	
+	if ( iRSqlStatementReady )
+        {
+        iRSqlStatement.Close();
+        iRSqlStatementReady = EFalse;
+        }
+		
+	// we don't need condition for iterating database.
+	iCntSqlStatement->ClearCondition();
+	
+	iRSqlStatement.PrepareL(iContactsFile.NamedDatabase(), iCntSqlStatement->SqlStringL());
+	iRSqlStatementReady = ETrue;
+	}
+
+	
+/**
+Stop iteration by releasing iteration sql statement.
+*/
+void CCntPplViewSession::EndIterate()
+    {
+    if ( iRSqlStatementReady )
+        {
+        iRSqlStatement.Close();
+        iRSqlStatementReady = EFalse;
+        }
+    }
+
+	
+/**
+Get next view contact object from iterating sql statement.
+
+@return CViewContact object or NULL if iteration reachs end of rows.
+*/
+CViewContact* CCntPplViewSession::NextItemL(TContactViewPreferences aViewPrefs)
+	{
+	if(!iRSqlStatementReady)
+		{
+		//Iteration has not started
+		BeginIterateL();	
+		}
+	
+	return CreateViewItemL(iRSqlStatement, *iCntSqlStatement, aViewPrefs);
+	}
+
+	
+/**
+Get view contact object based on given contact id.
+
+@return CViewContact object or NULL if there is not such a contact.
+*/
+CViewContact* CCntPplViewSession::ItemAtL(TContactItemId aContactId)
+	{
+	//Cancel the timer so that the cached Prepare statement would not be deleted.
+	Cancel();
+	
+	CViewContact* viewContact = NULL;
+	
+	TRAPD(err, viewContact = doItemAtL(aContactId));
+    if(err != KErrNone)
+        {
+        CleanupCachedPrepareStatement();
+    	User::Leave(err);	
+        }
+    	
+	//Reset the timer
+	After(KCachedPrepareTimeOut);
+	return viewContact;
+	}
+
+
+/**
+The method to do the real work of get view contact object based on given contact id.
+
+@return CViewContact object or NULL if there is not such a contact.
+*/
+CViewContact* CCntPplViewSession::doItemAtL(TContactItemId aContactId)
+    {
+    if (! iContactsFile.IsOpened())
+    	{
+    	User::Leave(KErrInUse);
+    	}
+    
+	if ( !iCachedSqlStatementReady )
+		{
+		//iCacheSqlStatement is just for ItemAt while iRSqlStatement is used for iteration 
+		//and maintained by BeginIterateL and EndIterateL.
+    	iCntSqlStatement->SetConditionL(KSelectCondition_SearchForContactId()); 
+		
+		//Create a new sqlstatment and cache its Prepare statement.	
+		iCachedSqlStatement.PrepareL(iContactsFile.NamedDatabase(),  iCntSqlStatement->SqlStringL());
+		iCachedSqlStatementReady = ETrue;
+		}
+		
+	User::LeaveIfError(iCachedSqlStatement.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition.	
+
+	CViewContact* viewContact = CreateViewItemL(iCachedSqlStatement, *iCntSqlStatement, iViewPrefs);
+	
+	// Adding this to the cleanup stack, because coverity recons that "iCachedSqlStatement->Reset();" can leave, and it's probably right
+	CleanupStack::PushL(viewContact);
+	iCachedSqlStatement.Reset();
+
+	// Pop it back off the cleanup stack, and hand over ownership
+	CleanupStack::Pop(viewContact);
+	return viewContact;
+    }
+
+
+/**
+Clean up the cached prepare statement.
+*/
+void CCntPplViewSession::CleanupCachedPrepareStatement()
+    {
+    if ( iCachedSqlStatementReady )
+        {
+        iCachedSqlStatement.Close();
+        iCachedSqlStatementReady = EFalse;
+        }
+    }
+
+/**
+CTimer callback funtion, the cached Prepare statement would be de-cached if ItemAtL is not called
+during the time interval defined by KCachedPrepareTimeOut.
+*/
+void CCntPplViewSession::RunL()
+    {
+    CleanupCachedPrepareStatement();
+    }
+	
+	
+/**
+Create view contact object based on given sql statement.
+
+@return CViewContact object or NULL the contact is not found.
+*/
+CViewContact* CCntPplViewSession::CreateViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
+	{
+	if (! iContactsFile.IsOpened())
+		{
+		User::Leave(KErrInUse);
+		}
+	
+	CViewContact* viewContact = InitialiseViewItemL(aSqlStmt, aCntSqlStmt, aViewPrefs);
+	if(!viewContact)
+		{
+		//Couldn't find the contact.
+		return NULL;
+		}
+	
+	CleanupStack::PushL(viewContact);
+	if(viewContact->ContactType() == CViewContact::EContactItem)
+		{
+		FillViewItemL(*viewContact, aSqlStmt, aViewPrefs);
+		}
+	
+	TUid typeUid = GetContactFieldMatchUid(*viewContact, aViewPrefs);	
+	if(typeUid != KUidContactFieldNone)
+		{
+		RSqlStatement contactSqlStmt;
+		CleanupClosePushL(contactSqlStmt);
+		
+		/* we have to reload the row from SQL database to cache in text header and text blob */ 	
+		contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(),  iSqlSmtSelectAllFieldsById.SqlStringL());
+		User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, viewContact->Id())); //Bind item id into the condition.	
+		
+		TInt err = contactSqlStmt.Next();
+		if(err == KSqlAtEnd)
+			{
+			//Should never be here, we found it in InitialiseViewItemL 
+			//but couldn't find the same contact in same database.
+			CleanupStack::PopAndDestroy(viewContact);
+			return NULL;
+			}			
+			
+		User::LeaveIfError(err);
+		
+		/* set first field with possible content for group or unsorted contact */	
+		CContactDatabase::TTextFieldMinimal buf;
+		TextFieldL(contactSqlStmt, iSqlSmtSelectAllFieldsById, iContactProperties.SystemTemplateL(), typeUid, buf);
+		viewContact->SetFirstFieldForBlankContactL(buf);
+		CleanupStack::PopAndDestroy(&contactSqlStmt);
+		} //if(typeUid != 0)
+	
+	CleanupStack::Pop(viewContact);
+	return viewContact;
+	}
+
+	
+/**
+Filling content for the given view contact object.
+
+@param aViewContact reference to the view contact object to be filled
+@param aSqlStmt the sql statement which contains the retrieved content for the view object. 
+*/
+void CCntPplViewSession::FillViewItemL(CViewContact& aViewContact, RSqlStatement& aSqlStmt, const TContactViewPreferences& aViewPrefs)
+	{
+	if(iIsFastAccessFieldsOnly)
+		{
+		//The view gets fields only from fast access columns	
+		const TInt KTextDefCount = iTextDef->Count();
+		for(TInt index = 0; index < KTextDefCount; ++index)
+			{
+			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(iTextDef->At(index).iFieldType.iUid);
+			ASSERT(KColumnName.Length() > 0);
+			
+			TPtrC fieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName));
+   			AddFieldInViewContactL(aViewContact, fieldPtrC, aViewPrefs);
+			} //for
+		}
+	else
+		{
+		TBool searchFastAccessFields = EFalse;
+		
+		// iTextDef contains the fields that should be included in the view.
+		// The array of all the field objects in a contact item is returned from
+		// the Contacts table.  
+		RPointerArray<CContactItemField> fields;
+		CleanupStack::PushL(TCleanupItem(TCntPersistenceUtility::ResetAndDestroyRPointerArray, &fields));
+		
+		TPtrC8 textHeader;
+		aSqlStmt.ColumnBinary(iCntSqlStatement->ParameterIndex(KContactTextFieldHeader()), textHeader);
+		RDesReadStream textHeaderStream(textHeader);
+		CleanupClosePushL(textHeaderStream);
+        CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
+        
+    	RStoreReadStream textHeaderStoreStream;
+    	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
+        
+		TPtrC textFieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KContactTextFields()));
+		HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
+			
+		TCntPersistenceUtility::ReadTextBlobL(textHeaderStoreStream, textFieldsBuf, *iTextDef, iContactProperties.SystemTemplateL(), fields, searchFastAccessFields);
+		CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
+		
+		// Loop through fields, checking for fields from fast access fields, and add 
+		// the fields to the view contact object.
+		const TInt KFieldsNumMax = fields.Count();
+		for(TInt fieldsIndex = 0; fieldsIndex < KFieldsNumMax; ++fieldsIndex)
+			{
+			// this doesn't own the instance stored in fields array.
+			CContactItemField* itemField = fields[fieldsIndex];
+
+			if(itemField == NULL)
+				{
+				aViewContact.AddFieldL(KNullDesC);
+				continue;
+				}
+
+			// The array of fields retrieved from the text fields blob does not
+			// contain the text data Fast Access fields. If the searchFastAccessFields 
+			// flags have been set then get the data from Fast Access columns
+			// before adding the data to the view.
+			TPtrC fieldText;
+			if(searchFastAccessFields && itemField->ContentType().FieldTypeCount() > 0)
+				{
+				//Check the field name of the first field type(key field type) 
+				//in the field's field types array
+    			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(itemField->ContentType().FieldType(0).iUid);
+				if(KColumnName.Length() > 0)
+					{
+					//this is a fast access field.
+					fieldText.Set(aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName)));
+					}
+				else
+					{
+					fieldText.Set(itemField->TextStorage()->Text());
+					}					
+				}
+			else
+				{
+				fieldText.Set(itemField->TextStorage()->Text());
+				}
+			
+			AddFieldInViewContactL(aViewContact, fieldText, aViewPrefs);
+			}
+		
+		CleanupStack::PopAndDestroy(&fields);
+		}
+	}
+
+	
+/**
+Initialise requested view contact object based on given parameters:
+ 1. search the contact in contact table.
+ 2. fill in contact type and hint to the view contact object.
+
+@param aSqlStmt      reference to a RSqlStatement to be read in data 
+@return initialized CViewContact object or NULL if reached end of rows.
+*/
+CViewContact* CCntPplViewSession::InitialiseViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
+	{
+	CViewContact* viewContact = NULL;
+	
+    while(viewContact == NULL)
+	    {
+    	TInt err = aSqlStmt.Next();
+    	 
+    	if(err == KSqlAtEnd)
+    	    {
+    	    return NULL;
+    	    }
+    	    
+       	User::LeaveIfError(err);
+       	
+    	TInt typeFlags = aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactTypeFlags()));
+    	TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags);
+    	
+        if(!ContactCorrectType(contactTypeUid, aViewPrefs))
+            {
+            //The contact type doesn't match the view prefreference
+            continue;
+            }
+    	
+    	viewContact = CViewContact::NewLC(KNullContactId);
+    	
+    	/* Got a row and add common fields for both Groups and Contact view items. */
+    	viewContact->SetId(aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactId())));
+    	viewContact->SetContactHint(TCntPersistenceUtility::TypeFlagsToHint(typeFlags));
+    	viewContact->SetContactTypeUid(contactTypeUid);
+    	
+    	
+    	if(contactTypeUid == KUidContactGroup)
+    		{
+    		// Groups don't require all the field types to be set.
+    		viewContact->SetContactType(CViewContact::EGroup);
+    		}
+    	else
+    		{
+    		// All other contact types do require field types to be set.
+    		viewContact->SetContactType(CViewContact::EContactItem);
+    		}
+
+    	CleanupStack::Pop(viewContact);		
+	    }
+   	
+	return viewContact;    
+	}	
+
+	
+/**
+Check if the retrieved view contact is group or unsorted contact, if so return suitable field 
+match uid in order to fill in a possible text for the contact: 
+For group contact    -- find template label.
+For unsorted contact -- find first not none field.
+
+@param aViewContact     reference to the retrieved view contact object.
+@param aViewPreferences the view preferences made by client.
+ 
+@return suitable match uid or KUidContactFieldNone if it's not group or unsorted contact.
+*/
+TUid CCntPplViewSession::GetContactFieldMatchUid(const CViewContact& aViewContact, const TContactViewPreferences& aViewPreferences)	
+	{
+	TUid typeUid = KUidContactFieldNone;
+	if(aViewContact.ContactType() == CViewContact::EGroup && (aViewPreferences & (EGroupsOnly | EContactAndGroups)))
+		{
+		// Check for group view contact type.  This type of view contact uses the
+		// template label field to populate the first view contact field.
+		typeUid = KUidContactFieldTemplateLabel;
+		}
+	else if(!aViewContact.IsSortable() && (aViewPreferences & (EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd)) == 0)		
+		{
+		// None of the sort fields contained any data.  We want this contact to
+		// be sorted by the first bit of text we find so we need to retrieve the
+		// first text available from the contact and use this to populate the
+		// first view contact field.
+		typeUid = KUidContactFieldMatchAll;
+		}
+	return typeUid;	
+	}
+
+	
+/**
+Refine the field content and add the refined content to the given view contact object.
+ 
+@param aViewContact     reference to the retrieved view contact object.
+@param aFieldPtrC    	The actual field content read from database.
+@param aViewPreferences The view preferences for how to format the content. 
+*/
+void CCntPplViewSession::AddFieldInViewContactL(CViewContact& aViewContact, TPtrC& aFieldPtrC, const TContactViewPreferences& aViewPreferences)
+	{
+	_LIT(KBlank," ");
+	
+	// Truncate to 64 if necessary.
+	TPtr ptr(const_cast<TUint16*>(aFieldPtrC.Ptr()), KTextFieldMinimalLength);
+	if(aFieldPtrC.Length() > KTextFieldMinimalLength) 
+		{
+		ptr.SetLength(KTextFieldMinimalLength); 
+		}
+	else
+		{
+		ptr.SetLength(aFieldPtrC.Length());
+		}
+		
+	// Add the field to the view.
+	if((ptr.Length() == 0) ||
+	   (ptr.Length() == 1 && (aViewPreferences & ESingleWhiteSpaceIsEmptyField) && ptr.Compare(KBlank)==KErrNone))
+		{
+		/* empty field */
+		aViewContact.AddFieldL(KNullDesC);
+		} 
+	else
+		{
+		aViewContact.AddFieldL(ptr);
+		}
+	}
+
+/** 
+Retrieve the field text for the given field type and contact item ID.
+
+The behaviour differs when a specific field type is not given i.e. when
+aFieldType is KUidContactFieldMatchAll:
+
+- First tries to find an email for the given contact item ID.
+- If there is no email then it retrieves the first entry in Fast Access fields
+for the given contact item ID.
+- If there is no Fast Access fields then it retrieves the first entry in the
+text fields blob for the given contact item ID.
+
+Text for all other field types are retrieved from the text fields blob.
+
+The caller must determine that the given contact item ID exists before calling
+this method.
+*/
+void CCntPplViewSession::TextFieldL(RSqlStatement& aSqlStatement, const CCntSqlStatement& aCntSqlStmt, const CContactTemplate& aSystemTemplate, TFieldType aFieldType, TDes& aText)
+	{
+	TPtrC8 textHeader;
+	aSqlStatement.ColumnBinary(aCntSqlStmt.ParameterIndex(KContactTextFieldHeader()), textHeader);
+	RDesReadStream textHeaderStream(textHeader);
+	CleanupClosePushL(textHeaderStream);	
+    CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
+    
+	RStoreReadStream textHeaderStoreStream;
+   	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
+
+	TPtrC textFieldPtrC = aSqlStatement.ColumnTextL(aCntSqlStmt.ParameterIndex(KContactTextFields()));
+	HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
+	
+	if(aFieldType == KUidContactFieldMatchAll)
+		{
+		if (TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText) == EFalse)
+			{
+			CContactDatabase::TTextFieldMinimal	fastAccessText;
+			if (HasTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, fastAccessText))
+				{
+				aText.Copy(fastAccessText);		
+				}
+			}
+		} 
+	else
+		{
+		if (SpecificTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, aFieldType, aText) == EFalse)
+			{
+			TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText);
+			}
+		}
+		
+	CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
+	}
+
+
+/**
+The first text field in the Fast Access fields is found and returned via the
+parameter aText.
+
+@param aCntItemId The contact ID for which the first text field is required.
+@param aText On return contains the text for the field of the first Identity
+text field.
+
+@return ETrue if a Fast Access text field was found, EFalse otherwise.
+*/
+TBool CCntPplViewSession::HasTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, TDes& aText)
+	{
+	for(TInt ii = EGivenName; ii <= ECompanyNamePrn; ++ii)
+		{
+		const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(KFastAccessFieldUids[ii]);
+		TPtrC identText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
+		if(identText.Length() > 0)
+			{
+			TCntPersistenceUtility::CopyMinFieldText(identText, aText);
+			return ETrue;
+			}
+		}
+	return EFalse;
+	}
+
+	
+/**
+Checks if the given field type is in the Fast Access fields and if so the field text
+is returned via the parameter aText.
+
+@param aCntItemId The contact ID for which the specific text field is required.
+@param aText On return contains the field text for the first Fast Access fields
+with field type aFieldType.
+@param aFieldType The specific field requested.
+
+@return ETrue if the specific fast access text field was found, EFalse otherwise.
+*/
+TBool CCntPplViewSession::SpecificTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, const TFieldType aFieldType, TDes& aText)
+	{
+    const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(aFieldType.iUid);
+	if(KColumnName.Length() > 0)
+		{
+		// This is a fast access field.
+		TPtrC fastAccessText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
+		TCntPersistenceUtility::CopyMinFieldText(fastAccessText, aText);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+	
+/**
+Get view session id
+
+@return the view session id assigned to the session.
+*/
+TInt CCntPplViewSession::ViewId() const
+	{
+	return iViewId;
+	}
+
+
+TBool CCntPplViewSession::ContactCorrectType(TUid aContactTypeUid, TContactViewPreferences aTypeToInclude)
+    {
+    TBool correctType = EFalse;
+
+    if (aContactTypeUid == KUidContactCard)
+        {
+        if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly)))
+            {
+            correctType = ETrue;
+            }
+        }
+    else if (aContactTypeUid == KUidContactOwnCard)
+        {
+        if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly | EContactCardsOnly)))
+            {
+            correctType = ETrue;
+            }
+        }
+    else if (aContactTypeUid == KUidContactGroup)
+        {
+        if (aTypeToInclude & (EGroupsOnly | EContactAndGroups))
+            {
+            correctType = ETrue;
+            }
+        }
+    else if (aContactTypeUid == KUidContactICCEntry)
+        {
+        if (aTypeToInclude & (EICCEntriesOnly | EICCEntriesAndContacts))
+            {
+            correctType = ETrue;
+            }
+        }
+
+    return correctType;
+    }
+
+	
+/**
+ * Close the resource which is running and depends on RSqlDatabase 
+ * that will be closed in CPplContactsFile.
+ */
+void CCntPplViewSession::OnCloseL()
+    {
+
+    if ( iRSqlStatementReady )
+        {
+        iRSqlStatement.Close();
+        iRSqlStatementReady = EFalse;
+        }
+
+    if ( iCachedSqlStatementReady )
+        {
+        iCachedSqlStatement.Close();
+        iCachedSqlStatementReady = EFalse;
+        }
+
+    }
+
+