wvuing/wvuipresence/src/CAPresenceUtils.cpp
changeset 0 094583676ce7
equal deleted inserted replaced
-1:000000000000 0:094583676ce7
       
     1 /*
       
     2 * Copyright (c) 2002-2005 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:  Utility class for presence functions
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "CAPresenceDefinitions.h"
       
    22 #include "CAPresenceUtils.h"
       
    23 #include "ChatDebugPrint.h"
       
    24 #include "CCAStorageManagerFactory.h"
       
    25 #include "MCAStoredContact.h"
       
    26 #include "MCAStoredContacts.h"
       
    27 #include "MCAWatcherObserver.h"
       
    28 #include "CCAPresenceError.h"
       
    29 #include "CCAPresenceErrors.h"
       
    30 #include "ImpsCSPAllErrors.h"
       
    31 #include "CAPresenceConst.h"
       
    32 #include "MCAContactList.h"
       
    33 #include "TDecodeAttrParams.h"
       
    34 #include "SServerPrefers.h"
       
    35 #include "MCAPresenceUpdater.h"
       
    36 #include "impsbuilddefinitions.h"
       
    37 
       
    38 #include "WVUIPresenceVariationNG.hrh"
       
    39 #include <WVUIPresenceVariationNG.rsg>
       
    40 
       
    41 #include <PEngWVPresenceAttributes2.h>
       
    42 #include <MPEngPresenceAttrModel2.h>
       
    43 #include <MPEngContactList2.h>
       
    44 #include <MPEngTransactionStatus2.h>
       
    45 #include <PEngWVPresenceErrors2.h>
       
    46 #include <ImpsErrors.h>
       
    47 #include <PEngPresenceEngineErrors2.h>
       
    48 #include <MPEngContactItem.h>
       
    49 #include <MPEngContactListProperties.h>
       
    50 #include <barsread.h> // RResourceReader
       
    51 #include <eikenv.h>
       
    52 
       
    53 // "test character identity and accents, ignore case"
       
    54 const TInt KCollationLevel = 1;
       
    55 #ifndef IMPS_FETCH_CONTACT_BACKGROUND
       
    56 const TInt KMaxIdAtTheTime = 2;
       
    57 #else
       
    58 const TInt KMaxIdAtTheTime = 20;
       
    59 #endif //IMPS_FETCH_CONTACT_BACKGROUND
       
    60 
       
    61 _LIT( KPanicAttribute, "WVUIPresenceVariation attribute" );
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CAPresenceUtils::DecodeOnlineState
       
    65 // (other items were commented in a header).
       
    66 // -----------------------------------------------------------------------------
       
    67 //
       
    68 MCAPresence::TPresenceStatus CAPresenceUtils::DecodeOnlineState(
       
    69     const RPointerArray<CCAState>& aStates,
       
    70     const RPointerArray<MPEngPresenceAttrModel2>& aAttributes )
       
    71     {
       
    72     MCAPresence::TPresenceStatus status( MCAPresence::EUnknown );
       
    73 
       
    74     TInt stateCount( aStates.Count() );
       
    75     TBool stateFound( EFalse );
       
    76     for ( TInt stateIndex( 0 ); stateIndex < stateCount && !stateFound; ++stateIndex )
       
    77         {
       
    78         CCAState* state = aStates[stateIndex];
       
    79         TInt stateAttrCount( state->iAttributes.Count() );
       
    80         if ( stateAttrCount == 0 )
       
    81             {
       
    82             // no attributes => default state
       
    83             status = MCAPresence::TPresenceStatus( state->iStateId );
       
    84             }
       
    85         else
       
    86             {
       
    87             // we have a match if:
       
    88             // all attributes defined in state can be found from current
       
    89             // set of attributes with same values as in state.
       
    90 
       
    91             stateFound = ETrue;
       
    92             for ( TInt stateAttrIndex( 0 ); stateAttrIndex < stateAttrCount  &&
       
    93                   stateFound; ++stateAttrIndex )
       
    94                 {
       
    95                 TCAAttribute& stateAttr = state->iAttributes[stateAttrIndex];
       
    96 
       
    97                 const MPEngPresenceAttrModel2* attr =
       
    98                     FindAttr( stateAttr.iAttribute, aAttributes );
       
    99                 if ( attr )
       
   100                     {
       
   101                     // attribute found
       
   102                     if ( attr->DataInt( stateAttr.iField, stateAttr.iGroup )
       
   103                          != stateAttr.iData ||
       
   104                          attr->Qualifier()
       
   105                          != stateAttr.iQualifier )
       
   106                         {
       
   107                         // but different value or qualifier => doesn't match
       
   108                         stateFound = EFalse;
       
   109                         }
       
   110                     }
       
   111                 else
       
   112                     {
       
   113                     // not found at all => doesn't match
       
   114                     stateFound = EFalse;
       
   115                     }
       
   116                 }
       
   117 
       
   118             if ( stateFound )
       
   119                 {
       
   120                 status = MCAPresence::TPresenceStatus( state->iStateId );
       
   121                 }
       
   122             }
       
   123         }
       
   124 
       
   125     CHAT_DP_TXT( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
       
   126     return status;
       
   127     }
       
   128 
       
   129 // -----------------------------------------------------------------------------
       
   130 // CAPresenceUtils::PopulateAttributes
       
   131 // (other items were commented in a header).
       
   132 // -----------------------------------------------------------------------------
       
   133 //
       
   134 void CAPresenceUtils::PopulateAttributesL( const MPEngPresenceAttrModel2& aModel,
       
   135                                            RPointerArray<MPEngPresenceAttrModel2>& aArray,
       
   136                                            TStorageManagerGlobals::TClientType& aClientType,
       
   137                                            TPtrC& aAlias,
       
   138                                            TPtrC& aStatusText )
       
   139     {
       
   140     switch ( aModel.Type() )
       
   141         {
       
   142         case KUidPrAttrClientInfo:
       
   143             {
       
   144             aClientType = TStorageManagerGlobals::EUnknownClient;
       
   145             if ( aModel.Qualifier() )
       
   146                 {
       
   147                 switch ( aModel.DataInt( EPEngCliInfDeviceType ) )
       
   148                     {
       
   149                     case EPEngCliDevTypeMobilePhone:
       
   150                         {
       
   151                         aClientType = TStorageManagerGlobals::EMobile;
       
   152                         break;
       
   153                         }
       
   154                     case EPEngCliDevTypeComputer:
       
   155                         {
       
   156                         aClientType = TStorageManagerGlobals::EPC;
       
   157                         break;
       
   158                         }
       
   159                     default:
       
   160                         {
       
   161                         // nothing to do here
       
   162                         }
       
   163                     }
       
   164                 }
       
   165             break;
       
   166             }
       
   167         case KUidPrAttrAlias:
       
   168             {
       
   169             if ( aAlias.Ptr() )
       
   170                 {
       
   171                 // have valid descriptor to where this points,
       
   172                 // otherwise it's unused by the IM Open Conversation
       
   173                 // routines
       
   174                 aAlias.Set( aModel.DataDesC16( EPEngAlias ) );
       
   175                 }
       
   176             break;
       
   177             }
       
   178         case KUidPrAttrStatusText:
       
   179             {
       
   180             if ( ! aStatusText.Ptr() )
       
   181                 {
       
   182                 // have valid descriptor to where this points,
       
   183                 // otherwise it's unused by the IM Open Conversation
       
   184                 // routines
       
   185                 aStatusText.Set( aModel.DataDesC16( EPEngStatusText ) );
       
   186                 }
       
   187             break;
       
   188             }
       
   189         default:
       
   190             {
       
   191             aArray.AppendL( &aModel );
       
   192             break;
       
   193             }
       
   194         }
       
   195     }
       
   196 
       
   197 // -----------------------------------------------------------------------------
       
   198 // CAPresenceUtils::GenerateFriendsArrayLC
       
   199 // (other items were commented in a header).
       
   200 // -----------------------------------------------------------------------------
       
   201 //
       
   202 CPtrCArray* CAPresenceUtils::GenerateFriendsArrayLC(
       
   203     MCAStoredContacts* aContactStorage )
       
   204     {
       
   205     TInt granularity( aContactStorage->ContactCount() );
       
   206     if ( granularity == 0 )
       
   207         {
       
   208         granularity = 1;
       
   209         }
       
   210 
       
   211     CPtrCArray* contactsArray =
       
   212         new ( ELeave ) CPtrCArray( granularity );
       
   213     CleanupStack::PushL( contactsArray );
       
   214 
       
   215     TInt listCount( aContactStorage->ListCount() );
       
   216     TKeyArrayFix cmpKey( 0, ECmpCollated );
       
   217     for ( TInt a( 0 ); a < listCount; ++a )
       
   218         {
       
   219         MCAContactList& contactList = aContactStorage->ListAt( a );
       
   220         TInt contactCount( contactList.Count() );
       
   221         for ( TInt b( 0 ); b < contactCount; ++b )
       
   222             {
       
   223             TPtrC userId( contactList[ b ].UserId() );
       
   224             TInt pos( KErrNotFound );
       
   225             if ( userId.Length() > 0 )
       
   226                 {
       
   227                 // user id exists
       
   228                 if ( contactsArray->FindIsq( userId, cmpKey, pos ) != 0 )
       
   229                     {
       
   230                     // user id not found already from the list, so let's add it
       
   231                     contactsArray->InsertIsqL( userId, cmpKey );
       
   232                     }
       
   233                 }
       
   234             }
       
   235         }
       
   236     return contactsArray;
       
   237     }
       
   238 
       
   239 // -----------------------------------------------------------------------------
       
   240 // CAPresenceUtils::PushModelArrayL
       
   241 // (other items were commented in a header).
       
   242 // -----------------------------------------------------------------------------
       
   243 //
       
   244 void CAPresenceUtils::PushModelArrayL(
       
   245     RPointerArray<MPEngPresenceAttrModel2>& aArray, TBool aOwnsItems )
       
   246     {
       
   247     if ( aOwnsItems )
       
   248         {
       
   249         CleanupStack::PushL( TCleanupItem( DestroyCloseModelArray, &aArray ) );
       
   250         }
       
   251     else
       
   252         {
       
   253         CleanupStack::PushL( TCleanupItem( CloseModelArray, &aArray ) );
       
   254         }
       
   255     }
       
   256 
       
   257 // -----------------------------------------------------------------------------
       
   258 // CAPresenceUtils::DecodeAttrModelsL
       
   259 // (other items were commented in a header).
       
   260 // -----------------------------------------------------------------------------
       
   261 //
       
   262 TBool CAPresenceUtils::DecodeAttrModelsL( struct TDecodeAttrParams& aParams )
       
   263     {
       
   264     CHAT_DP_TXT( "CAPresenceUtils::DecodeAttrModelsL  Enter" );
       
   265     // unpack the structure for easier access
       
   266     RPointerArray<CCAState>* states = aParams.iPresenceStates;
       
   267     RPointerArray< MPEngPresenceAttrModel2 >& array = aParams.iArray;
       
   268     MCAStoredContacts* contactStorage = aParams.iContactStorage;
       
   269     MCAWatcherObserver* watcherObserver = aParams.iWatcherObserver;
       
   270     CDesCArray* stateOnline = aParams.iStateOnline;
       
   271     CDesCArray* stateOffline = aParams.iStateOffline;
       
   272     CDesCArray* stateUnknown = aParams.iStateUnknown;
       
   273     TInt& entryIndex = aParams.iEntryIndex;
       
   274 
       
   275     TBool done( EFalse ); // flag for loop termination
       
   276     TBool updateUserData( EFalse );
       
   277 
       
   278     MPEngPresenceAttrModel2* model = NULL;
       
   279     RPointerArray<MPEngPresenceAttrModel2> attributes;
       
   280     CAPresenceUtils::PushModelArrayL( attributes, EFalse );
       
   281 
       
   282     // alias support preparations
       
   283     TPtrC aliasPtr( NULL, 0 );
       
   284     HBufC* dummy = NULL;
       
   285 
       
   286     if ( aParams.iServerPrefers.iAliasUsed )
       
   287         {
       
   288         // have alias support
       
   289         // alias ptr must point to non-NULL
       
   290         dummy = HBufC::NewL( 1 );
       
   291         CleanupStack::PushL( dummy );
       
   292         aliasPtr.Set( dummy->Des() );
       
   293         }
       
   294     else
       
   295         {
       
   296         // no alias support
       
   297         aliasPtr.Set( NULL, 0 );
       
   298         }
       
   299     TPtrC statusText( NULL, 0 );
       
   300 
       
   301     TStorageManagerGlobals::TPresenceStatus newPresenceStatus =
       
   302         TStorageManagerGlobals::EUnknown;
       
   303     TStorageManagerGlobals::TPresenceStatus oldPresenceStatus =
       
   304         TStorageManagerGlobals::EUnknown;
       
   305     TStorageManagerGlobals::TClientType clientType =
       
   306         TStorageManagerGlobals::EUnknownClient;
       
   307 
       
   308     TInt attrCount( array.Count() );
       
   309     const TDesC* lastID = NULL;
       
   310 
       
   311     CHAT_DP( D_CHAT_LIT( "DecodeAttrModelsL for %d models" ), attrCount );
       
   312 
       
   313     // Loop through all attributes received
       
   314     TInt idCount( 0 );
       
   315     do
       
   316         {
       
   317         updateUserData = EFalse;
       
   318 
       
   319         if ( entryIndex < attrCount )
       
   320             {
       
   321             model = array[entryIndex];
       
   322 
       
   323             // Create initial userID or
       
   324             // Check if all attributes concerning this user has been processed
       
   325             if ( !lastID )
       
   326                 {
       
   327                 lastID = &model->PresenceID();
       
   328                 }
       
   329             else if ( model->PresenceID() != *lastID )
       
   330                 {
       
   331                 ++idCount;
       
   332                 updateUserData = ETrue;
       
   333                 }
       
   334             }
       
   335         else
       
   336             {
       
   337             if ( attrCount > 0 )
       
   338                 {
       
   339                 updateUserData = ETrue;
       
   340                 }
       
   341             done = ETrue;
       
   342             }
       
   343 
       
   344         // If all attributes concerning certain user have been collected,
       
   345         // then we can update local presence information concerning that user
       
   346         if ( updateUserData )
       
   347             {
       
   348             newPresenceStatus = MapPresenceStateId(
       
   349                                     DecodeOnlineState( *states, attributes ) );
       
   350 
       
   351             CAPresenceUtils::FillArraysL( *lastID, newPresenceStatus,
       
   352                                           stateOnline, stateOffline,
       
   353                                           stateUnknown );
       
   354             if ( contactStorage )
       
   355                 {
       
   356                 MCAStoredContact* updatedContact = contactStorage->UpdatePresenceL(
       
   357                                                        *lastID, newPresenceStatus,
       
   358                                                        clientType, aliasPtr,
       
   359                                                        statusText,
       
   360                                                        oldPresenceStatus );
       
   361 
       
   362                 if ( updatedContact )
       
   363                     {
       
   364                     if ( updatedContact->IsWatched()
       
   365                          && watcherObserver
       
   366                          && ( newPresenceStatus != TStorageManagerGlobals::EUnknown )
       
   367                          && !( newPresenceStatus == TStorageManagerGlobals::EOffline
       
   368                                && oldPresenceStatus == TStorageManagerGlobals::EUnknown )
       
   369                        )
       
   370                         {
       
   371                         watcherObserver->HandleWatcherEvent( updatedContact );
       
   372                         }
       
   373                     }
       
   374                 }
       
   375 
       
   376             // reset attributes
       
   377             attributes.Reset();
       
   378             clientType = TStorageManagerGlobals::EUnknownClient;
       
   379 
       
   380             if ( aParams.iServerPrefers.iAliasUsed )
       
   381                 {
       
   382                 // have alias support
       
   383                 // alias ptr must point to non-NULL
       
   384                 aliasPtr.Set( dummy->Des() );
       
   385                 }
       
   386             statusText.Set( NULL, 0 );
       
   387 
       
   388             }
       
   389 
       
   390         if ( !done && idCount < KMaxIdAtTheTime )
       
   391             {
       
   392             lastID = &model->PresenceID();
       
   393             CAPresenceUtils::PopulateAttributesL( *model,
       
   394                                                   attributes,
       
   395                                                   clientType,
       
   396                                                   aliasPtr,
       
   397                                                   statusText );
       
   398             }
       
   399 
       
   400         ++entryIndex;
       
   401         } while ( !done && idCount < KMaxIdAtTheTime );
       
   402 
       
   403 
       
   404     --entryIndex;
       
   405 
       
   406     if ( aParams.iServerPrefers.iAliasUsed )
       
   407         {
       
   408         CleanupStack::PopAndDestroy( dummy );
       
   409         }
       
   410 
       
   411     CleanupStack::PopAndDestroy(); // attributes.Close()
       
   412     CHAT_DP( D_CHAT_LIT( "CAPresenceUtils::DecodeAttrModelsL  Done-:%d" ), done );
       
   413     return !done;
       
   414     }
       
   415 
       
   416 // -----------------------------------------------------------------------------
       
   417 // CAPresenceUtils::HandleListErrorsL
       
   418 // (other items were commented in a header).
       
   419 // -----------------------------------------------------------------------------
       
   420 //
       
   421 void CAPresenceUtils::HandleListErrorsL( TInt aError )
       
   422     {
       
   423     CHAT_DP( D_CHAT_LIT( "CCAPEngListManager::HandleListErrorsL checking \
       
   424 	                      error %d" ), aError );
       
   425 
       
   426     if ( aError != KErrNone && aError != KErrNotFound
       
   427          && aError != KErrAlreadyExists )
       
   428         {
       
   429         CHAT_DP_TXT( "Error can not be ignored, leaving..." );
       
   430         User::Leave( aError );
       
   431         }
       
   432     }
       
   433 
       
   434 // -----------------------------------------------------------------------------
       
   435 // CAPresenceUtils::CompareAttrModelArray
       
   436 // (other items were commented in a header).
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 TInt CAPresenceUtils::CompareAttrModelArray(
       
   440     const MPEngPresenceAttrModel2& aFirst,
       
   441     const MPEngPresenceAttrModel2& aSecond )
       
   442     {
       
   443     return aFirst.PresenceID().CompareC( aSecond.PresenceID(), KCollationLevel,
       
   444                                          NULL );
       
   445     }
       
   446 
       
   447 // -----------------------------------------------------------------------------
       
   448 // CAPresenceUtils::CloseModelArray
       
   449 // (other items were commented in a header).
       
   450 // -----------------------------------------------------------------------------
       
   451 //
       
   452 void CAPresenceUtils::CloseModelArray( TAny* aObject )
       
   453     {
       
   454     reinterpret_cast<RPointerArray<MPEngPresenceAttrModel2>*>( aObject )->
       
   455     Close();
       
   456     }
       
   457 
       
   458 // -----------------------------------------------------------------------------
       
   459 // CAPresenceUtils::DestroyCloseModelArray
       
   460 // (other items were commented in a header).
       
   461 // -----------------------------------------------------------------------------
       
   462 //
       
   463 void CAPresenceUtils::DestroyCloseModelArray( TAny* aObject )
       
   464     {
       
   465     reinterpret_cast<RPointerArray<MPEngPresenceAttrModel2>*>( aObject )->
       
   466     ResetAndDestroy();
       
   467     }
       
   468 
       
   469 // -----------------------------------------------------------------------------
       
   470 // CAPresenceUtils::FillArraysL
       
   471 // (other items were commented in a header).
       
   472 // -----------------------------------------------------------------------------
       
   473 //
       
   474 void CAPresenceUtils::FillArraysL(
       
   475     const TDesC& aUserId,
       
   476     TStorageManagerGlobals::TPresenceStatus aOnlineStatus,
       
   477     CDesCArray *aStateOnline,
       
   478     CDesCArray *aStateOffline,
       
   479     CDesCArray *aStateUnknown )
       
   480     {
       
   481     if ( aUserId == KNullDesC )
       
   482         {
       
   483         // if userID == KNullDesC then this is probably our own presence notify
       
   484         // no need to do anything here
       
   485         return;
       
   486         }
       
   487 
       
   488     switch ( aOnlineStatus )
       
   489         {
       
   490         case TStorageManagerGlobals::EOnline:
       
   491         case TStorageManagerGlobals::EAway:
       
   492         case TStorageManagerGlobals::EBusy: // flow through
       
   493             {
       
   494             if ( aStateOnline )
       
   495                 {
       
   496                 aStateOnline->AppendL( aUserId );
       
   497                 }
       
   498             break;
       
   499             }
       
   500         case TStorageManagerGlobals::EOffline:
       
   501             {
       
   502             if ( aStateOffline )
       
   503                 {
       
   504                 aStateOffline->AppendL( aUserId );
       
   505                 }
       
   506             break;
       
   507             }
       
   508         case TStorageManagerGlobals::EUnknown:
       
   509             {
       
   510             if ( aStateUnknown )
       
   511                 {
       
   512                 aStateUnknown->AppendL( aUserId );
       
   513                 }
       
   514             break;
       
   515             }
       
   516         default:
       
   517             {
       
   518             // Unknown state, ignore
       
   519             break;
       
   520             }
       
   521         }
       
   522     }
       
   523 
       
   524 // -----------------------------------------------------------------------------
       
   525 // CAPresenceUtils::HandleTransactionStatusL
       
   526 // (other items were commented in a header).
       
   527 // -----------------------------------------------------------------------------
       
   528 //
       
   529 void CAPresenceUtils::HandleTransactionStatusL( MPEngTransactionStatus2&
       
   530                                                 aStatus, CCAPresenceErrors& aErrorContainer )
       
   531     {
       
   532     CHAT_DP_TXT( "CAPresenceUtils::HandleTransactionStatusL" );
       
   533 
       
   534     // Reset the container
       
   535     aErrorContainer.Reset();
       
   536     aErrorContainer.SetError( CAPresenceUtils::MapErrorPECtoCSP(
       
   537                                   aStatus.Status() ) );
       
   538 
       
   539     // If partially successful, then fill the local information
       
   540     if ( aErrorContainer.Error() == ECSPPartiallySuccessful )
       
   541         {
       
   542         CHAT_DP_TXT( "CAPresenceUtils::HandleTransactionStatusL, received \
       
   543                       ECSPPartiallySuccessful" );
       
   544         const MPEngDetailedResultEntry2* detailed = NULL;
       
   545         TPtrC data;
       
   546 
       
   547         TInt count( aStatus.DetailedResultCount() );
       
   548         for ( TInt i( 0 ); i < count; ++i )
       
   549             {
       
   550             detailed = &aStatus.DetailedResult( i );
       
   551             detailed->GetDetailedDesc( data, EPEngDTPresenceID );
       
   552             CCAPresenceError* error =
       
   553                 CCAPresenceError::NewLC( CAPresenceUtils::MapErrorPECtoCSP(
       
   554                                              detailed->Error() ), data );
       
   555             CHAT_DP( D_CHAT_LIT( "Detailed result (%d): %d: %S" ), i,
       
   556                      error->ErrorCode(), &data );
       
   557 
       
   558             // Ownership is passed to error container
       
   559             aErrorContainer.AddDetailedErrorL( error );
       
   560             CleanupStack::Pop( error );
       
   561             }
       
   562         }
       
   563     }
       
   564 
       
   565 // -----------------------------------------------------------------------------
       
   566 // CAPresenceUtils::MapErrorPECtoCSP
       
   567 // (other items were commented in a header).
       
   568 // -----------------------------------------------------------------------------
       
   569 //
       
   570 TInt CAPresenceUtils::MapErrorPECtoCSP( TInt aError )
       
   571     {
       
   572     TInt error( aError );
       
   573 
       
   574     // Map everything between KPEngErrorWVServerResponseBase and KPEngErrorBase
       
   575     // to Imps_ERROR_BASE
       
   576     if ( aError < KPEngErrorWVServerResponseBase &&
       
   577          aError > KPEngErrorBase )
       
   578         {
       
   579         error = aError - KPEngErrorWVServerResponseBase + Imps_ERROR_BASE;
       
   580         }
       
   581 
       
   582     return error;
       
   583     }
       
   584 
       
   585 // -----------------------------------------------------------------------------
       
   586 // CAPresenceUtils::AppendContactsL
       
   587 // (other items were commented in a header).
       
   588 // -----------------------------------------------------------------------------
       
   589 //
       
   590 TBool CAPresenceUtils::AppendContactsL( MPEngContactList2* aContactList,
       
   591                                         CDesCArray* aWVIds,
       
   592                                         CDesCArray* aNicknames,
       
   593                                         MCAStoredContacts* aContactStorage,
       
   594                                         TInt& aEntryIndex,
       
   595                                         MCAContactList& aCaContactList,
       
   596                                         MCAPresenceUpdater& aPresenceUpdater )
       
   597     {
       
   598     // Fill arrays
       
   599     TInt idCount( 0 );
       
   600     TInt count( aContactList->Count() );
       
   601     if ( aEntryIndex >= count )
       
   602         {
       
   603         // list has been changed, possibly we ran out of memory
       
   604         aEntryIndex = count - 1;
       
   605         }
       
   606 
       
   607     if ( aWVIds && aNicknames )
       
   608         {
       
   609         while ( ( idCount < KMaxIdAtTheTime ) && ( aEntryIndex >= 0 ) )
       
   610             {
       
   611             MPEngContactItem& contact = aContactList->ContactItem( aEntryIndex );
       
   612             TPtrC id = contact.Id();
       
   613             TPtrC nick( contact.NickName() );
       
   614             // append to lists
       
   615             aWVIds->AppendL( id );
       
   616             aNicknames->AppendL( nick );
       
   617             ++idCount;
       
   618             --aEntryIndex;
       
   619             }
       
   620         }
       
   621     else
       
   622         {
       
   623         RPointerArray<MPEngPresenceAttrModel2> attrModels;
       
   624         CAPresenceUtils::PushModelArrayL( attrModels, ETrue );
       
   625         RPointerArray<MPEngPresenceAttrModel2> onlineStateModels;
       
   626         CAPresenceUtils::PushModelArrayL( onlineStateModels, EFalse );
       
   627 
       
   628         TPtrC aliasPtr( NULL, 0 );
       
   629         TPtrC statusText( NULL, 0 );
       
   630         TStorageManagerGlobals::TClientType clientType =
       
   631             TStorageManagerGlobals::EUnknownClient;
       
   632         const RPointerArray<CCAState>& presenceStates = aPresenceUpdater.PresenceStates();
       
   633         TStorageManagerGlobals::TPresenceStatus presenceStatus =
       
   634             TStorageManagerGlobals::EUnknown;
       
   635 
       
   636         while ( ( idCount < KMaxIdAtTheTime ) && ( aEntryIndex >= 0 ) )
       
   637             {
       
   638             MPEngContactItem& contact = aContactList->ContactItem( aEntryIndex );
       
   639             TPtrC uderId = contact.Id();
       
   640             TPtrC nick( contact.NickName() );
       
   641 
       
   642             // fetch attribute for this contact and add it all at once
       
   643             aPresenceUpdater.ExtractAttributeModelsForUserL( uderId, attrModels );
       
   644             // populate attributes
       
   645             TInt attrCount( attrModels.Count() );
       
   646             for ( TInt x( 0 ) ; x < attrCount ; ++x )
       
   647                 {
       
   648                 CAPresenceUtils::PopulateAttributesL( *attrModels[x],
       
   649                                                       onlineStateModels,
       
   650                                                       clientType,
       
   651                                                       aliasPtr,
       
   652                                                       statusText );
       
   653                 }
       
   654 
       
   655             presenceStatus = MapPresenceStateId(
       
   656                                  DecodeOnlineState( presenceStates, onlineStateModels ) );
       
   657 
       
   658 
       
   659             // update directly to storage
       
   660             aContactStorage->CreateContactL( aCaContactList,
       
   661                                              nick,
       
   662                                              uderId,
       
   663                                              presenceStatus,
       
   664                                              clientType,
       
   665                                              aliasPtr,
       
   666                                              statusText );
       
   667 
       
   668             // reset attributes
       
   669             onlineStateModels.Reset();
       
   670             attrModels.ResetAndDestroy();
       
   671 
       
   672             clientType = TStorageManagerGlobals::EUnknownClient;
       
   673             statusText.Set( NULL, 0 );
       
   674             aliasPtr.Set( KNullDesC );
       
   675 
       
   676             ++idCount;
       
   677             --aEntryIndex;
       
   678             }
       
   679         CleanupStack::PopAndDestroy( 2 ); // attrModels, onlineStateModels
       
   680         }
       
   681 
       
   682     // if aEntryIndex is -1, then we are done
       
   683     return ( aEntryIndex != -1 );
       
   684     }
       
   685 
       
   686 
       
   687 // -----------------------------------------------------------------------------
       
   688 // CAPresenceUtils::ReadAttributeL
       
   689 // (other items were commented in a header).
       
   690 // -----------------------------------------------------------------------------
       
   691 //
       
   692 TCAAttribute CAPresenceUtils::ReadAttributeL( TResourceReader& aReader )
       
   693     {
       
   694     TInt attribute( aReader.ReadInt16() );
       
   695     TInt qualifier( aReader.ReadInt16() );
       
   696     TInt value( aReader.ReadInt16() );
       
   697 
       
   698     TCAAttribute attr;
       
   699     attr.iQualifier = ( qualifier == EIMQualifierTrue );
       
   700     attr.iData = KErrNotFound;
       
   701     attr.iField = KErrNotFound;
       
   702     attr.iGroup = KPEngDefaultAttrValueGroup;
       
   703 
       
   704     switch ( attribute )
       
   705         {
       
   706         case EIMOnlineAttr:
       
   707             {
       
   708             attr.iAttribute = KUidPrAttrOnlineStatus;
       
   709             attr.iField = EPEngOnlineStatus;
       
   710             switch ( value )
       
   711                 {
       
   712                 case EIMOnlineNoChange:
       
   713                     {
       
   714                     // by default, value isn't used
       
   715                     break;
       
   716                     }
       
   717                 case EIMOnlineTrue:
       
   718                     {
       
   719                     attr.iData = EPEngOnlineStatusOnline;
       
   720                     break;
       
   721                     }
       
   722                 case EIMOnlineFalse:
       
   723                     {
       
   724                     attr.iData = EPEngOnlineStatusOffline;
       
   725                     break;
       
   726                     }
       
   727                 default:
       
   728                     {
       
   729                     User::Panic( KPanicAttribute, KErrArgument );
       
   730                     }
       
   731                 }
       
   732             break;
       
   733             }
       
   734         case EIMUserAvailabilityAttr:
       
   735             {
       
   736             attr.iAttribute = KUidPrAttrUserAvailability;
       
   737             attr.iField = EPEngUsrAvailability;
       
   738             switch ( value )
       
   739                 {
       
   740                 case EIMUserAvailabilityNoChange:
       
   741                     {
       
   742                     // by default, value isn't used
       
   743                     break;
       
   744                     }
       
   745                 case EIMUserAvailabilityNotAvailable:
       
   746                     {
       
   747                     attr.iData = EPEngUsrAvailabilityOffline;
       
   748                     break;
       
   749                     }
       
   750                 case EIMUserAvailabilityDiscreet:
       
   751                     {
       
   752                     attr.iData = EPEngUsrAvailabilityDiscreet;
       
   753                     break;
       
   754                     }
       
   755                 case EIMUserAvailabilityAvailable:
       
   756                     {
       
   757                     attr.iData = EPEngUsrAvailabilityOnline;
       
   758                     break;
       
   759                     }
       
   760                 default:
       
   761                     {
       
   762                     User::Panic( KPanicAttribute, KErrArgument );
       
   763                     }
       
   764                 }
       
   765             break;
       
   766             }
       
   767         case EIMCommCapAttr:
       
   768             {
       
   769             attr.iAttribute = KUidPrAttrCommCap;
       
   770             attr.iField = EPEngCommCapStatus;
       
   771             attr.iGroup = EPEngCommCapIMClient;
       
   772             switch ( value )
       
   773                 {
       
   774                 case EIMCommCapNoChange:
       
   775                     {
       
   776                     // by default, value isn't used
       
   777                     break;
       
   778                     }
       
   779                 case EIMCommCapClosed:
       
   780                     {
       
   781                     attr.iData = EPEngCommCapStatusClosed;
       
   782                     break;
       
   783                     }
       
   784                 case EIMCommCapOpen:
       
   785                     {
       
   786                     attr.iData = EPEngCommCapStatusOpen;
       
   787                     break;
       
   788                     }
       
   789                 default:
       
   790                     {
       
   791                     User::Panic( KPanicAttribute, KErrArgument );
       
   792                     }
       
   793                 }
       
   794             break;
       
   795             }
       
   796         case EIMStatusTextAttr:
       
   797             {
       
   798             attr.iAttribute = KUidPrAttrStatusText;
       
   799             switch ( value )
       
   800                 {
       
   801                 case EIMStatusTextNoChange:
       
   802                     {
       
   803                     // by default, value isn't used
       
   804                     break;
       
   805                     }
       
   806                 default:
       
   807                     {
       
   808                     User::Panic( KPanicAttribute, KErrArgument );
       
   809                     }
       
   810                 }
       
   811             break;
       
   812             }
       
   813         default:
       
   814             {
       
   815             User::Panic( KPanicAttribute, KErrArgument );
       
   816             }
       
   817         }
       
   818     return attr;
       
   819     }
       
   820 
       
   821 // -----------------------------------------------------------------------------
       
   822 // CAPresenceUtils::MapStateId
       
   823 // (other items were commented in a header).
       
   824 // -----------------------------------------------------------------------------
       
   825 //
       
   826 TInt CAPresenceUtils::MapStateId( TInt aResourceStateId )
       
   827     {
       
   828     MCAPresence::TPresenceStatus ret( MCAPresence::EUnknown );
       
   829     switch ( aResourceStateId )
       
   830         {
       
   831         case EIMStateAvailable:
       
   832             {
       
   833             ret = MCAPresence::EOnline;
       
   834             break;
       
   835             }
       
   836         case EIMStateAway:
       
   837             {
       
   838             ret = MCAPresence::EAway;
       
   839             break;
       
   840             }
       
   841         case EIMStateBusy:
       
   842             {
       
   843             ret = MCAPresence::EBusy;
       
   844             break;
       
   845             }
       
   846         case EIMStateInvisible: // flowthrough at the moment
       
   847         case EIMStateOffline:
       
   848             {
       
   849             ret = MCAPresence::EOffline;
       
   850             break;
       
   851             }
       
   852         default:
       
   853             {
       
   854             User::Panic( KPanicAttribute, KErrArgument );
       
   855             }
       
   856         }
       
   857     return ret;
       
   858     }
       
   859 
       
   860 // -----------------------------------------------------------------------------
       
   861 // CAPresenceUtils::MapPresenceStateId
       
   862 // (other items were commented in a header).
       
   863 // -----------------------------------------------------------------------------
       
   864 //
       
   865 TStorageManagerGlobals::TPresenceStatus CAPresenceUtils::MapPresenceStateId(
       
   866     MCAPresence::TPresenceStatus aPresenceStateId )
       
   867     {
       
   868     TStorageManagerGlobals::TPresenceStatus ret( TStorageManagerGlobals::EUnknown );
       
   869     switch ( aPresenceStateId )
       
   870         {
       
   871         case MCAPresence::EOnline:
       
   872             {
       
   873             ret = TStorageManagerGlobals::EOnline;
       
   874             break;
       
   875             }
       
   876         case MCAPresence::EOffline:
       
   877             {
       
   878             ret = TStorageManagerGlobals::EOffline;
       
   879             break;
       
   880             }
       
   881         case MCAPresence::EAway:
       
   882             {
       
   883             ret = TStorageManagerGlobals::EAway;
       
   884             break;
       
   885             }
       
   886         case MCAPresence::EBusy:
       
   887             {
       
   888             ret = TStorageManagerGlobals::EBusy;
       
   889             break;
       
   890             }
       
   891         default:
       
   892             {
       
   893             // nothing to do
       
   894             }
       
   895         }
       
   896     return ret;
       
   897     }
       
   898 
       
   899 // -----------------------------------------------------------------------------
       
   900 // CAPresenceUtils::ReadStatesFromResourceL
       
   901 // (other items were commented in a header).
       
   902 // -----------------------------------------------------------------------------
       
   903 //
       
   904 void CAPresenceUtils::ReadStatesFromResourceL( TInt aResourceId,
       
   905                                                RPointerArray<CCAState>& aStates )
       
   906     {
       
   907     TResourceReader reader;
       
   908     CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
       
   909 
       
   910     // reset array
       
   911     aStates.ResetAndDestroy();
       
   912 
       
   913     // read states
       
   914     TInt stateCount( reader.ReadInt16() );
       
   915     for ( TInt stateIndex( 0 ); stateIndex < stateCount; ++stateIndex )
       
   916         {
       
   917         // read state id and create state for it
       
   918         TInt stateId( MapStateId( reader.ReadInt16() ) );
       
   919 
       
   920         CCAState* state = new( ELeave )CCAState( stateId );
       
   921         CleanupStack::PushL( state );
       
   922 
       
   923         // and attributes
       
   924         TInt attributeCount( reader.ReadInt16() );
       
   925         for ( TInt i( 0 ); i < attributeCount; ++i )
       
   926             {
       
   927             state->iAttributes.AppendL( ReadAttributeL( reader ) );
       
   928             }
       
   929 
       
   930         // finished
       
   931         aStates.AppendL( state );
       
   932         CleanupStack::Pop( state );
       
   933         }
       
   934 
       
   935     CleanupStack::PopAndDestroy(); // reader
       
   936     }
       
   937 
       
   938 // -----------------------------------------------------------------------------
       
   939 // CAPresenceUtils::FindState
       
   940 // (other items were commented in a header).
       
   941 // -----------------------------------------------------------------------------
       
   942 //
       
   943 CCAState* CAPresenceUtils::FindStateL( TInt aState, const RPointerArray<CCAState>& aStates )
       
   944     {
       
   945     CCAState* tmp = new( ELeave )CCAState( aState );
       
   946     CleanupStack::PushL( tmp );
       
   947 
       
   948     CCAState* ret = NULL;
       
   949     TIdentityRelation< CCAState > equals( CAPresenceUtils::EqualStates );
       
   950 
       
   951     TInt index( aStates.Find( tmp, equals ) );
       
   952     if ( index != KErrNotFound )
       
   953         {
       
   954         ret = aStates[index];
       
   955         }
       
   956 
       
   957     CleanupStack::PopAndDestroy( tmp );
       
   958     return ret;
       
   959     }
       
   960 
       
   961 // -----------------------------------------------------------------------------
       
   962 // CAPresenceUtils::FindAttrL
       
   963 // (other items were commented in a header).
       
   964 // -----------------------------------------------------------------------------
       
   965 //
       
   966 const MPEngPresenceAttrModel2* CAPresenceUtils::FindAttr( TInt aType,
       
   967                                                           const RPointerArray<MPEngPresenceAttrModel2>& aArray )
       
   968     {
       
   969     TInt count( aArray.Count() );
       
   970     for ( TInt i( 0 ); i < count; ++i )
       
   971         {
       
   972         const MPEngPresenceAttrModel2* attr = aArray[i];
       
   973         if ( attr->Type() == aType )
       
   974             {
       
   975             return attr;
       
   976             }
       
   977         }
       
   978     return NULL;
       
   979     }
       
   980 
       
   981 // -----------------------------------------------------------------------------
       
   982 // CAPresenceUtils::EqualStates
       
   983 // (other items were commented in a header).
       
   984 // -----------------------------------------------------------------------------
       
   985 //
       
   986 TBool CAPresenceUtils::EqualStates( const CCAState& aState1, const CCAState& aState2 )
       
   987     {
       
   988     return ( aState1.iStateId == aState2.iStateId );
       
   989     }
       
   990 
       
   991 
       
   992 //  End of File