phonebookengines/VirtualPhonebook/VPbkEng/src/CVPbkTopContactOperation.cpp
changeset 0 e686773b3f54
child 13 a6539d1e8e43
equal deleted inserted replaced
-1:000000000000 0:e686773b3f54
       
     1 /*
       
     2 * Copyright (c) 2005-2007 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:  Top Contact opeartion
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDES
       
    20 #include "CVPbkTopContactOperation.h"
       
    21 
       
    22 #include <barsc.h>
       
    23 #include <barsread.h>
       
    24 
       
    25 #include <MVPbkContactViewBase.h>
       
    26 #include <VPbkStoreUriLiterals.h>
       
    27 #include <CVPbkContactViewDefinition.h>
       
    28 #include <CVPbkContactLinkArray.h>
       
    29 #include <MVPbkContactLink.h>
       
    30 #include <MVPbkContactOperationBase.h>
       
    31 #include <MVPbkContactStoreProperties.h>
       
    32 #include <MVPbkContactStoreList.h>
       
    33 #include <CVPbkContactStoreUriArray.h>
       
    34 #include <TVPbkFieldTypeMapping.h>
       
    35 #include <MVPbkContactFieldTextData.h>
       
    36 #include <CVPbkFieldTypeSelector.h>
       
    37 #include <MVPbkFieldType.h>
       
    38 #include <CVPbkContactManager.h>
       
    39 #include <MVPbkContactStore.h>
       
    40 #include <VPbkContactViewFilterBuilder.h>
       
    41 #include <CVPbkSortOrder.h>
       
    42 #include <VPbkEng.rsg>
       
    43 #include <VPbkDataCaging.hrh>
       
    44 #include <RLocalizedResourceFile.h>
       
    45 #include <TVPbkFieldVersitProperty.h>
       
    46 
       
    47 #include "CVPbkContactEasyManager.h"
       
    48 #include "VPbkDebug.h"
       
    49 
       
    50 #include <CVPbkSortOrderAcquirer.h>
       
    51 #include <CVPbkEComImplementationsList.h>
       
    52 #include <VPbkSortOrderAcquirerUid.h>
       
    53 
       
    54 namespace
       
    55 	{
       
    56 	const TInt KFirstTopOrderIndex = 1;
       
    57     const TInt KTcFieldLength = 10;
       
    58     
       
    59     _LIT( KAllContactsSortOrderDisplayName, "AllContacts" );
       
    60 
       
    61     /**
       
    62      * Custom cleanup function.
       
    63      *
       
    64      * @param aObj  Object to clean.
       
    65      */
       
    66     void CleanupResetAndDestroy( TAny* aObj )
       
    67         {
       
    68         if ( aObj )
       
    69             {
       
    70             static_cast<RImplInfoPtrArray*>( aObj )->ResetAndDestroy();
       
    71             }
       
    72         }    
       
    73     
       
    74 #ifdef _DEBUG	
       
    75 	enum TTopErrors
       
    76 	    {
       
    77 		ETopErrorWrongLogic1,
       
    78 		ETopErrorWrongLogic2,
       
    79 		ETopErrorWrongLogic3,
       
    80 		EInvalidViewOperation,
       
    81 		EInvalidLinksOperation,
       
    82 		EInvalidTopOperation,
       
    83 		ETopErrorAlreadyHaveAStore,
       
    84 		ETopErrorAlreadyHaveAView,
       
    85 		ETopErrorNoView,
       
    86 		ETopErrorNoFieldData,
       
    87 		ETopErrorNoLinks,
       
    88 		ETopViewMissing,
       
    89 		ETopErrorBadIndex,
       
    90 		ETopErrorOldArrayExists,
       
    91 		ETopErrorNoContacts,
       
    92         ETopErrorWrongState,
       
    93         ETopErrorWrongStateRun,
       
    94 	    };
       
    95 	
       
    96 	_LIT( KPanicStrTopManagement, "VPbk_topManag");
       
    97 	
       
    98 	void Panic(TTopErrors aReason)
       
    99 	    {
       
   100 	    User::Panic(KPanicStrTopManagement,aReason);
       
   101 	    }
       
   102 #endif	
       
   103 	}
       
   104 
       
   105 ///////////////////////////////////////////////////////////////////////////////
       
   106 
       
   107 CVPbkTopContactOperation* CVPbkTopContactOperation::NewLC(
       
   108         CVPbkContactManager& aContactManager,
       
   109         MVPbkOperationErrorObserver& aErrorObserver,
       
   110         TTopOperation aOperation)
       
   111     {
       
   112     CVPbkTopContactOperation* self = new (ELeave) CVPbkTopContactOperation(
       
   113             aContactManager,
       
   114             aErrorObserver,
       
   115             aOperation );
       
   116     CleanupStack::PushL( self );
       
   117     self->ConstructL();
       
   118     return self;
       
   119     }
       
   120 
       
   121 void CVPbkTopContactOperation::ConstructL()
       
   122     {
       
   123     iContactEasyManager = CVPbkContactEasyManager::NewL( iContactManager );
       
   124     }
       
   125 
       
   126 CVPbkTopContactOperation::CVPbkTopContactOperation(
       
   127         CVPbkContactManager& aContactManager,
       
   128         MVPbkOperationErrorObserver& aErrorObserver,
       
   129         TTopOperation aOperation )
       
   130     : CActive( EPriorityStandard ),
       
   131     iCurrentOperation(aOperation),
       
   132     iNextState(EStateOpenStore),
       
   133     iContactManager(aContactManager),
       
   134     iErrorObserver(&aErrorObserver)
       
   135     {
       
   136     CActiveScheduler::Add( this );
       
   137     CompleteOurself(); //start execution right away
       
   138     }
       
   139 
       
   140 CVPbkTopContactOperation::~CVPbkTopContactOperation()
       
   141     {
       
   142     Cancel();
       
   143     delete iContactOperation;
       
   144     delete iContactEasyManager;
       
   145     iContacts.ResetAndDestroy();
       
   146     delete iInputLinks;
       
   147     delete iView;
       
   148     if ( iContactStore )
       
   149         {
       
   150         // Store is not owned by us.
       
   151         iContactStore->Close( *this );
       
   152         }
       
   153     }
       
   154 
       
   155 MVPbkContactOperationBase* CVPbkTopContactOperation::NewGetViewOperationL(
       
   156         CVPbkContactManager& aContactManager,
       
   157         MVPbkOperationResultObserver<MVPbkContactViewBase*>& aObserver,
       
   158         MVPbkOperationErrorObserver& aErrorObserver,
       
   159         TTopOperation aOperation )
       
   160     {
       
   161     __ASSERT_DEBUG( aOperation == EGetTopContacts || 
       
   162                     aOperation == EGetNonTopContacts,
       
   163                     Panic(EInvalidViewOperation) );
       
   164     
       
   165     CVPbkTopContactOperation* self = NewLC(
       
   166             aContactManager,
       
   167             aErrorObserver,
       
   168             aOperation );
       
   169     self->iViewObserver = &aObserver;
       
   170 
       
   171     CleanupStack::Pop(self);
       
   172     return self;
       
   173     }
       
   174 
       
   175 MVPbkContactOperationBase* CVPbkTopContactOperation::NewGetViewLinksOperationL(
       
   176         CVPbkContactManager& aContactManager,
       
   177         MVPbkOperationResultObserver<MVPbkContactLinkArray*>& aObserver,
       
   178         MVPbkOperationErrorObserver& aErrorObserver,
       
   179         TTopOperation aOperation )
       
   180     {
       
   181     __ASSERT_DEBUG( aOperation == EGetTopContactLinks || 
       
   182                     aOperation == EGetNonTopContactLinks,
       
   183                     Panic(EInvalidLinksOperation) );
       
   184     
       
   185     CVPbkTopContactOperation* self = NewLC(
       
   186             aContactManager,
       
   187             aErrorObserver,
       
   188             aOperation );
       
   189     self->iLinksObserver = &aObserver;
       
   190 
       
   191     CleanupStack::Pop(self);
       
   192     return self;
       
   193     }
       
   194 
       
   195 MVPbkContactOperationBase* CVPbkTopContactOperation::NewTopOperationL(
       
   196         CVPbkContactManager& aContactManager,
       
   197         const MVPbkContactLinkArray& aContactLinks,
       
   198         MVPbkOperationObserver& aObserver,
       
   199         MVPbkOperationErrorObserver& aErrorObserver,
       
   200         TTopOperation aOperation )
       
   201     {
       
   202     __ASSERT_DEBUG( aOperation == EAddToTop || aOperation == ERemoveFromTop ||
       
   203             aOperation == EReorderTop,
       
   204             Panic(EInvalidTopOperation) );
       
   205     
       
   206     CVPbkTopContactOperation* self = NewLC(
       
   207             aContactManager,
       
   208             aErrorObserver,
       
   209             aOperation );
       
   210     self->iObserver = &aObserver;
       
   211     self->iInputLinks = CloneArrayL( aContactLinks ); 
       
   212     
       
   213     CleanupStack::Pop(self);
       
   214     return self;
       
   215     }
       
   216 
       
   217 void CVPbkTopContactOperation::DoCancel()
       
   218 	{
       
   219 	delete iContactOperation;
       
   220 	iContactOperation = NULL;
       
   221 	iContactEasyManager->Cancel();
       
   222 	}
       
   223 
       
   224 void CVPbkTopContactOperation::RunL()
       
   225 	{
       
   226 	if ( iNextState == EStateAbortWithError )
       
   227 	    {
       
   228 	    NotifyError( iAbortError );
       
   229 	    }
       
   230 	else
       
   231 	    {
       
   232     	switch ( iCurrentOperation )
       
   233     	    {
       
   234     	    case EAddToTop:
       
   235     	    case ERemoveFromTop:
       
   236     	    case EReorderTop:
       
   237         		{
       
   238         		Top_RunL();
       
   239         		break;
       
   240         		}
       
   241     	    case EGetNonTopContacts:
       
   242     	    case EGetTopContacts:
       
   243     	    case EGetTopContactLinks:
       
   244     	    case EGetNonTopContactLinks:
       
   245                 {
       
   246         		GetView_RunL();
       
   247         		break;
       
   248                 }
       
   249     	    default:
       
   250     	        __ASSERT_DEBUG( EFalse,
       
   251     	                Panic( ETopErrorWrongStateRun ) );
       
   252             }
       
   253 	    }
       
   254 	}
       
   255 
       
   256 TInt CVPbkTopContactOperation::RunError( TInt aError )
       
   257 	{
       
   258 	NotifyError( aError );
       
   259 	return KErrNone;
       
   260 	}
       
   261 
       
   262 //---------------------------------------------------------------
       
   263 // These are from MVPbkContactViewObserver
       
   264 
       
   265 void CVPbkTopContactOperation::ContactViewReady(
       
   266     MVPbkContactViewBase& aView )
       
   267     {
       
   268     aView.RemoveObserver(*this);  
       
   269 	CompleteOurself();
       
   270     }
       
   271 
       
   272 void CVPbkTopContactOperation::ContactViewUnavailable(
       
   273     MVPbkContactViewBase& aView )
       
   274     {
       
   275     aView.RemoveObserver(*this);
       
   276 	AbortWithError( KErrGeneral );
       
   277     }
       
   278 
       
   279 void CVPbkTopContactOperation::ContactAddedToView(
       
   280     MVPbkContactViewBase& /*aView*/, 
       
   281     TInt /*aIndex*/, 
       
   282     const MVPbkContactLink& /*aContactLink*/ )
       
   283     {
       
   284     }
       
   285 
       
   286 void CVPbkTopContactOperation::ContactRemovedFromView(
       
   287     MVPbkContactViewBase& /*aView*/, 
       
   288     TInt /*aIndex*/, 
       
   289     const MVPbkContactLink& /*aContactLink*/ )
       
   290     {
       
   291     }
       
   292 
       
   293 void CVPbkTopContactOperation::ContactViewError(
       
   294         MVPbkContactViewBase& /*aView*/, 
       
   295         TInt aError, 
       
   296         TBool /*aErrorNotified*/ )
       
   297     {
       
   298     AbortWithError( aError );
       
   299     }
       
   300 
       
   301 
       
   302 //---------------------------------------------------------------
       
   303 // These are from MVPbkContactStoreObserver
       
   304 
       
   305 void CVPbkTopContactOperation::StoreReady(MVPbkContactStore& /*aContactStore*/)
       
   306 	{
       
   307 	CompleteOurself();
       
   308 	}
       
   309 
       
   310 void CVPbkTopContactOperation::StoreUnavailable(
       
   311 	MVPbkContactStore& /*aContactStore*/, TInt aReason)
       
   312 	{
       
   313 	AbortWithError( aReason );
       
   314 	}
       
   315 
       
   316 void CVPbkTopContactOperation::HandleStoreEventL(
       
   317     MVPbkContactStore& /*aContactStore*/, 
       
   318     TVPbkContactStoreEvent /*aStoreEvent*/)
       
   319 	{
       
   320 	}
       
   321 
       
   322 //---------------------------------------------------------------
       
   323 // These are from MVPbkBatchOperationObserver
       
   324 
       
   325 void CVPbkTopContactOperation::StepComplete( 
       
   326     MVPbkContactOperationBase& /*aOperation*/,
       
   327     TInt /*aStepSize*/ )
       
   328     {
       
   329     // Ignore.
       
   330     }
       
   331 
       
   332 TBool CVPbkTopContactOperation::StepFailed(
       
   333     MVPbkContactOperationBase& /*aOperation*/,
       
   334     TInt /*aStepSize*/, TInt aError )
       
   335     {
       
   336     AbortWithError( aError );
       
   337     delete iContactOperation;
       
   338     iContactOperation = NULL;
       
   339     return EFalse; // do not continue
       
   340     }
       
   341 
       
   342 void CVPbkTopContactOperation::OperationComplete( 
       
   343     MVPbkContactOperationBase& /*aOperation*/ )
       
   344     {
       
   345     // Committing of contacts has completed.
       
   346     delete iContactOperation;
       
   347     iContactOperation = NULL;
       
   348     iContacts.ResetAndDestroy();
       
   349     //can leave only when returning links 
       
   350     TRAP_IGNORE(NotifyResultL());
       
   351     }
       
   352 
       
   353 //---------------------------------------------------------------
       
   354 // From MVPbkContactEasyManagerObserver
       
   355 void CVPbkTopContactOperation::VPbkOperationCompleted(
       
   356         MVPbkContactOperationBase* /*aOperation*/)
       
   357     {
       
   358 
       
   359     // Retrieving and locking of contacts is now complete.
       
   360     CompleteOurself();
       
   361     // Continue processing in RunL()
       
   362     }
       
   363 
       
   364 void CVPbkTopContactOperation::VPbkOperationFailed(
       
   365         MVPbkContactOperationBase* /*aOperation*/,
       
   366         TInt aError )
       
   367     {
       
   368     AbortWithError( aError );
       
   369     }
       
   370 
       
   371 // --------------------------------------------------------------------------
       
   372 // Creates contact link array from a contact view.
       
   373 // --------------------------------------------------------------------------
       
   374 MVPbkContactLinkArray* CVPbkTopContactOperation::ViewToLinkArrayL(
       
   375         const MVPbkContactViewBase& aView )
       
   376     {
       
   377     CVPbkContactLinkArray* links = CVPbkContactLinkArray::NewLC(); 
       
   378     TInt count = aView.ContactCountL();
       
   379     for ( TInt n = 0; n  < count; ++n )
       
   380         {
       
   381         MVPbkContactLink* link = aView.CreateLinkLC( n );
       
   382         links->AppendL( link );
       
   383         CleanupStack::Pop(); // link
       
   384         }
       
   385     CleanupStack::Pop( links );
       
   386     return links;
       
   387     }
       
   388 
       
   389 // --------------------------------------------------------------------------
       
   390 // Loads and opens contact store
       
   391 // --------------------------------------------------------------------------
       
   392 void CVPbkTopContactOperation::OpenStoreL( const TVPbkContactStoreUriPtr& aUri )
       
   393     {
       
   394     // First need to open the store.
       
   395     iContactManager.LoadContactStoreL( aUri );
       
   396 
       
   397     iContactStore = iContactManager.ContactStoresL().Find( aUri );
       
   398     // Asynchronous opening call.
       
   399     iContactStore->OpenL(*this);
       
   400     }
       
   401 
       
   402 // --------------------------------------------------------------------------
       
   403 // Loads and opens default contact store
       
   404 // --------------------------------------------------------------------------
       
   405 void CVPbkTopContactOperation::OpenDefaultStoreL()
       
   406     {
       
   407     TVPbkContactStoreUriPtr uri( KVPbkDefaultCntDbURI );
       
   408     OpenStoreL( uri );
       
   409 	}
       
   410 
       
   411 // --------------------------------------------------------------------------
       
   412 // Requests a top contact view. The completion is signalled to this
       
   413 // object through MVPbkContactViewObserver. The observer callback will pass
       
   414 // the event on in a certain way that is dependent on the current iState
       
   415 // value.
       
   416 // -------------------------------------------------------------------------- 
       
   417 void CVPbkTopContactOperation::RequestTopContactsViewL()
       
   418 	{
       
   419 	__ASSERT_DEBUG( !iView, Panic(ETopErrorAlreadyHaveAView) );
       
   420 	
       
   421     CVPbkContactViewDefinition* viewDef = CVPbkContactViewDefinition::NewLC();
       
   422     viewDef->SetUriL( KVPbkDefaultCntDbURI );
       
   423     
       
   424     CVPbkFieldTypeSelector* filter = CVPbkFieldTypeSelector::NewL(
       
   425         iContactManager.FieldTypes());
       
   426     CleanupStack::PushL(filter);         
       
   427     VPbkContactViewFilterBuilder::BuildContactViewFilterL( *filter, 
       
   428         TVPbkContactViewFilter(EVPbkContactViewFilterTopContact), iContactManager );
       
   429 
       
   430     viewDef->SetFieldTypeFilterL( filter ); 
       
   431     CleanupStack::PopAndDestroy( filter );  
       
   432 
       
   433     CVPbkSortOrderAcquirer* soa = AllContactsSortOrderL();
       
   434     CleanupStack::PushL(soa);
       
   435 
       
   436     iView = iContactManager.CreateContactViewLC(
       
   437         *this, *viewDef, soa->SortOrder() );
       
   438 
       
   439     CleanupStack::Pop(); // iView
       
   440     CleanupStack::PopAndDestroy( soa );
       
   441     CleanupStack::PopAndDestroy( viewDef );
       
   442 	}
       
   443 
       
   444 // --------------------------------------------------------------------------
       
   445 // Requests a top contact view. The completion is signalled to this
       
   446 // object through MVPbkContactViewObserver. The observer callback will pass
       
   447 // the event on in a certain way that is dependent on the current iState
       
   448 // value.
       
   449 // --------------------------------------------------------------------------
       
   450 void CVPbkTopContactOperation::RequestNonTopContactsViewL()
       
   451 	{
       
   452 	__ASSERT_DEBUG( !iView, Panic(ETopErrorAlreadyHaveAView) );
       
   453 	
       
   454     CVPbkContactViewDefinition* viewDef = CVPbkContactViewDefinition::NewLC();
       
   455     viewDef->SetUriL( KVPbkDefaultCntDbURI );
       
   456     
       
   457     CVPbkSortOrderAcquirer* soa = AllContactsSortOrderL();
       
   458     CleanupStack::PushL(soa);
       
   459 
       
   460     // Add the Non-Top Contacts selector           
       
   461     // No filter (i.e. with a field x) is used
       
   462     // but a contact selector
       
   463     viewDef->SetContactSelector(this);   // ownership not transferred     
       
   464 
       
   465     iView = iContactManager.CreateContactViewLC(
       
   466         *this, *viewDef, soa->SortOrder() );
       
   467 
       
   468     CleanupStack::Pop(); // iView
       
   469     CleanupStack::PopAndDestroy( soa );
       
   470     CleanupStack::PopAndDestroy( viewDef );
       
   471 	}
       
   472 
       
   473 // --------------------------------------------------------------------------
       
   474 // The RunL handler for top operations.
       
   475 // --------------------------------------------------------------------------
       
   476 inline void CVPbkTopContactOperation::Top_RunL()
       
   477 	{
       
   478 	if ( iNextState == EStateOpenStore )
       
   479         {
       
   480         if ( iInputLinks->Count() > 0 )
       
   481             {
       
   482             // view is needed for AddToTop operation to get next top index
       
   483             if ( iCurrentOperation == EAddToTop )
       
   484                 {
       
   485                 iNextState = EStateCreateView;
       
   486                 }
       
   487             else
       
   488                 {
       
   489                 iNextState = EStateRetrieveLock;
       
   490                 }
       
   491             OpenStoreL( iInputLinks->At(0).ContactStore().StoreProperties().Uri() );
       
   492             }
       
   493         else
       
   494             {
       
   495             // Empty input array is ok do nothing
       
   496             // just signal completion right away
       
   497             iNextState = EStateNone;
       
   498             NotifyResultL();
       
   499             }
       
   500         }
       
   501 	else if ( iNextState == EStateCreateView )
       
   502 		{
       
   503 		iNextState = EStateRetrieveLock;
       
   504 		RequestTopContactsViewL();
       
   505 		// When view is ready, we come back to this function.
       
   506 		}
       
   507 	else if ( iNextState == EStateRetrieveLock )
       
   508 		{
       
   509         iNextState = EStateModifyCommit;
       
   510         iContactEasyManager->RetrieveAndLockContactsL(
       
   511             *iInputLinks, iContacts, *this, *this );
       
   512         // The contacts are placed into iContacts.
       
   513         // Completion is signalled to our callback, which
       
   514         // will complete ourself so we come back here to the next state.
       
   515 		}
       
   516     else if ( iNextState == EStateModifyCommit )
       
   517         {
       
   518         DoTopOperationL();
       
   519         
       
   520         iNextState = EStateNone;
       
   521         iContactOperation = iContactManager.CommitContactsL(
       
   522             iContacts.Array(), *this );
       
   523         // Completion is signalled to our callback, where our observer is
       
   524         // called for informing that everything is done.
       
   525         }
       
   526 	}
       
   527 
       
   528 // --------------------------------------------------------------------------
       
   529 // Perform actual contact modification, add, remove or change toppnes
       
   530 // depending on the operation
       
   531 // --------------------------------------------------------------------------
       
   532 inline void CVPbkTopContactOperation::DoTopOperationL()
       
   533     {
       
   534     switch( iCurrentOperation )
       
   535         {
       
   536         case EAddToTop:
       
   537             {
       
   538             // get next top index and delete the view right away, 
       
   539             __ASSERT_DEBUG( iView, Panic(ETopViewMissing) );
       
   540             TInt nextTopIndex = NextTopOrderIndexL( *iView );
       
   541             __ASSERT_DEBUG( nextTopIndex >= 0, Panic(ETopErrorBadIndex) );
       
   542             delete iView;
       
   543             iView = NULL;
       
   544 
       
   545             SetTopOrderToContactsL( iContacts, nextTopIndex );
       
   546             break;
       
   547             }
       
   548         case ERemoveFromTop:
       
   549             {
       
   550             RemoveTopnessFromContacts( iContacts );
       
   551             break;
       
   552             }
       
   553         case EReorderTop:
       
   554             {
       
   555             ReorderContactsL( iContacts );
       
   556             break;
       
   557             }
       
   558         default:
       
   559             __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   560         }   
       
   561     }
       
   562 
       
   563 // --------------------------------------------------------------------------
       
   564 // The RunL handler for get view/links operation.
       
   565 // --------------------------------------------------------------------------
       
   566 inline void CVPbkTopContactOperation::GetView_RunL()
       
   567 	{
       
   568 	if ( iNextState == EStateOpenStore )
       
   569         {
       
   570         iNextState = EStateCreateView;
       
   571         OpenDefaultStoreL();
       
   572         }
       
   573     else if ( iNextState == EStateCreateView )
       
   574 	    {
       
   575 	    iNextState = EStateNone;
       
   576 	    switch( iCurrentOperation )
       
   577 	        {
       
   578 	        case EGetTopContacts:
       
   579 	        case EGetTopContactLinks:
       
   580 	            {
       
   581 	            RequestTopContactsViewL();
       
   582 	            break;
       
   583 	            }
       
   584 	        case EGetNonTopContacts:
       
   585 	        case EGetNonTopContactLinks:
       
   586 	            {
       
   587 	            RequestNonTopContactsViewL();
       
   588 	            break;
       
   589 	            }
       
   590 	        default:
       
   591 	            __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   592 	        } 	    
       
   593 	    }
       
   594 	else
       
   595 	    {
       
   596 	    __ASSERT_DEBUG( iNextState == EStateNone, Panic(ETopErrorWrongState) );
       
   597     	// The view is ready.
       
   598     	NotifyResultL();
       
   599 	    }
       
   600 	}
       
   601 
       
   602 // --------------------------------------------------------------------------
       
   603 // Finds out what is the top ordering index for new top contacts.
       
   604 // It looks at the collection of top contacts in iView which has been fetched
       
   605 // earlier.
       
   606 // @return The next top index, or KFirstTopOrderIndex if no valid data was found.
       
   607 // --------------------------------------------------------------------------
       
   608 TInt CVPbkTopContactOperation::NextTopOrderIndexL(
       
   609     const MVPbkContactViewBase& aView )
       
   610 	{
       
   611 	const TInt count = aView.ContactCountL();
       
   612 	TInt result = KFirstTopOrderIndex; // The default if no tops exist yet.
       
   613 	if ( count > 0 )
       
   614 		{
       
   615 		// Take the last contact.
       
   616 		const MVPbkViewContact& contact = aView.ContactAtL( count - 1 );
       
   617 		const TInt orderValue = TopOrder( contact );
       
   618 		// Check the validity of the stored value.
       
   619 		if ( orderValue >=  KFirstTopOrderIndex && orderValue < KMaxTInt )
       
   620 		    {
       
   621 		    // Yes the value is OK.
       
   622 		    // Offset of one from existing last top contact.
       
   623 		    result = orderValue + 1;
       
   624 		    }
       
   625 		}
       
   626 	return result;
       
   627 	}
       
   628 
       
   629 // --------------------------------------------------------------------------
       
   630 // Completes this active object.
       
   631 // --------------------------------------------------------------------------
       
   632 void CVPbkTopContactOperation::CompleteOurself()
       
   633 	{
       
   634 	if ( !IsActive() )
       
   635 		{
       
   636 		TRequestStatus* status = &iStatus;
       
   637 	    User::RequestComplete( status, KErrNone );
       
   638 	    SetActive();
       
   639 		}
       
   640 	else
       
   641 		{
       
   642 		__ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongLogic3) );
       
   643 		}
       
   644 	}
       
   645 
       
   646 // --------------------------------------------------------------------------
       
   647 // Clone contact link array, used to copy input link array
       
   648 // --------------------------------------------------------------------------
       
   649 CVPbkContactLinkArray* CVPbkTopContactOperation::CloneArrayL(
       
   650 	const MVPbkContactLinkArray& aArray )
       
   651 	{
       
   652 	CVPbkContactLinkArray* newArray = CVPbkContactLinkArray::NewLC();
       
   653 	const TInt count = aArray.Count();
       
   654 	for ( TInt n = 0; n < count; ++n )
       
   655 		{
       
   656         MVPbkContactLink* link = aArray.At(n).CloneLC();
       
   657         newArray->AppendL( link );
       
   658         CleanupStack::Pop(); // link
       
   659 		}
       
   660 	CleanupStack::Pop( newArray );
       
   661 	return newArray;
       
   662 	}
       
   663 
       
   664 // --------------------------------------------------------------------------
       
   665 // Sets the top contact data to the contacts.
       
   666 // Does not commit the contacts.
       
   667 // The contacts might already have some top data. If not then
       
   668 // the data holder is created.
       
   669 // @param aContacts The contacts to be modified.
       
   670 // @param aHighestOrderIndex The value from which ordering starts. The order
       
   671 // value increases in steps of one.
       
   672 // --------------------------------------------------------------------------
       
   673 void CVPbkTopContactOperation::SetTopOrderToContactsL(
       
   674     RPointerArray<MVPbkStoreContact>& aContacts,
       
   675     TInt aHighestOrderIndex )
       
   676     {
       
   677     TInt topOrderIndex = aHighestOrderIndex; 
       
   678     const TInt count = aContacts.Count();
       
   679     for ( TInt n = 0; n < count; ++ n )
       
   680         {
       
   681         MVPbkStoreContact& contact = *aContacts[ n ];
       
   682         SetTopOrderL( contact, topOrderIndex );
       
   683         ++topOrderIndex;
       
   684         }
       
   685     }
       
   686 
       
   687 // --------------------------------------------------------------------------
       
   688 // Remove "top" field from contacts
       
   689 // --------------------------------------------------------------------------
       
   690 void CVPbkTopContactOperation::RemoveTopnessFromContacts(
       
   691     RPointerArray<MVPbkStoreContact>& aContacts )
       
   692     {
       
   693     const TInt count = aContacts.Count();
       
   694     for ( TInt n = 0; n < count; ++ n )
       
   695         {
       
   696         MVPbkStoreContact& contact = *aContacts[ n ];
       
   697         RemoveTopnessFromContact( contact );
       
   698         }
       
   699     }
       
   700 
       
   701 // --------------------------------------------------------------------------
       
   702 // Find and remove the "top" field from a contact
       
   703 // --------------------------------------------------------------------------
       
   704 void CVPbkTopContactOperation::RemoveTopnessFromContact(
       
   705     MVPbkStoreContact& aContact )
       
   706     {
       
   707     MVPbkStoreContactFieldCollection& fields = aContact.Fields();
       
   708     const TInt count = fields.FieldCount();
       
   709     for ( TInt n = 0; n < count; ++n )
       
   710         {
       
   711         TVPbkFieldVersitProperty versitProp;
       
   712         versitProp.SetName(EVPbkVersitNameTopContact);
       
   713         const MVPbkFieldType* fieldType = fields.FieldAt(n).BestMatchingFieldType();
       
   714         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   715             {
       
   716             aContact.RemoveField( n );
       
   717             break;
       
   718             }
       
   719         }
       
   720     }
       
   721 
       
   722 // --------------------------------------------------------------------------
       
   723 // Change contacts "top" field according to their relative order
       
   724 // in the input array. Reuses top values the contacts
       
   725 // --------------------------------------------------------------------------
       
   726 void CVPbkTopContactOperation::ReorderContactsL(
       
   727     RPointerArray<MVPbkStoreContact>& aContacts )
       
   728     {
       
   729     const TInt count = aContacts.Count();
       
   730     RArray<TInt> topOrders;
       
   731     RPointerArray<MVPbkStoreContact> contactsToBeReordered; // does not own
       
   732     CleanupClosePushL(topOrders);
       
   733     CleanupClosePushL(contactsToBeReordered);
       
   734     
       
   735     for ( TInt n = 0; n < count; ++n )
       
   736         {
       
   737         const MVPbkStoreContact& contact = *aContacts[ n ];
       
   738         const TInt topOrder = TopOrder( contact );
       
   739         if ( topOrder >= 0 )
       
   740             {
       
   741             // Yes it is a top contact.
       
   742             User::LeaveIfError( contactsToBeReordered.Append( &contact ) );
       
   743             topOrders.AppendL( topOrder );
       
   744             }
       
   745         }
       
   746     topOrders.Sort();
       
   747 
       
   748     // Now set the order values. Reuse the old order values, but assign them
       
   749     // now to different contacts.
       
   750     const TInt reorderCount = topOrders.Count();
       
   751     for ( TInt i = 0; i < reorderCount; ++i )
       
   752         {
       
   753         MVPbkStoreContact& contact = *contactsToBeReordered[ i ];
       
   754         SetTopOrderL( contact, topOrders[ i ] );
       
   755         }
       
   756     CleanupStack::PopAndDestroy(); //contactsToBeReordered
       
   757     CleanupStack::PopAndDestroy(); // topOrders
       
   758     }
       
   759 
       
   760 // --------------------------------------------------------------------------
       
   761 // Returns field type for the top field type
       
   762 // --------------------------------------------------------------------------
       
   763 const MVPbkFieldType& CVPbkTopContactOperation::TopContactFieldTypeL()
       
   764     {
       
   765     const MVPbkFieldType* fieldType;
       
   766     TVPbkFieldTypeMapping mapping;
       
   767     TVPbkFieldVersitProperty versitProp;
       
   768     versitProp.SetName(EVPbkVersitNameTopContact);
       
   769     mapping.SetVersitProperty(versitProp);
       
   770     fieldType = mapping.FindMatch(iContactManager.FieldTypes());
       
   771     if (!fieldType)
       
   772         {
       
   773         User::Leave(KErrNotFound);
       
   774         }
       
   775     return *fieldType;
       
   776     }
       
   777 
       
   778 
       
   779 // --------------------------------------------------------------------------
       
   780 // Gives the top contact order value.
       
   781 // If there is no valid Top Contact order value, then returns
       
   782 // KErrNotFound.
       
   783 //
       
   784 // @param aTopContact The top contact.
       
   785 // @return Order value, or KErrNotFound if there is no
       
   786 //         Top Contact data.
       
   787 // --------------------------------------------------------------------------
       
   788 TInt CVPbkTopContactOperation::TopOrder( const MVPbkBaseContact& aContact )
       
   789     {
       
   790     const MVPbkContactFieldTextData* textData = FindTopFieldTextData( aContact );
       
   791     TInt result = KErrNotFound;
       
   792     if ( textData )
       
   793         {
       
   794         TPtrC text(textData->Text());
       
   795         const TBool isEmpty = textData->IsEmpty();
       
   796         TLex lexer(text);
       
   797         
       
   798         if ( !isEmpty )
       
   799             {
       
   800             TInt topOrder;
       
   801             if(!lexer.Val(topOrder))
       
   802 	            {
       
   803 	             result=topOrder;	
       
   804 	            }
       
   805             }
       
   806         }          
       
   807     return result;
       
   808     }
       
   809 
       
   810 // --------------------------------------------------------------------------
       
   811 // From MVPbkContactSelector
       
   812 // --------------------------------------------------------------------------
       
   813 TBool CVPbkTopContactOperation::IsContactIncluded( const MVPbkBaseContact& aContact )
       
   814     {
       
   815     return (TopOrder(aContact) == KErrNotFound);
       
   816     }
       
   817 
       
   818 // --------------------------------------------------------------------------
       
   819 // Saves top index to the contact field
       
   820 // --------------------------------------------------------------------------
       
   821 void CVPbkTopContactOperation::SetTopOrderL(
       
   822     MVPbkContactFieldTextData& aTextData, TInt aTopOrderIndex )
       
   823     {
       
   824     TBuf<KTcFieldLength> text;
       
   825     text.NumFixedWidth(aTopOrderIndex, EDecimal, KTcFieldLength);
       
   826     aTextData.SetTextL( text );
       
   827     }
       
   828 
       
   829 // --------------------------------------------------------------------------
       
   830 // Adds given top index to a store contact
       
   831 // --------------------------------------------------------------------------
       
   832 void CVPbkTopContactOperation::SetTopOrderL(
       
   833     MVPbkStoreContact& aContact, TInt aTopOrderIndex )
       
   834     {
       
   835     MVPbkContactFieldTextData* textData = FindTopFieldTextData( aContact );
       
   836     if ( textData )
       
   837         {
       
   838         // The field already exists
       
   839         SetTopOrderL( *textData, aTopOrderIndex );
       
   840         }
       
   841     else
       
   842         {
       
   843         // Need to create the field.
       
   844         MVPbkStoreContactField* field = aContact.CreateFieldLC(
       
   845             TopContactFieldTypeL() );        
       
   846         MVPbkContactFieldTextData& fieldData = 
       
   847             MVPbkContactFieldTextData::Cast( field->FieldData() );        
       
   848         SetTopOrderL( fieldData, aTopOrderIndex );
       
   849         // Add VPbk Field to the contact
       
   850         aContact.AddFieldL(field);                    
       
   851         CleanupStack::Pop(); // field
       
   852         }    
       
   853     }
       
   854 
       
   855 // --------------------------------------------------------------------------
       
   856 // Retruns top field text data of a view contact
       
   857 // or NULL if aContact doesn't have top field
       
   858 // --------------------------------------------------------------------------
       
   859 const MVPbkContactFieldTextData* CVPbkTopContactOperation::FindTopFieldTextData(
       
   860     const MVPbkBaseContact& aContact )
       
   861     {
       
   862     // Loop through all VPbk fields in the contact 
       
   863     // check if a field contains top contact type.
       
   864     const MVPbkBaseContactFieldCollection& fields = aContact.Fields();
       
   865     const TInt count = fields.FieldCount();
       
   866     const MVPbkContactFieldTextData* result = NULL;
       
   867     for ( TUint i = 0; i < count && !result; ++i )
       
   868         {
       
   869         const MVPbkBaseContactField& field = fields.FieldAt(i);
       
   870         TVPbkFieldVersitProperty versitProp;
       
   871         versitProp.SetName(EVPbkVersitNameTopContact);
       
   872         const MVPbkFieldType* fieldType = field.BestMatchingFieldType();
       
   873         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   874             {
       
   875             // Contact Template has Top Contact Field, therefore
       
   876             // a newly created contact will have an empty TC field
       
   877             // So, remember to make an additional check to see if the field
       
   878             // has data or not by calling IsEmpty().
       
   879             result = &MVPbkContactFieldTextData::Cast( field.FieldData() );        
       
   880             }                   
       
   881         }
       
   882     return result;
       
   883     }
       
   884 
       
   885 // --------------------------------------------------------------------------
       
   886 // Retruns top field text data of a store contact
       
   887 // or NULL if aContact doesn't have top field
       
   888 // --------------------------------------------------------------------------
       
   889 MVPbkContactFieldTextData* CVPbkTopContactOperation::FindTopFieldTextData(
       
   890     MVPbkStoreContact& aContact )
       
   891     {
       
   892     // Loop through all VPbk fields in the contact 
       
   893     // check if a field contains top contact type.
       
   894     MVPbkStoreContactFieldCollection& fields = aContact.Fields();
       
   895     const TInt count = fields.FieldCount();
       
   896     MVPbkContactFieldTextData* result = NULL;
       
   897     for ( TUint i = 0; i < count && !result; ++i )
       
   898         {
       
   899         MVPbkStoreContactField& field = fields.FieldAt(i);
       
   900         TVPbkFieldVersitProperty versitProp;
       
   901         versitProp.SetName(EVPbkVersitNameTopContact);
       
   902         const MVPbkFieldType* fieldType = field.BestMatchingFieldType();
       
   903         if ( fieldType && fieldType->Matches(versitProp, 0) )
       
   904             {
       
   905             // Contact Template has Top Contact Field, therefore
       
   906             // a newly created contact will have an empty TC field
       
   907             // So, remember to make an additional check to see if the field
       
   908             // has data or not by calling IsEmpty().
       
   909             result = &MVPbkContactFieldTextData::Cast( field.FieldData() );        
       
   910             }                   
       
   911         }
       
   912     return result;
       
   913     }
       
   914 
       
   915 // --------------------------------------------------------------------------
       
   916 // Notifies operation observer of results
       
   917 // --------------------------------------------------------------------------
       
   918 void CVPbkTopContactOperation::NotifyResultL()
       
   919     {
       
   920     switch( iCurrentOperation )
       
   921         {
       
   922         case EGetTopContacts:
       
   923         case EGetNonTopContacts:
       
   924             {
       
   925             __ASSERT_DEBUG( iView, Panic(ETopErrorNoView) );
       
   926             MVPbkContactViewBase* view = iView;
       
   927             iView = NULL; //transfer ownership
       
   928             iViewObserver->VPbkOperationResultCompleted( this, view );
       
   929             break;
       
   930             }
       
   931         case EGetTopContactLinks:
       
   932         case EGetNonTopContactLinks:
       
   933             {
       
   934             __ASSERT_DEBUG( iView, Panic(ETopErrorNoView) );
       
   935             MVPbkContactLinkArray* links = ViewToLinkArrayL( *iView );
       
   936             iLinksObserver->VPbkOperationResultCompleted( this, links );
       
   937             break;
       
   938             }
       
   939         case EAddToTop:
       
   940         case ERemoveFromTop:
       
   941         case EReorderTop:
       
   942             {
       
   943             iObserver->VPbkOperationCompleted( this );
       
   944             break;
       
   945             }
       
   946         default:
       
   947             __ASSERT_DEBUG( EFalse, Panic(ETopErrorWrongState) );
       
   948         }
       
   949     }
       
   950 
       
   951 // --------------------------------------------------------------------------
       
   952 // Sends error notification to the error observer
       
   953 // --------------------------------------------------------------------------
       
   954 inline void CVPbkTopContactOperation::NotifyError(TInt aErr)
       
   955     {
       
   956     iErrorObserver->VPbkOperationFailed( this, aErr );
       
   957     }
       
   958 
       
   959 // --------------------------------------------------------------------------
       
   960 // Notify error async
       
   961 // --------------------------------------------------------------------------
       
   962 void CVPbkTopContactOperation::AbortWithError(TInt aErr)
       
   963     {
       
   964     iAbortError = aErr;
       
   965     iNextState = EStateAbortWithError;
       
   966     CompleteOurself();
       
   967     }
       
   968 
       
   969 // --------------------------------------------------------------------------
       
   970 // Aquire sort order from presentation layer
       
   971 // --------------------------------------------------------------------------
       
   972 CVPbkSortOrderAcquirer* CVPbkTopContactOperation::AllContactsSortOrderL() const
       
   973     {
       
   974     CVPbkSortOrderAcquirer* result = NULL;
       
   975     // Acquire group sort order
       
   976     RImplInfoPtrArray implementations;
       
   977     REComSession::ListImplementationsL
       
   978         ( TUid::Uid( KVPbkSortOrderAcquirerInterfaceUID ), implementations );
       
   979     CleanupStack::PushL( TCleanupItem
       
   980             ( CleanupResetAndDestroy, &implementations ) );
       
   981 
       
   982     TBool found = EFalse;
       
   983     const TInt count = implementations.Count();
       
   984     for ( TInt i = count - 1; i >= 0 && !found ; --i )
       
   985         {
       
   986         CImplementationInformation* implInfo = implementations[i];
       
   987 
       
   988         if ( implInfo->DisplayName().
       
   989                 CompareC( KAllContactsSortOrderDisplayName ) == 0 )
       
   990             {
       
   991             TUid implUid = implInfo->ImplementationUid();
       
   992 
       
   993             CVPbkSortOrderAcquirer::TSortOrderAcquirerParam param
       
   994                 ( iContactManager.FieldTypes() );
       
   995 
       
   996             result = CVPbkSortOrderAcquirer::NewL
       
   997                 ( implUid, param );
       
   998             found = ETrue;
       
   999             }
       
  1000         }
       
  1001     CleanupStack::PopAndDestroy(); // implementations
       
  1002     return result;
       
  1003     }
       
  1004 
       
  1005 // end of file