phonebookengines/contactsmodel/cntplsql/src/cntpplviewsession.cpp
branchRCL_3
changeset 63 f4a778e096c2
child 64 c1e8ba0c2b16
equal deleted inserted replaced
62:5b6f26637ad3 63:f4a778e096c2
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @internalComponent
       
    19  @released
       
    20 */
       
    21 #include "cntpplviewmanager.h"
       
    22 #include "dbsqlconstants.h"
       
    23 #include "cntpersistenceutility.h"
       
    24 #include <cntfldst.h>
       
    25 
       
    26 const TInt KCachedPrepareTimeOut = 1000000; //1 second
       
    27 
       
    28 /**
       
    29 Object factory method.
       
    30 */
       
    31 CCntPplViewSession* CCntPplViewSession::NewL(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, const CContactTextDef& aTextDef, const TContactViewPreferences aViewPrefs)
       
    32 	{
       
    33 	CCntPplViewSession* viewSession = new (ELeave) CCntPplViewSession(aContactsFile, aContactProperties, aSelectAllFields, aViewId, aViewPrefs);
       
    34 	CleanupStack::PushL(viewSession);
       
    35 	viewSession->ConstructL(aTextDef);
       
    36 	CleanupStack::Pop(viewSession);
       
    37 	return viewSession;
       
    38 	}
       
    39 
       
    40 	
       
    41 /**
       
    42 CCntPplViewSession first phase constructor.
       
    43 */
       
    44 CCntPplViewSession::CCntPplViewSession(CPplContactsFile& aContactsFile, const CLplContactProperties& aContactProperties, CCntSqlStatement& aSelectAllFields, TInt aViewId, TContactViewPreferences aViewPrefs)
       
    45 :  	CTimer(CActive::EPriorityIdle),
       
    46     iViewId(aViewId),
       
    47 	iContactProperties(aContactProperties),
       
    48     iContactsFile(aContactsFile),
       
    49 	iSqlSmtSelectAllFieldsById(aSelectAllFields),
       
    50 	iViewPrefs(aViewPrefs),
       
    51 	iRSqlStatementReady(EFalse),
       
    52 	iCachedSqlStatementReady(EFalse)
       
    53 	{
       
    54 	CActiveScheduler::Add(this);
       
    55 	}
       
    56 
       
    57 	
       
    58 /**
       
    59 CCntPplViewSession destructor.
       
    60 */
       
    61 CCntPplViewSession::~CCntPplViewSession()
       
    62 	{
       
    63 	Deque();
       
    64 	iContactsFile.RemoveSqlDBObserverL( *this );
       
    65     if ( iRSqlStatementReady )
       
    66         {
       
    67         iRSqlStatement.Close();
       
    68         iRSqlStatementReady = EFalse;
       
    69         }
       
    70 
       
    71     if ( iCachedSqlStatementReady )
       
    72         {
       
    73         iCachedSqlStatement.Close();
       
    74         iCachedSqlStatementReady = EFalse;
       
    75         }
       
    76 	
       
    77 	delete iCntSqlStatement;
       
    78 	delete iTextDef;
       
    79 	}
       
    80 
       
    81 	
       
    82 /**
       
    83 CCntPplViewSession second phase constructor.
       
    84 */
       
    85 void CCntPplViewSession::ConstructL(const CContactTextDef& aTextDef)
       
    86 	{
       
    87 	//Constructing iCntSqlStatement, iTextDef, and iIsFastAccessFieldsOnly
       
    88 	//by simply call ChangeSortOrderL
       
    89 	CTimer::ConstructL();
       
    90     iContactsFile.AddSqlDBObserverL( *this );
       
    91     ChangeSortOrderL( aTextDef );
       
    92 	}	
       
    93 
       
    94 	
       
    95 /**
       
    96 Change the sorting order/text definition. It should be always called when 
       
    97 there is not an iteration started in persistence layer.
       
    98 
       
    99 @param aTextDef the new text definition to be used in the view session.
       
   100 */
       
   101 void CCntPplViewSession::ChangeSortOrderL(const CContactTextDef& aTextDef)
       
   102 	{
       
   103 	//Cleanup the cached Prepare statement as the sort order will be changed
       
   104 	Cancel();
       
   105     CleanupCachedPrepareStatement();
       
   106 	
       
   107 	//Copy the text definition
       
   108 	CContactTextDef* textDef = CContactTextDef::NewLC();
       
   109 	const TInt KTextDefCount = aTextDef.Count();
       
   110 	for (TInt index = 0; index < KTextDefCount; ++index)
       
   111 		{
       
   112 		textDef->AppendL(TContactTextDefItem(aTextDef.At(index).iFieldType));
       
   113 		}
       
   114 	
       
   115 	// Create select statement on contact table
       
   116 	TCntSqlStatementType statementType(ESelect, KSqlContactTableName());
       
   117 	CCntSqlStatement* sqlSmt = TSqlProvider::GetSqlStatementL(statementType);
       
   118 	CleanupStack::PushL(sqlSmt);
       
   119 	
       
   120 	// Always select id, type flags.	
       
   121 	sqlSmt->SetParamL(KContactId(), KSpace());
       
   122 	sqlSmt->SetParamL(KContactTypeFlags(), KSpace());
       
   123 	
       
   124 	//Go through text definition to construct select statement.
       
   125 	TBool isFastAccessOnly = ETrue;
       
   126 	for(TInt ii = 0; ii < KTextDefCount; ++ii)
       
   127 		{
       
   128 		const TDesC& KColunmName = TCntPersistenceUtility::GetFastAccessColumnNameById(aTextDef.At(ii).iFieldType.iUid);
       
   129 		if(KColunmName.Length() > 0) 
       
   130 			{
       
   131 			sqlSmt->SetParamL(KColunmName, KSpace());
       
   132 			}
       
   133 		else
       
   134 			{
       
   135 			isFastAccessOnly = EFalse;		
       
   136 			}
       
   137 		}
       
   138 	
       
   139 	if(!isFastAccessOnly)
       
   140 		{
       
   141 		//Fields in text blob are needed, add text fields header and
       
   142         //text blob columns in the select statement.		
       
   143 		sqlSmt->SetParamL(KContactTextFieldHeader(), KSpace());
       
   144 		sqlSmt->SetParamL(KContactTextFields(), KSpace());
       
   145 		}
       
   146 
       
   147 	CleanupStack::Pop(2, textDef); // sqlSmt, textDef.
       
   148 	
       
   149 	delete iCntSqlStatement;
       
   150 	iCntSqlStatement = sqlSmt;
       
   151 	
       
   152 	delete iTextDef;
       
   153 	iTextDef = textDef;
       
   154 	
       
   155 	iIsFastAccessFieldsOnly = isFastAccessOnly;
       
   156 	}
       
   157 	
       
   158 
       
   159 /**
       
   160 Preparing sql statement for the coming iteration requests from upper layer.
       
   161 Caller has the responsibilty of controling the lifecycle of the iteration 
       
   162 session -- when it starts and stop.  
       
   163 */
       
   164 void CCntPplViewSession::BeginIterateL()
       
   165 	{
       
   166 	if (! iContactsFile.IsOpened())
       
   167 		{
       
   168 		User::Leave(KErrInUse);
       
   169 		}
       
   170 	
       
   171 	if ( iRSqlStatementReady )
       
   172         {
       
   173         iRSqlStatement.Close();
       
   174         iRSqlStatementReady = EFalse;
       
   175         }
       
   176 		
       
   177 	// we don't need condition for iterating database.
       
   178 	iCntSqlStatement->ClearCondition();
       
   179 	
       
   180 	iRSqlStatement.PrepareL(iContactsFile.NamedDatabase(), iCntSqlStatement->SqlStringL());
       
   181 	iRSqlStatementReady = ETrue;
       
   182 	}
       
   183 
       
   184 	
       
   185 /**
       
   186 Stop iteration by releasing iteration sql statement.
       
   187 */
       
   188 void CCntPplViewSession::EndIterate()
       
   189     {
       
   190     if ( iRSqlStatementReady )
       
   191         {
       
   192         iRSqlStatement.Close();
       
   193         iRSqlStatementReady = EFalse;
       
   194         }
       
   195     }
       
   196 
       
   197 	
       
   198 /**
       
   199 Get next view contact object from iterating sql statement.
       
   200 
       
   201 @return CViewContact object or NULL if iteration reachs end of rows.
       
   202 */
       
   203 CViewContact* CCntPplViewSession::NextItemL(TContactViewPreferences aViewPrefs)
       
   204 	{
       
   205 	if(!iRSqlStatementReady)
       
   206 		{
       
   207 		//Iteration has not started
       
   208 		BeginIterateL();	
       
   209 		}
       
   210 	
       
   211 	return CreateViewItemL(iRSqlStatement, *iCntSqlStatement, aViewPrefs);
       
   212 	}
       
   213 
       
   214 	
       
   215 /**
       
   216 Get view contact object based on given contact id.
       
   217 
       
   218 @return CViewContact object or NULL if there is not such a contact.
       
   219 */
       
   220 CViewContact* CCntPplViewSession::ItemAtL(TContactItemId aContactId)
       
   221 	{
       
   222 	//Cancel the timer so that the cached Prepare statement would not be deleted.
       
   223 	Cancel();
       
   224 	
       
   225 	CViewContact* viewContact = NULL;
       
   226 	
       
   227 	TRAPD(err, viewContact = doItemAtL(aContactId));
       
   228     if(err != KErrNone)
       
   229         {
       
   230         CleanupCachedPrepareStatement();
       
   231     	User::Leave(err);	
       
   232         }
       
   233     	
       
   234 	//Reset the timer
       
   235 	After(KCachedPrepareTimeOut);
       
   236 	return viewContact;
       
   237 	}
       
   238 
       
   239 
       
   240 /**
       
   241 The method to do the real work of get view contact object based on given contact id.
       
   242 
       
   243 @return CViewContact object or NULL if there is not such a contact.
       
   244 */
       
   245 CViewContact* CCntPplViewSession::doItemAtL(TContactItemId aContactId)
       
   246     {
       
   247     if (! iContactsFile.IsOpened())
       
   248     	{
       
   249     	User::Leave(KErrInUse);
       
   250     	}
       
   251     
       
   252 	if ( !iCachedSqlStatementReady )
       
   253 		{
       
   254 		//iCacheSqlStatement is just for ItemAt while iRSqlStatement is used for iteration 
       
   255 		//and maintained by BeginIterateL and EndIterateL.
       
   256     	iCntSqlStatement->SetConditionL(KSelectCondition_SearchForContactId()); 
       
   257 		
       
   258 		//Create a new sqlstatment and cache its Prepare statement.	
       
   259 		iCachedSqlStatement.PrepareL(iContactsFile.NamedDatabase(),  iCntSqlStatement->SqlStringL());
       
   260 		iCachedSqlStatementReady = ETrue;
       
   261 		}
       
   262 		
       
   263 	User::LeaveIfError(iCachedSqlStatement.BindInt(KFirstIndex, aContactId)); //Bind item id into the condition.	
       
   264 
       
   265 	CViewContact* viewContact = CreateViewItemL(iCachedSqlStatement, *iCntSqlStatement, iViewPrefs);
       
   266 	
       
   267 	// Adding this to the cleanup stack, because coverity recons that "iCachedSqlStatement->Reset();" can leave, and it's probably right
       
   268 	CleanupStack::PushL(viewContact);
       
   269 	iCachedSqlStatement.Reset();
       
   270 
       
   271 	// Pop it back off the cleanup stack, and hand over ownership
       
   272 	CleanupStack::Pop(viewContact);
       
   273 	return viewContact;
       
   274     }
       
   275 
       
   276 
       
   277 /**
       
   278 Clean up the cached prepare statement.
       
   279 */
       
   280 void CCntPplViewSession::CleanupCachedPrepareStatement()
       
   281     {
       
   282     if ( iCachedSqlStatementReady )
       
   283         {
       
   284         iCachedSqlStatement.Close();
       
   285         iCachedSqlStatementReady = EFalse;
       
   286         }
       
   287     }
       
   288 
       
   289 /**
       
   290 CTimer callback funtion, the cached Prepare statement would be de-cached if ItemAtL is not called
       
   291 during the time interval defined by KCachedPrepareTimeOut.
       
   292 */
       
   293 void CCntPplViewSession::RunL()
       
   294     {
       
   295     CleanupCachedPrepareStatement();
       
   296     }
       
   297 	
       
   298 	
       
   299 /**
       
   300 Create view contact object based on given sql statement.
       
   301 
       
   302 @return CViewContact object or NULL the contact is not found.
       
   303 */
       
   304 CViewContact* CCntPplViewSession::CreateViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   305 	{
       
   306 	if (! iContactsFile.IsOpened())
       
   307 		{
       
   308 		User::Leave(KErrInUse);
       
   309 		}
       
   310 	
       
   311 	CViewContact* viewContact = InitialiseViewItemL(aSqlStmt, aCntSqlStmt, aViewPrefs);
       
   312 	if(!viewContact)
       
   313 		{
       
   314 		//Couldn't find the contact.
       
   315 		return NULL;
       
   316 		}
       
   317 	
       
   318 	CleanupStack::PushL(viewContact);
       
   319 	if(viewContact->ContactType() == CViewContact::EContactItem)
       
   320 		{
       
   321 		FillViewItemL(*viewContact, aSqlStmt, aViewPrefs);
       
   322 		}
       
   323 	
       
   324 	TUid typeUid = GetContactFieldMatchUid(*viewContact, aViewPrefs);	
       
   325 	if(typeUid != KUidContactFieldNone)
       
   326 		{
       
   327 		RSqlStatement contactSqlStmt;
       
   328 		CleanupClosePushL(contactSqlStmt);
       
   329 		
       
   330 		/* we have to reload the row from SQL database to cache in text header and text blob */ 	
       
   331 		contactSqlStmt.PrepareL(iContactsFile.NamedDatabase(),  iSqlSmtSelectAllFieldsById.SqlStringL());
       
   332 		User::LeaveIfError(contactSqlStmt.BindInt(KFirstIndex, viewContact->Id())); //Bind item id into the condition.	
       
   333 		
       
   334 		TInt err = contactSqlStmt.Next();
       
   335 		if(err == KSqlAtEnd)
       
   336 			{
       
   337 			//Should never be here, we found it in InitialiseViewItemL 
       
   338 			//but couldn't find the same contact in same database.
       
   339 			CleanupStack::PopAndDestroy(viewContact);
       
   340 			return NULL;
       
   341 			}			
       
   342 			
       
   343 		User::LeaveIfError(err);
       
   344 		
       
   345 		/* set first field with possible content for group or unsorted contact */	
       
   346 		CContactDatabase::TTextFieldMinimal buf;
       
   347 		TextFieldL(contactSqlStmt, iSqlSmtSelectAllFieldsById, iContactProperties.SystemTemplateL(), typeUid, buf);
       
   348 		viewContact->SetFirstFieldForBlankContactL(buf);
       
   349 		CleanupStack::PopAndDestroy(&contactSqlStmt);
       
   350 		} //if(typeUid != 0)
       
   351 	
       
   352 	CleanupStack::Pop(viewContact);
       
   353 	return viewContact;
       
   354 	}
       
   355 
       
   356 	
       
   357 /**
       
   358 Filling content for the given view contact object.
       
   359 
       
   360 @param aViewContact reference to the view contact object to be filled
       
   361 @param aSqlStmt the sql statement which contains the retrieved content for the view object. 
       
   362 */
       
   363 void CCntPplViewSession::FillViewItemL(CViewContact& aViewContact, RSqlStatement& aSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   364 	{
       
   365 	if(iIsFastAccessFieldsOnly)
       
   366 		{
       
   367 		//The view gets fields only from fast access columns	
       
   368 		const TInt KTextDefCount = iTextDef->Count();
       
   369 		for(TInt index = 0; index < KTextDefCount; ++index)
       
   370 			{
       
   371 			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(iTextDef->At(index).iFieldType.iUid);
       
   372 			ASSERT(KColumnName.Length() > 0);
       
   373 			
       
   374 			TPtrC fieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName));
       
   375    			AddFieldInViewContactL(aViewContact, fieldPtrC, aViewPrefs);
       
   376 			} //for
       
   377 		}
       
   378 	else
       
   379 		{
       
   380 		TBool searchFastAccessFields = EFalse;
       
   381 		
       
   382 		// iTextDef contains the fields that should be included in the view.
       
   383 		// The array of all the field objects in a contact item is returned from
       
   384 		// the Contacts table.  
       
   385 		RPointerArray<CContactItemField> fields;
       
   386 		CleanupStack::PushL(TCleanupItem(TCntPersistenceUtility::ResetAndDestroyRPointerArray, &fields));
       
   387 		
       
   388 		TPtrC8 textHeader;
       
   389 		aSqlStmt.ColumnBinary(iCntSqlStatement->ParameterIndex(KContactTextFieldHeader()), textHeader);
       
   390 		RDesReadStream textHeaderStream(textHeader);
       
   391 		CleanupClosePushL(textHeaderStream);
       
   392         CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
       
   393         
       
   394     	RStoreReadStream textHeaderStoreStream;
       
   395     	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
       
   396         
       
   397 		TPtrC textFieldPtrC = aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KContactTextFields()));
       
   398 		HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
       
   399 			
       
   400 		TCntPersistenceUtility::ReadTextBlobL(textHeaderStoreStream, textFieldsBuf, *iTextDef, iContactProperties.SystemTemplateL(), fields, searchFastAccessFields);
       
   401 		CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
       
   402 		
       
   403 		// Loop through fields, checking for fields from fast access fields, and add 
       
   404 		// the fields to the view contact object.
       
   405 		const TInt KFieldsNumMax = fields.Count();
       
   406 		for(TInt fieldsIndex = 0; fieldsIndex < KFieldsNumMax; ++fieldsIndex)
       
   407 			{
       
   408 			// this doesn't own the instance stored in fields array.
       
   409 			CContactItemField* itemField = fields[fieldsIndex];
       
   410 
       
   411 			if(itemField == NULL)
       
   412 				{
       
   413 				aViewContact.AddFieldL(KNullDesC);
       
   414 				continue;
       
   415 				}
       
   416 
       
   417 			// The array of fields retrieved from the text fields blob does not
       
   418 			// contain the text data Fast Access fields. If the searchFastAccessFields 
       
   419 			// flags have been set then get the data from Fast Access columns
       
   420 			// before adding the data to the view.
       
   421 			TPtrC fieldText;
       
   422 			if(searchFastAccessFields && itemField->ContentType().FieldTypeCount() > 0)
       
   423 				{
       
   424 				//Check the field name of the first field type(key field type) 
       
   425 				//in the field's field types array
       
   426     			const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(itemField->ContentType().FieldType(0).iUid);
       
   427 				if(KColumnName.Length() > 0)
       
   428 					{
       
   429 					//this is a fast access field.
       
   430 					fieldText.Set(aSqlStmt.ColumnTextL(iCntSqlStatement->ParameterIndex(KColumnName)));
       
   431 					}
       
   432 				else
       
   433 					{
       
   434 					fieldText.Set(itemField->TextStorage()->Text());
       
   435 					}					
       
   436 				}
       
   437 			else
       
   438 				{
       
   439 				fieldText.Set(itemField->TextStorage()->Text());
       
   440 				}
       
   441 			
       
   442 			AddFieldInViewContactL(aViewContact, fieldText, aViewPrefs);
       
   443 			}
       
   444 		
       
   445 		CleanupStack::PopAndDestroy(&fields);
       
   446 		}
       
   447 	}
       
   448 
       
   449 	
       
   450 /**
       
   451 Initialise requested view contact object based on given parameters:
       
   452  1. search the contact in contact table.
       
   453  2. fill in contact type and hint to the view contact object.
       
   454 
       
   455 @param aSqlStmt      reference to a RSqlStatement to be read in data 
       
   456 @return initialized CViewContact object or NULL if reached end of rows.
       
   457 */
       
   458 CViewContact* CCntPplViewSession::InitialiseViewItemL(RSqlStatement& aSqlStmt, const CCntSqlStatement& aCntSqlStmt, const TContactViewPreferences& aViewPrefs)
       
   459 	{
       
   460 	CViewContact* viewContact = NULL;
       
   461 	
       
   462     while(viewContact == NULL)
       
   463 	    {
       
   464     	TInt err = aSqlStmt.Next();
       
   465     	 
       
   466     	if(err == KSqlAtEnd)
       
   467     	    {
       
   468     	    return NULL;
       
   469     	    }
       
   470     	    
       
   471        	User::LeaveIfError(err);
       
   472        	
       
   473     	TInt typeFlags = aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactTypeFlags()));
       
   474     	TUid contactTypeUid = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags);
       
   475     	
       
   476         if(!ContactCorrectType(contactTypeUid, aViewPrefs))
       
   477             {
       
   478             //The contact type doesn't match the view prefreference
       
   479             continue;
       
   480             }
       
   481     	
       
   482     	viewContact = CViewContact::NewLC(KNullContactId);
       
   483     	
       
   484     	/* Got a row and add common fields for both Groups and Contact view items. */
       
   485     	viewContact->SetId(aSqlStmt.ColumnInt(aCntSqlStmt.ParameterIndex(KContactId())));
       
   486     	viewContact->SetContactHint(TCntPersistenceUtility::TypeFlagsToHint(typeFlags));
       
   487     	viewContact->SetContactTypeUid(contactTypeUid);
       
   488     	
       
   489     	
       
   490     	if(contactTypeUid == KUidContactGroup)
       
   491     		{
       
   492     		// Groups don't require all the field types to be set.
       
   493     		viewContact->SetContactType(CViewContact::EGroup);
       
   494     		}
       
   495     	else
       
   496     		{
       
   497     		// All other contact types do require field types to be set.
       
   498     		viewContact->SetContactType(CViewContact::EContactItem);
       
   499     		}
       
   500 
       
   501     	CleanupStack::Pop(viewContact);		
       
   502 	    }
       
   503    	
       
   504 	return viewContact;    
       
   505 	}	
       
   506 
       
   507 	
       
   508 /**
       
   509 Check if the retrieved view contact is group or unsorted contact, if so return suitable field 
       
   510 match uid in order to fill in a possible text for the contact: 
       
   511 For group contact    -- find template label.
       
   512 For unsorted contact -- find first not none field.
       
   513 
       
   514 @param aViewContact     reference to the retrieved view contact object.
       
   515 @param aViewPreferences the view preferences made by client.
       
   516  
       
   517 @return suitable match uid or KUidContactFieldNone if it's not group or unsorted contact.
       
   518 */
       
   519 TUid CCntPplViewSession::GetContactFieldMatchUid(const CViewContact& aViewContact, const TContactViewPreferences& aViewPreferences)	
       
   520 	{
       
   521 	TUid typeUid = KUidContactFieldNone;
       
   522 	if(aViewContact.ContactType() == CViewContact::EGroup && (aViewPreferences & (EGroupsOnly | EContactAndGroups)))
       
   523 		{
       
   524 		// Check for group view contact type.  This type of view contact uses the
       
   525 		// template label field to populate the first view contact field.
       
   526 		typeUid = KUidContactFieldTemplateLabel;
       
   527 		}
       
   528 	else if(!aViewContact.IsSortable() && (aViewPreferences & (EIgnoreUnSorted | EUnSortedAtBeginning | EUnSortedAtEnd)) == 0)		
       
   529 		{
       
   530 		// None of the sort fields contained any data.  We want this contact to
       
   531 		// be sorted by the first bit of text we find so we need to retrieve the
       
   532 		// first text available from the contact and use this to populate the
       
   533 		// first view contact field.
       
   534 		typeUid = KUidContactFieldMatchAll;
       
   535 		}
       
   536 	return typeUid;	
       
   537 	}
       
   538 
       
   539 	
       
   540 /**
       
   541 Refine the field content and add the refined content to the given view contact object.
       
   542  
       
   543 @param aViewContact     reference to the retrieved view contact object.
       
   544 @param aFieldPtrC    	The actual field content read from database.
       
   545 @param aViewPreferences The view preferences for how to format the content. 
       
   546 */
       
   547 void CCntPplViewSession::AddFieldInViewContactL(CViewContact& aViewContact, TPtrC& aFieldPtrC, const TContactViewPreferences& aViewPreferences)
       
   548 	{
       
   549 	_LIT(KBlank," ");
       
   550 	
       
   551 	// Truncate to 64 if necessary.
       
   552 	TPtr ptr(const_cast<TUint16*>(aFieldPtrC.Ptr()), KTextFieldMinimalLength);
       
   553 	if(aFieldPtrC.Length() > KTextFieldMinimalLength) 
       
   554 		{
       
   555 		ptr.SetLength(KTextFieldMinimalLength); 
       
   556 		}
       
   557 	else
       
   558 		{
       
   559 		ptr.SetLength(aFieldPtrC.Length());
       
   560 		}
       
   561 		
       
   562 	// Add the field to the view.
       
   563 	if((ptr.Length() == 0) ||
       
   564 	   (ptr.Length() == 1 && (aViewPreferences & ESingleWhiteSpaceIsEmptyField) && ptr.Compare(KBlank)==KErrNone))
       
   565 		{
       
   566 		/* empty field */
       
   567 		aViewContact.AddFieldL(KNullDesC);
       
   568 		} 
       
   569 	else
       
   570 		{
       
   571 		aViewContact.AddFieldL(ptr);
       
   572 		}
       
   573 	}
       
   574 
       
   575 /** 
       
   576 Retrieve the field text for the given field type and contact item ID.
       
   577 
       
   578 The behaviour differs when a specific field type is not given i.e. when
       
   579 aFieldType is KUidContactFieldMatchAll:
       
   580 
       
   581 - First tries to find an email for the given contact item ID.
       
   582 - If there is no email then it retrieves the first entry in Fast Access fields
       
   583 for the given contact item ID.
       
   584 - If there is no Fast Access fields then it retrieves the first entry in the
       
   585 text fields blob for the given contact item ID.
       
   586 
       
   587 Text for all other field types are retrieved from the text fields blob.
       
   588 
       
   589 The caller must determine that the given contact item ID exists before calling
       
   590 this method.
       
   591 */
       
   592 void CCntPplViewSession::TextFieldL(RSqlStatement& aSqlStatement, const CCntSqlStatement& aCntSqlStmt, const CContactTemplate& aSystemTemplate, TFieldType aFieldType, TDes& aText)
       
   593 	{
       
   594 	TPtrC8 textHeader;
       
   595 	aSqlStatement.ColumnBinary(aCntSqlStmt.ParameterIndex(KContactTextFieldHeader()), textHeader);
       
   596 	RDesReadStream textHeaderStream(textHeader);
       
   597 	CleanupClosePushL(textHeaderStream);	
       
   598     CEmbeddedStore* textHeaderStore = CEmbeddedStore::FromLC(textHeaderStream);
       
   599     
       
   600 	RStoreReadStream textHeaderStoreStream;
       
   601    	textHeaderStoreStream.OpenLC(*textHeaderStore,textHeaderStore->Root());
       
   602 
       
   603 	TPtrC textFieldPtrC = aSqlStatement.ColumnTextL(aCntSqlStmt.ParameterIndex(KContactTextFields()));
       
   604 	HBufC* textFieldsBuf = textFieldPtrC.AllocLC();
       
   605 	
       
   606 	if(aFieldType == KUidContactFieldMatchAll)
       
   607 		{
       
   608 		if (TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText) == EFalse)
       
   609 			{
       
   610 			CContactDatabase::TTextFieldMinimal	fastAccessText;
       
   611 			if (HasTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, fastAccessText))
       
   612 				{
       
   613 				aText.Copy(fastAccessText);		
       
   614 				}
       
   615 			}
       
   616 		} 
       
   617 	else
       
   618 		{
       
   619 		if (SpecificTxtFieldInFastAccessFieldsL(aSqlStatement, aCntSqlStmt, aFieldType, aText) == EFalse)
       
   620 			{
       
   621 			TCntPersistenceUtility::FindTxtFieldInTextBlobL(textHeaderStoreStream, textFieldsBuf, aSystemTemplate, aFieldType, aText);
       
   622 			}
       
   623 		}
       
   624 		
       
   625 	CleanupStack::PopAndDestroy(4, &textHeaderStream); //textHeaderStore, textHeaderStream, textHeaderStoreStream, textFieldsBuf
       
   626 	}
       
   627 
       
   628 
       
   629 /**
       
   630 The first text field in the Fast Access fields is found and returned via the
       
   631 parameter aText.
       
   632 
       
   633 @param aCntItemId The contact ID for which the first text field is required.
       
   634 @param aText On return contains the text for the field of the first Identity
       
   635 text field.
       
   636 
       
   637 @return ETrue if a Fast Access text field was found, EFalse otherwise.
       
   638 */
       
   639 TBool CCntPplViewSession::HasTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, TDes& aText)
       
   640 	{
       
   641 	for(TInt ii = EGivenName; ii <= ECompanyNamePrn; ++ii)
       
   642 		{
       
   643 		const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(KFastAccessFieldUids[ii]);
       
   644 		TPtrC identText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
       
   645 		if(identText.Length() > 0)
       
   646 			{
       
   647 			TCntPersistenceUtility::CopyMinFieldText(identText, aText);
       
   648 			return ETrue;
       
   649 			}
       
   650 		}
       
   651 	return EFalse;
       
   652 	}
       
   653 
       
   654 	
       
   655 /**
       
   656 Checks if the given field type is in the Fast Access fields and if so the field text
       
   657 is returned via the parameter aText.
       
   658 
       
   659 @param aCntItemId The contact ID for which the specific text field is required.
       
   660 @param aText On return contains the field text for the first Fast Access fields
       
   661 with field type aFieldType.
       
   662 @param aFieldType The specific field requested.
       
   663 
       
   664 @return ETrue if the specific fast access text field was found, EFalse otherwise.
       
   665 */
       
   666 TBool CCntPplViewSession::SpecificTxtFieldInFastAccessFieldsL(RSqlStatement& aSelectStmt, const CCntSqlStatement& aCntSqlStmt, const TFieldType aFieldType, TDes& aText)
       
   667 	{
       
   668     const TDesC& KColumnName = TCntPersistenceUtility::GetFastAccessColumnNameById(aFieldType.iUid);
       
   669 	if(KColumnName.Length() > 0)
       
   670 		{
       
   671 		// This is a fast access field.
       
   672 		TPtrC fastAccessText = aSelectStmt.ColumnTextL(aCntSqlStmt.ParameterIndex(KColumnName));
       
   673 		TCntPersistenceUtility::CopyMinFieldText(fastAccessText, aText);
       
   674 		return ETrue;
       
   675 		}
       
   676 	return EFalse;
       
   677 	}
       
   678 
       
   679 	
       
   680 /**
       
   681 Get view session id
       
   682 
       
   683 @return the view session id assigned to the session.
       
   684 */
       
   685 TInt CCntPplViewSession::ViewId() const
       
   686 	{
       
   687 	return iViewId;
       
   688 	}
       
   689 
       
   690 
       
   691 TBool CCntPplViewSession::ContactCorrectType(TUid aContactTypeUid, TContactViewPreferences aTypeToInclude)
       
   692     {
       
   693     TBool correctType = EFalse;
       
   694 
       
   695     if (aContactTypeUid == KUidContactCard)
       
   696         {
       
   697         if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly)))
       
   698             {
       
   699             correctType = ETrue;
       
   700             }
       
   701         }
       
   702     else if (aContactTypeUid == KUidContactOwnCard)
       
   703         {
       
   704         if (!(aTypeToInclude & (EGroupsOnly | EICCEntriesOnly | EContactCardsOnly)))
       
   705             {
       
   706             correctType = ETrue;
       
   707             }
       
   708         }
       
   709     else if (aContactTypeUid == KUidContactGroup)
       
   710         {
       
   711         if (aTypeToInclude & (EGroupsOnly | EContactAndGroups))
       
   712             {
       
   713             correctType = ETrue;
       
   714             }
       
   715         }
       
   716     else if (aContactTypeUid == KUidContactICCEntry)
       
   717         {
       
   718         if (aTypeToInclude & (EICCEntriesOnly | EICCEntriesAndContacts))
       
   719             {
       
   720             correctType = ETrue;
       
   721             }
       
   722         }
       
   723 
       
   724     return correctType;
       
   725     }
       
   726 
       
   727 	
       
   728 /**
       
   729  * Close the resource which is running and depends on RSqlDatabase 
       
   730  * that will be closed in CPplContactsFile.
       
   731  */
       
   732 void CCntPplViewSession::OnCloseL()
       
   733     {
       
   734 
       
   735     if ( iRSqlStatementReady )
       
   736         {
       
   737         iRSqlStatement.Close();
       
   738         iRSqlStatementReady = EFalse;
       
   739         }
       
   740 
       
   741     if ( iCachedSqlStatementReady )
       
   742         {
       
   743         iCachedSqlStatement.Close();
       
   744         iCachedSqlStatementReady = EFalse;
       
   745         }
       
   746 
       
   747     }
       
   748 
       
   749