plugins/contacts/symbian/contactsmodel/cntplsql/src/pplcontactitemmanager.cpp
changeset 0 876b1a06bc25
child 5 603d3f8b6302
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalComponent
       
    22  @released
       
    23 */
       
    24 
       
    25 #include "pplcontactitemmanager.h"
       
    26 #include "cntsqlprovider.h"
       
    27 #include "dbsqlconstants.h"
       
    28 #include "cntpersistenceutility.h"
       
    29 #include "c12keypredictivesearchtable.h"
       
    30 #include "cqwertypredictivesearchtable.h"
       
    31 #include "cpredictivesearchsettingstable.h"
       
    32 #include "cpredictivesearchsynchronizer.h"
       
    33 #include "predictivesearchlog.h"
       
    34 //#include "cntmetadataoperation.h"
       
    35 #include <cntdef.h>
       
    36 #include <sqldb.h>
       
    37 #include <cntdb.h>
       
    38 
       
    39 // TODO: The code related to predictive search table is placed inside this
       
    40 // macro. Uncomment the below line to get the table into use.
       
    41 #define USE_PRED_SEARCH_TABLE
       
    42 
       
    43 // If this macro is defined, then pred.search qwerty tables are used
       
    44 #define USE_QWERTY_PRED_SEARCH_TABLE
       
    45 
       
    46 
       
    47 /**
       
    48 Creates a concrete CPplContactItemManager object 
       
    49 
       
    50 @param 	aDatabase reference to RSqlDatabase
       
    51 		aTransactionManager reference to MLplTransactionManager (provided by CPlContactsFile)
       
    52 @return concrete CPplContactItemManager object
       
    53 @leave KErrNoMemory, an out of memory occured
       
    54 */		
       
    55 CPplContactItemManager* CPplContactItemManager::NewL(RSqlDatabase& aDatabase, MLplTransactionManager& aTransactionManager, CLplContactProperties&  aContactProperties, RPplIccContactStore& aIccContactStore)
       
    56 	{
       
    57 	CPplContactItemManager* self = new (ELeave) CPplContactItemManager(aDatabase, aTransactionManager, aContactProperties, aIccContactStore);
       
    58 	CleanupStack::PushL(self);
       
    59 	self->ConstructL();
       
    60 	CleanupStack::Pop(self);
       
    61 	return self;	
       
    62 	}
       
    63 
       
    64 /**
       
    65 Class destructor. Deletes holded CCntSqlStatement
       
    66 
       
    67 */		
       
    68 CPplContactItemManager::~CPplContactItemManager()
       
    69 	{
       
    70 	delete iSelectStatement;	
       
    71 	delete iContactTable;
       
    72 	delete iCommAddrTable;
       
    73 #if defined(USE_PRED_SEARCH_TABLE)
       
    74 	PRINT(_L("delete pred search table objects"));
       
    75 	delete iPredictiveSearchSynchronizer;
       
    76 	delete iPredSearch12keyTable;
       
    77 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
    78 	delete iPredSearchQwertyTable;
       
    79 	delete iPredSearchSettingsTable;
       
    80 #endif
       
    81 	PRINT(_L("delete pred search table objects - done"));
       
    82 #endif
       
    83     delete iPresenceTable; 
       
    84 	delete iGroupTable;
       
    85 	delete iPreferencePersistor;
       
    86 	//iColSession.Close();
       
    87 	}
       
    88 	
       
    89 /**
       
    90 Class constructor
       
    91 
       
    92 @param aDatabase reference to RSqlDatabase
       
    93 @param aTransactionManager reference to transaction manager
       
    94 @param aContactProperties reference to contact properties
       
    95 */	
       
    96 CPplContactItemManager::CPplContactItemManager(RSqlDatabase& aDatabase, MLplTransactionManager& aTransactionManager, CLplContactProperties&  aContactProperties, RPplIccContactStore& aIccContactStore) :
       
    97 	iDatabase(aDatabase),
       
    98 	iTransactionManager(aTransactionManager),
       
    99 	iContactProperties(aContactProperties),
       
   100 	iIccContactStore(aIccContactStore)
       
   101 	{
       
   102 	}
       
   103 	
       
   104 /**
       
   105 Add the given contact item to the database. Forward the call to CPplTableBase
       
   106 based classes representing the tables in the contact database.
       
   107 
       
   108 @param 	aItem The contact item to be added to the database. 
       
   109 @param 	aSessionId The ID of the session that issued the request.  Used to
       
   110 		prevent Phonebook Synchroniser deadlock.
       
   111 
       
   112 @return Contact item ID of the contact added to the database.
       
   113 */
       
   114 TContactItemId CPplContactItemManager::CreateL(CContactItem& aItem, TUint aSessionId)
       
   115 	{
       
   116 	TBool controlTransaction = !(iTransactionManager.IsTransactionActive());
       
   117 	
       
   118 	TBool compressedGuid=EFalse;
       
   119 
       
   120 	// If needed generate a gui for the current contact item
       
   121 	if (aItem.Guid() == TPtrC(KNullDesC))
       
   122 		{
       
   123 		iPreferencePersistor->SetGuidL(aItem, compressedGuid);
       
   124 		}
       
   125 
       
   126 	if (compressedGuid)
       
   127 		{
       
   128 		aItem.SetHasCompressedGuid(compressedGuid);
       
   129 		}
       
   130 
       
   131 	if (aItem.Type() == KUidContactICCEntry) 
       
   132 		{
       
   133 		const TInt ret = iContactProperties.ContactSynchroniserL(aSessionId).ValidateWriteContact(static_cast<CContactICCEntry&>(aItem));
       
   134 		User::LeaveIfError(ret);	
       
   135 		}
       
   136 	
       
   137 	if(controlTransaction)
       
   138 		{
       
   139 		StartTransactionL(aSessionId);
       
   140 		}
       
   141 		
       
   142 	iContactTable->CreateInDbL(aItem);	
       
   143 	iGroupTable->CreateInDbL(aItem);	
       
   144 	iCommAddrTable->CreateInDbL(aItem);
       
   145 #if defined(USE_PRED_SEARCH_TABLE)
       
   146 	PRINT(_L("add new contact to pred search tables"));
       
   147 	iPredSearch12keyTable->CreateInDbL(aItem);
       
   148 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   149 	iPredSearchQwertyTable->CreateInDbL(aItem);
       
   150 	iPredSearchSettingsTable->CreateInDbL(aItem);
       
   151 #endif
       
   152 	PRINT(_L("add new contact to pred search tables - done"));
       
   153 #endif
       
   154 
       
   155    	TContactItemId groupId = iIccContactStore.CreateInDbL(aItem, aSessionId);
       
   156    	if(groupId != KNullContactId)
       
   157    	    {
       
   158    	    //Every ICC entry is added to a special group, created by the Phonebook
       
   159         //Synchroniser server during the initial synchronisation with the Contacts Model.
       
   160 		CContactItemViewDef* itemDef = CContactItemViewDef::NewLC(CContactItemViewDef::EIncludeFields,CContactItemViewDef::EMaskHiddenFields);
       
   161 		itemDef->AddL(KUidContactFieldMatchAll);
       
   162 
       
   163 		// Add ICC entry to the group.
       
   164 		CContactGroup* grp = static_cast<CContactGroup*>(ReadLC(groupId, *itemDef, EPlAllInfo, aSessionId));
       
   165 		
       
   166 		grp->AddContactL(aItem.Id());
       
   167 		UpdateL(*grp, aSessionId);
       
   168 
       
   169 		CleanupStack::PopAndDestroy(2, itemDef); // grp
       
   170    	    }
       
   171 
       
   172 	if(controlTransaction)
       
   173 		{
       
   174 		CommitTransactionL();
       
   175 		}
       
   176 	
       
   177 	// Assuming success if no leaves at this point, so update
       
   178 	// the metadata search store for this entry
       
   179 	//CCntMetadataOperation* op = CCntMetadataOperation::NewLC(iColSession);
       
   180 	//TRAP_IGNORE(op->SaveContactLD(aItem));
       
   181 	//CleanupStack::Pop(op); // Do not destroy - called LD function
       
   182 	
       
   183 	return aItem.Id();	
       
   184 	}
       
   185 	
       
   186 /**
       
   187 Reads the contact item from the database using the given contact item ID.
       
   188 
       
   189 @param aItemId The Id number of the contact to be read.
       
   190 @param aView Specifies the fields to be read.
       
   191 @param aInfoToRead not used 
       
   192 @param aSessionId The ID of the session that issued the request.  This is used
       
   193 to prevent Phonebook Synchroniser deadlock.
       
   194 @param aIccOpenCheck Specifies if validation with the Phonebook Synchroniser is
       
   195 needed for this contact.
       
   196 
       
   197 @leave 	KErrArgument 	if the itemID can't be set within select statement
       
   198 @leave  KErrNotFound 	if a contact item with aItemId does not exist within contact database
       
   199 @leave  KSqlErrBusy 	the database file is locked; thrown if RSqlStatement::Next() 
       
   200 						returns this error
       
   201 @leave  KErrNoMemory 	an out of memory condition has occurred - the statement
       
   202                         will be reset;thrown if RSqlStatement::Next() returns this error
       
   203 @leave  KSqlErrGeneral	a run-time error has occured - this function must not
       
   204                         be called again;thrown if RSqlStatement::Next() returns this error
       
   205 @leave	KSqlErrMisuse	this function has been called after a previous call
       
   206                         returned KSqlAtEnd or KSqlErrGeneral.thrown if RSqlStatement::Next() 
       
   207                         returns this error
       
   208 @leave  KSqlErrStmtExpired	the SQL statement has expired (if new functions or
       
   209                             collating sequences have been registered or if an
       
   210                             authorizer function has been added or changed);
       
   211                             thrown if RSqlStatement::Next() returns this error
       
   212 
       
   213 @return CContactItem created from reading the database tables.
       
   214 */	
       
   215 CContactItem* CPplContactItemManager::ReadLC(TContactItemId aItemId, const CContactItemViewDef& aView, TInt aInfoToRead, TUint aSessionId, TBool aIccOpenCheck) const
       
   216 	{	
       
   217 	CContactTemplate* sysTemplate = NULL;
       
   218 	if (aItemId != KGoldenTemplateId) 
       
   219 		{
       
   220 		sysTemplate = const_cast<CContactTemplate*>(&iContactProperties.SystemTemplateL());
       
   221 		}
       
   222 	
       
   223 	RSqlStatement selectStmt;
       
   224 	CleanupClosePushL(selectStmt);
       
   225 	User::LeaveIfError(selectStmt.Prepare(iDatabase, iSelectStatement->SqlStringL()));
       
   226 	
       
   227 	TInt err = selectStmt.BindInt(KFirstParam, aItemId);
       
   228 	
       
   229 	if(err != KErrNone)
       
   230 		{
       
   231 		User::Leave(KErrArgument);	
       
   232 		}
       
   233 	
       
   234 	CContactItem* item = NULL;
       
   235 	TUid type(KNullUid);
       
   236 	
       
   237 	if((err = selectStmt.Next()) == KSqlAtRow)
       
   238 		{
       
   239 		TInt contactId = selectStmt.ColumnInt(iSelectStatement->ParameterIndex(KContactId));
       
   240 		TInt templateId = selectStmt.ColumnInt(iSelectStatement->ParameterIndex(KContactTemplateId));
       
   241 		TInt typeFlags = selectStmt.ColumnInt(iSelectStatement->ParameterIndex(KContactTypeFlags));
       
   242 		type = TCntPersistenceUtility::TypeFlagsToContactTypeUid(typeFlags); 
       
   243 		item = CContactItem::NewLC(type);
       
   244 		item->SetId(contactId);
       
   245 		TPtrC guid = selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactGuidString));
       
   246 		item->SetUidStringL(guid);
       
   247 		TInt attr = (typeFlags & EContactAttributes_Mask) >> EContactAttributes_Shift; 
       
   248 		item->SetAttributes(attr);
       
   249 		item->SetTemplateRefId(templateId);
       
   250 		item->SetLastModified(TTime(selectStmt.ColumnInt64(iSelectStatement->ParameterIndex(KContactLastModified)))); 
       
   251 		item->SetCreationDate(TTime(selectStmt.ColumnInt64(iSelectStatement->ParameterIndex(KContactCreationDate))));
       
   252 		item->SetAccessCount(selectStmt.ColumnInt(iSelectStatement->ParameterIndex(KContactAccessCount)));
       
   253 			
       
   254 		RArray<TPtrC> fastAccessFields;
       
   255 		CleanupClosePushL(fastAccessFields);
       
   256 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactFirstName)));
       
   257 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactLastName)));
       
   258 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactCompanyName)));
       
   259 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactFirstNamePrn)));
       
   260 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactLastNamePrn)));
       
   261 		fastAccessFields.AppendL(selectStmt.ColumnTextL(iSelectStatement->ParameterIndex(KContactCompanyNamePrn)));
       
   262 				
       
   263 		//set first name, last name, company name, first name pronunciation, last name pronunciation, company name pronunciation
       
   264 		for (TInt fieldNum = item->CardFields().Count() - 1; fieldNum>=0; --fieldNum) 
       
   265 			{
       
   266 			CContactItemField& textField = (item->CardFields())[fieldNum];
       
   267 			const TInt nameFieldIndex = NameFieldIndex(textField);
       
   268 
       
   269 			// Check if field is first name, last name, company name,
       
   270 			// first name pronunciation, last name pronunciation, company name pronunciation.
       
   271 			if (nameFieldIndex != KErrNotFound)
       
   272 				{
       
   273 				HBufC* text = HBufC::NewLC(fastAccessFields[nameFieldIndex].Size());
       
   274 				text->Des() = fastAccessFields[nameFieldIndex];
       
   275 				textField.TextStorage()->SetText(text);
       
   276 				CleanupStack::PopAndDestroy(text);
       
   277 				}
       
   278 			}
       
   279 			
       
   280 		CleanupStack::PopAndDestroy(&fastAccessFields);		
       
   281 		}
       
   282 	else
       
   283 		{
       
   284 		if(err == KSqlAtEnd)
       
   285 			{
       
   286 			User::Leave(KErrNotFound);	// Select statement did not return any row		
       
   287 			}
       
   288 		else
       
   289 			{
       
   290 			User::Leave(err); 	// Otherwise selectStmt.Next() generated a sql error
       
   291 			}	
       
   292 		
       
   293 		}
       
   294 
       
   295 	if (!(item->IsDeleted()) || type == KUidContactCardTemplate)
       
   296 		{
       
   297 		TCntPersistenceUtility::ReadBlobL(*item, aView, sysTemplate, iDatabase);
       
   298 		}
       
   299     
       
   300     //Fill in group content.
       
   301     static_cast<CPplGroupsTable*>(iGroupTable)->ReadL(*item);
       
   302     
       
   303     //Validate checking ICC entry.
       
   304     iIccContactStore.ReadL(*item, aInfoToRead, aSessionId, aIccOpenCheck);
       
   305     
       
   306 	CleanupStack::Pop(item);
       
   307 	CleanupStack::PopAndDestroy(&selectStmt);
       
   308 	CleanupStack::PushL(item);
       
   309 	
       
   310 	return item;
       
   311 	}
       
   312 	
       
   313 /** 
       
   314 Updates the given contact item in the database.Forward the call to CPplTableBase
       
   315 based classes representing the tables in the contact database.
       
   316 
       
   317 @param aItem The contact to be updated with all the changes (received from the
       
   318 user).
       
   319 @param aSessionId The ID of the session that issued the request.  Used to
       
   320 prevent Phonebook Synchroniser deadlock.
       
   321 */	
       
   322 void CPplContactItemManager::UpdateL(CContactItem& aItem, TUint aSessionId, TBool /*aSpeeDailUpdate*/)
       
   323 	{
       
   324 	TBool controlTransaction = !(iTransactionManager.IsTransactionActive());
       
   325 	
       
   326 	if (aItem.Type() == KUidContactICCEntry) 
       
   327 		{
       
   328         //Fakely validating read right to ICC entry to keep BC.
       
   329 		const TInt ret = iContactProperties.ContactSynchroniserL(aSessionId).ValidateContact(MContactSynchroniser::ERead, aItem.Id());
       
   330 		User::LeaveIfError(ret);	
       
   331 		}
       
   332 		
       
   333 	if(controlTransaction)
       
   334 		{
       
   335 		StartTransactionL(aSessionId);
       
   336 		}
       
   337 
       
   338 	iIccContactStore.UpdateL(aItem, aSessionId);
       
   339 	iContactTable->UpdateL(aItem);	
       
   340 	iGroupTable->UpdateL(aItem);	
       
   341 	iCommAddrTable->UpdateL(aItem);
       
   342 #if defined(USE_PRED_SEARCH_TABLE)
       
   343 	PRINT(_L("update contact in pred search tables"));
       
   344 	iPredSearch12keyTable->UpdateL(aItem);
       
   345 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   346 	iPredSearchQwertyTable->UpdateL(aItem);
       
   347 	iPredSearchSettingsTable->UpdateL(aItem);
       
   348 #endif
       
   349 	PRINT(_L("update contact in pred search tables - done"));
       
   350 #endif
       
   351 
       
   352 	if(controlTransaction)
       
   353 		{
       
   354 		CommitTransactionL();
       
   355 		}
       
   356 		
       
   357 	// If the item is the System template then delete it from the template
       
   358 	// manager.  The template can later be recreated from the table.
       
   359 	if (aItem.Id() == KGoldenTemplateId)
       
   360 		{
       
   361 		iContactProperties.SystemTemplateManager().DeleteTemplate();
       
   362 		}
       
   363 	
       
   364     // Assuming success if no leaves at this point, so update
       
   365     // the metadata search store for this entry
       
   366     //CCntMetadataOperation* op = CCntMetadataOperation::NewLC(iColSession);
       
   367     //TRAP_IGNORE(op->SaveContactLD(aItem));
       
   368     //CleanupStack::Pop(op); // Do not destroy - called LD function
       
   369 	}
       
   370 
       
   371 /**
       
   372 Deletes the given contact from the database.Forward the call to CPplTableBase
       
   373 based classes representing the tables in the contact database. In low disk condition
       
   374 checks if it can gain access to reserver database space and perform the deletion. If 
       
   375 this is not possible a KErrDiskFull will be thrown.
       
   376 
       
   377 @param aItemId The contact ID of the contact item to be deleted.
       
   378 @param aSessionId The ID of the session that issued the request.  Used to
       
   379 prevent Phonebook Synchroniser deadlock.
       
   380 
       
   381 @leave KErrDiskFull if a full disk error appears
       
   382 
       
   383 @return The item which was read from the database before it was deleted.   This
       
   384 object can be used by, for example, the CLplAnalyserProxy::DeleteLC() method to
       
   385 create a notification message.
       
   386 */	
       
   387 CContactItem* CPplContactItemManager::DeleteLC(TContactItemId  aItemId, TUint aSessionId, TCntSendEventAction /*aEventType*/)
       
   388 	{
       
   389 	TBool controlTransaction = !(iTransactionManager.IsTransactionActive());
       
   390 
       
   391 	CContactItemViewDef* viewDef = CContactItemViewDef::NewL(CContactItemViewDef::EIncludeFields, CContactItemViewDef::EIncludeHiddenFields);
       
   392 	CleanupStack::PushL(viewDef);
       
   393 
       
   394 	if(controlTransaction)
       
   395 		{
       
   396 		StartTransactionL(aSessionId);
       
   397 		}
       
   398 
       
   399 	TBool lowDisk = EFalse;
       
   400 	CContactItem* savedContactItem = static_cast<CPplContactTable*>(iContactTable)->DeleteLC(aItemId, lowDisk);
       
   401 	if (lowDisk) 
       
   402 		{
       
   403 		CleanupStack::PopAndDestroy(savedContactItem); // this was returned from the first call, but not deleted in the db
       
   404 		TInt err = iDatabase.GetReserveAccess();
       
   405 		if(err != KErrNotFound)
       
   406 			{
       
   407 			User::Leave(KErrDiskFull);	
       
   408 			}
       
   409 		
       
   410 		lowDisk = EFalse;
       
   411 		
       
   412 		savedContactItem = static_cast<CPplContactTable*>(iContactTable)->DeleteLC(aItemId, lowDisk);
       
   413 		if(lowDisk)
       
   414 			{
       
   415 			iDatabase.FreeReservedSpace();
       
   416 			User::Leave(KErrDiskFull);	
       
   417 			}
       
   418 		iDatabase.FreeReservedSpace();		
       
   419 		}
       
   420 
       
   421 	lowDisk = EFalse;	
       
   422 	iGroupTable->DeleteL(*savedContactItem, lowDisk);	
       
   423 	if (lowDisk) 
       
   424 		{
       
   425 		DeleteInLowDiskConditionL(iGroupTable, savedContactItem);
       
   426 		}
       
   427 
       
   428 	lowDisk = EFalse;
       
   429 	iCommAddrTable->DeleteL(*savedContactItem, lowDisk);	
       
   430 	if (lowDisk) 
       
   431 		{
       
   432 		DeleteInLowDiskConditionL(iCommAddrTable, savedContactItem);
       
   433 		}
       
   434 
       
   435 #if defined(USE_PRED_SEARCH_TABLE)
       
   436 	PRINT(_L("delete contact from pred search tables"));
       
   437 	lowDisk = EFalse;
       
   438     iPredSearch12keyTable->DeleteL(*savedContactItem, lowDisk);
       
   439     if (lowDisk) 
       
   440 		{
       
   441 		DeleteInLowDiskConditionL(iPredSearch12keyTable, savedContactItem);
       
   442 		}
       
   443 	lowDisk = EFalse;
       
   444 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   445 	iPredSearchQwertyTable->DeleteL(*savedContactItem, lowDisk);
       
   446     if (lowDisk) 
       
   447 		{
       
   448 		DeleteInLowDiskConditionL(iPredSearchQwertyTable, savedContactItem);
       
   449 		}
       
   450 	iPredSearchSettingsTable->DeleteL(*savedContactItem, lowDisk);
       
   451     if (lowDisk) 
       
   452 		{
       
   453 		DeleteInLowDiskConditionL(iPredSearchSettingsTable, savedContactItem);
       
   454 		}
       
   455 #endif
       
   456 	PRINT(_L("delete contact from pred search tables - done"));
       
   457 #endif
       
   458   
       
   459     //Fake checking read access to ICCEntry store to keep BC.
       
   460     iIccContactStore.ReadL(*savedContactItem, EPlGroupMembershipInfo, aSessionId, EFalse);    
       
   461     
       
   462 	//Don't need to check low disk state for ICC synchronizer.
       
   463 	iIccContactStore.DeleteL(*savedContactItem, aSessionId);
       
   464 
       
   465 	if(controlTransaction)
       
   466 		{
       
   467 		CommitTransactionL();  	// Pops item
       
   468 		}
       
   469 		
       
   470 	CleanupStack::Pop();		// Pops item or transaction
       
   471 	CleanupStack::PopAndDestroy(viewDef);	
       
   472 	CleanupStack::PushL(savedContactItem);
       
   473 
       
   474 	// Assume no leaves by this point indicates successful delete,
       
   475 	// therefore update the metadata store
       
   476 	//CCntMetadataOperation* op = CCntMetadataOperation::NewLC(iColSession);
       
   477 	//TRAP_IGNORE(op->DeleteContactLD(aItemId));
       
   478 	//CleanupStack::Pop(op); // Do not destroy - called LD function
       
   479 	
       
   480 	return savedContactItem;
       
   481 	
       
   482 	}
       
   483 	
       
   484 /**
       
   485 Perform a deletion in low disk condition
       
   486 
       
   487 @param aTable CPplTableBase on which the deletion will be done
       
   488 @param aContactItem the contact item to be deleted
       
   489 
       
   490 @leave KErrDiskFull if the deletion can't be done a KerrDiskFull will be throw
       
   491 */
       
   492 void CPplContactItemManager::DeleteInLowDiskConditionL(CPplTableBase* aTable, CContactItem* aContactItem)
       
   493 	{
       
   494 	TInt err = iDatabase.GetReserveAccess();
       
   495 	if(err != KErrNotFound)
       
   496 		{
       
   497 		User::Leave(KErrDiskFull);	
       
   498 		}
       
   499 		
       
   500 	TBool lowDisk = EFalse;
       
   501 	aTable->DeleteL(*aContactItem, lowDisk);
       
   502 	if(lowDisk)
       
   503 		{
       
   504 		iDatabase.FreeReservedSpace();
       
   505 		User::Leave(KErrDiskFull);	
       
   506 		}
       
   507 	iDatabase.FreeReservedSpace();		
       
   508 	}
       
   509 	
       
   510 /**
       
   511 Change the type of the given contact item to the given type.Forward the call to CPplTableBase
       
   512 based classes representing the tables in the contact database.
       
   513 
       
   514 @param aItemId Contact item ID whose type is to be changed.
       
   515 @param aNewType New type for contact item.
       
   516 */	
       
   517 void CPplContactItemManager::ChangeTypeL(TContactItemId aItemId, TUid aNewType)
       
   518 	{
       
   519 	static_cast<CPplContactTable*>(iContactTable)->ChangeTypeL(aItemId, aNewType);
       
   520 	}
       
   521 
       
   522 /** 
       
   523 Does nothing: the CLplAnalyserProxy class sets the connetion ID.
       
   524 */
       
   525 void CPplContactItemManager::SetConnectionId(TInt /*aConnectionId*/)
       
   526 	{
       
   527 	}
       
   528 	
       
   529 /**
       
   530 Second phase constructor for CPplContactItemManager object.
       
   531 Sets the CCntSqlStatement to be used for reading contact item.
       
   532 
       
   533 */
       
   534 void CPplContactItemManager::ConstructL()
       
   535 	{
       
   536 	RDebug::Print(_L("CPplContactItemManager::ConstructL"));
       
   537 	TCntSqlStatementType statementType(ESelect, KSqlContactTableName);
       
   538 	
       
   539 	iSelectStatement = TSqlProvider::GetSqlStatementL(statementType);
       
   540 	
       
   541 	// also prepare everything in CCntSqlStatement
       
   542 	// First add columns from contact table
       
   543 	iSelectStatement->SetParamL(KContactId, KSpace);
       
   544 	iSelectStatement->SetParamL(KContactTemplateId, KSpace);
       
   545 	iSelectStatement->SetParamL(KContactTypeFlags, KSpace);
       
   546 	iSelectStatement->SetParamL(KContactAccessCount, KSpace);
       
   547 	iSelectStatement->SetParamL(KContactCreationDate, KSpace);	
       
   548 	iSelectStatement->SetParamL(KContactLastModified, KSpace);
       
   549 	iSelectStatement->SetParamL(KContactGuidString, KSpace);
       
   550 	iSelectStatement->SetParamL(KContactFirstName, KSpace);
       
   551 	iSelectStatement->SetParamL(KContactLastName, KSpace);
       
   552 	iSelectStatement->SetParamL(KContactCompanyName, KSpace);
       
   553 	iSelectStatement->SetParamL(KContactFirstNamePrn, KSpace);
       
   554 	iSelectStatement->SetParamL(KContactLastNamePrn, KSpace);
       
   555 	iSelectStatement->SetParamL(KContactCompanyNamePrn, KSpace);
       
   556 	
       
   557 	HBufC* condition = HBufC::NewLC(KWhereStringEqualsStringFormatText().Size() + KContactId().Size());
       
   558 	TPtr ptrCondition = condition->Des();
       
   559 	ptrCondition.Format(KWhereStringEqualsStringFormatText, &KContactId, &KVar);
       
   560 	
       
   561 	// Set condition
       
   562 	iSelectStatement->SetConditionL(ptrCondition);
       
   563 	
       
   564 	CleanupStack::PopAndDestroy( condition ); 
       
   565 
       
   566 	// construct tables
       
   567 	iContactTable = CPplContactTable::NewL(iDatabase, iContactProperties);
       
   568 	iCommAddrTable = CPplCommAddrTable::NewL(iDatabase, iContactProperties);
       
   569 	iGroupTable = CPplGroupsTable::NewL(iDatabase);
       
   570 	iPreferencePersistor = CPplPreferencesPersistor::NewL(iDatabase);
       
   571 
       
   572 #if defined(USE_PRED_SEARCH_TABLE)
       
   573 	PRINT(_L("create C12keyPredictiveSearchTable object"));
       
   574 	iPredSearch12keyTable = C12keyPredictiveSearchTable::NewL(iDatabase);
       
   575 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   576 	PRINT(_L("create CQwertyPredictiveSearchTable object"));
       
   577 	iPredSearchQwertyTable = CQwertyPredictiveSearchTable::NewL(iDatabase);
       
   578 	PRINT(_L("create CPredictiveSearchSettingsTable object"));
       
   579 	iPredSearchSettingsTable = CPredictiveSearchSettingsTable::NewL(iDatabase);
       
   580 
       
   581 	iPredictiveSearchSynchronizer =
       
   582 		CPredictiveSearchSynchronizer::NewL(iDatabase,
       
   583 											*iPredSearch12keyTable,
       
   584 											*iPredSearchQwertyTable,
       
   585 											*iPredSearchSettingsTable);
       
   586 #endif // #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   587 #endif // #if defined(USE_PRED_SEARCH_TABLE)
       
   588 
       
   589 	iPresenceTable = CPplPresenceTable::NewL(iDatabase); 
       
   590 	
       
   591 	// Connect to metadata server
       
   592 	//User::LeaveIfError(iColSession.Connect());
       
   593 
       
   594 	RDebug::Print(_L("CPplContactItemManager::ConstructL ends"));
       
   595 	}
       
   596 
       
   597 /**
       
   598 Cleanup operation. If one of the crud operation fails, this method will be called
       
   599 to rollback the sql transaction
       
   600 
       
   601 */
       
   602 void CPplContactItemManager::CleanupOperationRollbackL(TAny* aPplContactItemanager)
       
   603 	{
       
   604 	CPplContactItemManager* contactItemManager = static_cast<CPplContactItemManager*>(aPplContactItemanager);
       
   605 	contactItemManager->iTransactionManager.RollbackCurrentTransactionL(contactItemManager->iSessionId);
       
   606 	}
       
   607 	
       
   608 /**
       
   609 Utility method used to identify if the provided CContactItemField is first name, last name, 
       
   610 company name, first name pronunciation, last name pronunciation or company name pronunciation 
       
   611 Method used to fill information when a CContactItem is read from contact database
       
   612 
       
   613 @param aNameField reference to a constant CContactItemField for which the index will be returned
       
   614 
       
   615 */	
       
   616 TInt CPplContactItemManager::NameFieldIndex(const CContactItemField& aNameField) const
       
   617 	{
       
   618 	// For all the name fields...
       
   619 	for (TInt nameFieldNum=0; nameFieldNum < sizeof(KFastAccessFieldUids)/sizeof(TInt); ++nameFieldNum)
       
   620 		{
       
   621 		if (aNameField.ContentType().ContainsFieldType(TUid::Uid(KFastAccessFieldUids[nameFieldNum])))
       
   622 			{
       
   623 			return nameFieldNum;
       
   624 			}
       
   625 		}
       
   626 	return KErrNotFound;
       
   627 	}
       
   628 	
       
   629 /**
       
   630 Utility method used to start a transaction in database
       
   631 
       
   632 @param aSessionId id of the session
       
   633 */
       
   634 void CPplContactItemManager::StartTransactionL(TUint aSessionId)
       
   635 	{
       
   636 	iTransactionManager.StartTransactionL();
       
   637 	
       
   638 	iSessionId = aSessionId;
       
   639 	CleanupStack::PushL(TCleanupItem(CleanupOperationRollbackL, this));		
       
   640 	}
       
   641 	
       
   642 /**
       
   643 Utility method used to commit a transaction
       
   644 */
       
   645 void CPplContactItemManager::CommitTransactionL()
       
   646 	{
       
   647 	iTransactionManager.CommitCurrentTransactionL(iSessionId);
       
   648 		
       
   649 	CleanupStack::Pop(); //CleanupOperationRollbackL		
       
   650 	}
       
   651 	
       
   652 /**
       
   653 Utility method used to create tables in a newly create database
       
   654 */	
       
   655 void CPplContactItemManager::CreateTablesL()
       
   656 	{
       
   657 	RDebug::Print(_L("CPplContactItemManager::CreateTablesL"));	
       
   658 
       
   659 	TBool controlTransaction = !(iTransactionManager.IsTransactionActive());
       
   660 	
       
   661 	if (controlTransaction)
       
   662 		{
       
   663 		StartTransactionL(0);
       
   664 		}
       
   665 		
       
   666 	iContactTable->CreateTableL();	
       
   667 	iGroupTable->CreateTableL();	
       
   668 	iCommAddrTable->CreateTableL();
       
   669 	iPreferencePersistor->CreateTableL();
       
   670 #if defined(USE_PRED_SEARCH_TABLE)
       
   671 	PRINT(_L("create pred search tables to DB"));	
       
   672 	iPredSearch12keyTable->CreateTableL();
       
   673 #if defined(USE_QWERTY_PRED_SEARCH_TABLE)
       
   674 	iPredSearchQwertyTable->CreateTableL();
       
   675 	iPredSearchSettingsTable->CreateTableL();
       
   676 #endif
       
   677 	PRINT(_L("create pred search tables to DB - done"));	
       
   678 #endif
       
   679 	iPresenceTable->CreateTableL(); 
       
   680 	
       
   681 	if (controlTransaction)
       
   682 		{
       
   683 		CommitTransactionL();
       
   684 		}			
       
   685 
       
   686 	RDebug::Print(_L("CPplContactItemManager::CreateTablesL ends"));	
       
   687 	}
       
   688 	
       
   689 /**
       
   690 Utility method used to check if there is any record in the contact database
       
   691 
       
   692 @return ETrue if the contact database is empty and EFalse otherwise
       
   693 */	
       
   694 TBool CPplContactItemManager::IsDatabaseEmptyL()
       
   695 	{
       
   696 	return static_cast<CPplContactTable*>(iContactTable)->IsTableEmptyL();
       
   697 	}
       
   698 
       
   699 CContactIdArray* CPplContactItemManager::MatchPhoneNumberL(const TDesC& aNumber, TInt aMatchLengthFromRight)
       
   700 	{
       
   701 	// Call comm address table
       
   702 	if (aMatchLengthFromRight == KBestMatchingPhoneNumbers)
       
   703         {
       
   704         return  static_cast<CPplCommAddrTable*>(iCommAddrTable)->BestMatchingPhoneNumberL(aNumber);
       
   705         }
       
   706     else
       
   707         {
       
   708         return  static_cast<CPplCommAddrTable*>(iCommAddrTable)->MatchPhoneNumberL(aNumber, aMatchLengthFromRight);
       
   709         }
       
   710 	}
       
   711 
       
   712 /**
       
   713 Utility method used to retrieve an array of card template ids
       
   714 
       
   715 @return reference to a CContactIdArray containing the card template ids
       
   716 */
       
   717 CContactIdArray& CPplContactItemManager::CardTemplateIdsL()
       
   718 	{
       
   719 	// Call contact table
       
   720 	return  static_cast<CPplContactTable*>(iContactTable)->CardTemplateIdsL();	
       
   721 	}
       
   722 
       
   723 /**
       
   724 Utility method used to retrieve a reference to persistence layer preference persistor
       
   725 */
       
   726 CPplPreferencesPersistor& CPplContactItemManager::PreferencesPersitor()  
       
   727 	{
       
   728 	return *iPreferencePersistor;
       
   729 	}
       
   730 
       
   731 /**
       
   732 Utility method used to retrieve own card contact id
       
   733 */
       
   734 TContactItemId CPplContactItemManager::OwnCardIdL()
       
   735 	{
       
   736 	// Call contact table
       
   737 	return  static_cast<CPplContactTable*>(iContactTable)->OwnCardIdL();		
       
   738 	}
       
   739 	
       
   740 /**
       
   741 Utility method used to set own card id
       
   742 */	
       
   743 void CPplContactItemManager::SetOwnCardIdL(TContactItemId aId, TBool aPersist)
       
   744 	{	
       
   745 	// Call contact table
       
   746 	static_cast<CPplContactTable*>(iContactTable)->SetOwnCardIdL(aId, aPersist);		
       
   747 	}
       
   748 
       
   749 /**
       
   750 Utility class. Returns an array with ids of all groups in contact database
       
   751 */
       
   752 CContactIdArray* CPplContactItemManager::GroupIdListL()
       
   753 	{
       
   754 	CContactIdArray* idArray = CContactIdArray::NewLC();
       
   755 
       
   756 	HBufC* selectString = HBufC::NewLC(KOneTypeField().Length() + KSqlContactTableName().Length() + KContactTypeFlags().Length() + 3); 
       
   757 	TPtr ptrSelectString = selectString->Des();
       
   758 	ptrSelectString.Format(KOneTypeField, &KContactId, &KSqlContactTableName, &KContactTypeFlags, EContactType_Shift, EContactTypeFlags_Group);
       
   759 
       
   760 	RSqlStatement selectStatement;
       
   761 	CleanupClosePushL(selectStatement);
       
   762 	
       
   763 	User::LeaveIfError(selectStatement.Prepare(iDatabase, ptrSelectString));
       
   764 	const TInt KIdx = iSelectStatement->ParameterIndex(KContactId);
       
   765 	
       
   766 	TInt err;
       
   767 	while ((err = selectStatement.Next()) == KSqlAtRow)
       
   768 		{
       
   769 		idArray->AddL(selectStatement.ColumnInt(KIdx));	
       
   770 		}
       
   771 
       
   772 	if (err != KSqlAtEnd)
       
   773 		{
       
   774 		User::Leave(err);
       
   775 		}
       
   776 
       
   777     CleanupStack::PopAndDestroy(&selectStatement);
       
   778 	CleanupStack::PopAndDestroy(selectString);
       
   779 	CleanupStack::Pop(idArray);
       
   780 	
       
   781 	return idArray;
       
   782 	}
       
   783 
       
   784 /**
       
   785 Fast access method for retrieving a list of contact details as raw data.
       
   786 This method can be used for example to fetch the names of all contacts
       
   787 in a very efficient manner. It is assumed that the first column in
       
   788 aSearchQuery is 'id' and that the other columns are text.
       
   789 
       
   790 The returned buffer can be read with RBufReadStream - the first column
       
   791 of each row is a 32-bit integer (the id), the rest of the columns are
       
   792 16-bit descriptors. An id of 0 signifies the end of the list.
       
   793 */
       
   794 CBufSeg* CPplContactItemManager::DetailsListL(const TDesC& aSearchQuery) const
       
   795     {
       
   796     CBufSeg* array = CBufSeg::NewL(4096);
       
   797     CleanupStack::PushL(array);
       
   798 
       
   799     //Prepare and execute the sql query
       
   800     RSqlStatement selectStatement;
       
   801     CleanupClosePushL(selectStatement);
       
   802     User::LeaveIfError(selectStatement.Prepare(iDatabase, aSearchQuery));
       
   803 
       
   804     // Iterate through the results and append the contactIds to idArray
       
   805     TInt err;
       
   806     RBufWriteStream stream;
       
   807     stream.Open(*array);
       
   808     TInt columnCount = selectStatement.ColumnCount();
       
   809     while ((err = selectStatement.Next()) == KSqlAtRow)
       
   810         {
       
   811         stream.WriteInt32L(selectStatement.ColumnInt(0));
       
   812 		for (TInt i = 1; i < columnCount; ++i)
       
   813 	        stream << selectStatement.ColumnTextL(i);
       
   814         }
       
   815     stream.WriteInt32L(0);
       
   816     stream.Close();
       
   817 
       
   818     if (err != KSqlAtEnd)
       
   819         {
       
   820         User::Leave(err);
       
   821         }
       
   822 
       
   823     //Cleanup 
       
   824     CleanupStack::PopAndDestroy(&selectStatement);
       
   825     CleanupStack::Pop(array);
       
   826     
       
   827     return array;
       
   828     }
       
   829 
       
   830 /**
       
   831 Utility method used to rthe prefered card template id
       
   832 */
       
   833 TInt CPplContactItemManager::CardTemplatePrefIdL() const
       
   834 	{
       
   835 	return iPreferencePersistor->PreferredCardTemplateIdL();
       
   836 	}
       
   837 
       
   838 /**
       
   839 Utility method used to set the prefered card template id
       
   840 */
       
   841 void CPplContactItemManager::SetCardTemplatePrefIdL(TInt aCardTemplatePrefId)
       
   842 	{
       
   843 	iPreferencePersistor->SetPreferredCardTemplateIdL(aCardTemplatePrefId);
       
   844 	}
       
   845 
       
   846 void CPplContactItemManager::SynchronizePredSearchTableL()
       
   847 	{
       
   848 #if defined(USE_PRED_SEARCH_TABLE)
       
   849 	iPredictiveSearchSynchronizer->SynchronizeTablesL();
       
   850 #endif
       
   851 	}
       
   852 
       
   853 void CPplContactItemManager::RecreatePredSearchTablesL()
       
   854 	{
       
   855 #if defined(USE_PRED_SEARCH_TABLE)
       
   856 	iPredictiveSearchSynchronizer->DeletePredSearchTablesL();
       
   857 	iPredictiveSearchSynchronizer->CreatePredSearchTablesL();
       
   858 #endif
       
   859 	}