--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuipresence/src/CAPresenceUtils.cpp Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,992 @@
+/*
+* Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Utility class for presence functions
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CAPresenceDefinitions.h"
+#include "CAPresenceUtils.h"
+#include "ChatDebugPrint.h"
+#include "CCAStorageManagerFactory.h"
+#include "MCAStoredContact.h"
+#include "MCAStoredContacts.h"
+#include "MCAWatcherObserver.h"
+#include "CCAPresenceError.h"
+#include "CCAPresenceErrors.h"
+#include "ImpsCSPAllErrors.h"
+#include "CAPresenceConst.h"
+#include "MCAContactList.h"
+#include "TDecodeAttrParams.h"
+#include "SServerPrefers.h"
+#include "MCAPresenceUpdater.h"
+#include "impsbuilddefinitions.h"
+
+#include "WVUIPresenceVariationNG.hrh"
+#include <WVUIPresenceVariationNG.rsg>
+
+#include <PEngWVPresenceAttributes2.h>
+#include <MPEngPresenceAttrModel2.h>
+#include <MPEngContactList2.h>
+#include <MPEngTransactionStatus2.h>
+#include <PEngWVPresenceErrors2.h>
+#include <ImpsErrors.h>
+#include <PEngPresenceEngineErrors2.h>
+#include <MPEngContactItem.h>
+#include <MPEngContactListProperties.h>
+#include <barsread.h> // RResourceReader
+#include <eikenv.h>
+
+// "test character identity and accents, ignore case"
+const TInt KCollationLevel = 1;
+#ifndef IMPS_FETCH_CONTACT_BACKGROUND
+const TInt KMaxIdAtTheTime = 2;
+#else
+const TInt KMaxIdAtTheTime = 20;
+#endif //IMPS_FETCH_CONTACT_BACKGROUND
+
+_LIT( KPanicAttribute, "WVUIPresenceVariation attribute" );
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::DecodeOnlineState
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+MCAPresence::TPresenceStatus CAPresenceUtils::DecodeOnlineState(
+ const RPointerArray<CCAState>& aStates,
+ const RPointerArray<MPEngPresenceAttrModel2>& aAttributes )
+ {
+ MCAPresence::TPresenceStatus status( MCAPresence::EUnknown );
+
+ TInt stateCount( aStates.Count() );
+ TBool stateFound( EFalse );
+ for ( TInt stateIndex( 0 ); stateIndex < stateCount && !stateFound; ++stateIndex )
+ {
+ CCAState* state = aStates[stateIndex];
+ TInt stateAttrCount( state->iAttributes.Count() );
+ if ( stateAttrCount == 0 )
+ {
+ // no attributes => default state
+ status = MCAPresence::TPresenceStatus( state->iStateId );
+ }
+ else
+ {
+ // we have a match if:
+ // all attributes defined in state can be found from current
+ // set of attributes with same values as in state.
+
+ stateFound = ETrue;
+ for ( TInt stateAttrIndex( 0 ); stateAttrIndex < stateAttrCount &&
+ stateFound; ++stateAttrIndex )
+ {
+ TCAAttribute& stateAttr = state->iAttributes[stateAttrIndex];
+
+ const MPEngPresenceAttrModel2* attr =
+ FindAttr( stateAttr.iAttribute, aAttributes );
+ if ( attr )
+ {
+ // attribute found
+ if ( attr->DataInt( stateAttr.iField, stateAttr.iGroup )
+ != stateAttr.iData ||
+ attr->Qualifier()
+ != stateAttr.iQualifier )
+ {
+ // but different value or qualifier => doesn't match
+ stateFound = EFalse;
+ }
+ }
+ else
+ {
+ // not found at all => doesn't match
+ stateFound = EFalse;
+ }
+ }
+
+ if ( stateFound )
+ {
+ status = MCAPresence::TPresenceStatus( state->iStateId );
+ }
+ }
+ }
+
+ CHAT_DP_TXT( "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" );
+ return status;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::PopulateAttributes
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::PopulateAttributesL( const MPEngPresenceAttrModel2& aModel,
+ RPointerArray<MPEngPresenceAttrModel2>& aArray,
+ TStorageManagerGlobals::TClientType& aClientType,
+ TPtrC& aAlias,
+ TPtrC& aStatusText )
+ {
+ switch ( aModel.Type() )
+ {
+ case KUidPrAttrClientInfo:
+ {
+ aClientType = TStorageManagerGlobals::EUnknownClient;
+ if ( aModel.Qualifier() )
+ {
+ switch ( aModel.DataInt( EPEngCliInfDeviceType ) )
+ {
+ case EPEngCliDevTypeMobilePhone:
+ {
+ aClientType = TStorageManagerGlobals::EMobile;
+ break;
+ }
+ case EPEngCliDevTypeComputer:
+ {
+ aClientType = TStorageManagerGlobals::EPC;
+ break;
+ }
+ default:
+ {
+ // nothing to do here
+ }
+ }
+ }
+ break;
+ }
+ case KUidPrAttrAlias:
+ {
+ if ( aAlias.Ptr() )
+ {
+ // have valid descriptor to where this points,
+ // otherwise it's unused by the IM Open Conversation
+ // routines
+ aAlias.Set( aModel.DataDesC16( EPEngAlias ) );
+ }
+ break;
+ }
+ case KUidPrAttrStatusText:
+ {
+ if ( ! aStatusText.Ptr() )
+ {
+ // have valid descriptor to where this points,
+ // otherwise it's unused by the IM Open Conversation
+ // routines
+ aStatusText.Set( aModel.DataDesC16( EPEngStatusText ) );
+ }
+ break;
+ }
+ default:
+ {
+ aArray.AppendL( &aModel );
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::GenerateFriendsArrayLC
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CPtrCArray* CAPresenceUtils::GenerateFriendsArrayLC(
+ MCAStoredContacts* aContactStorage )
+ {
+ TInt granularity( aContactStorage->ContactCount() );
+ if ( granularity == 0 )
+ {
+ granularity = 1;
+ }
+
+ CPtrCArray* contactsArray =
+ new ( ELeave ) CPtrCArray( granularity );
+ CleanupStack::PushL( contactsArray );
+
+ TInt listCount( aContactStorage->ListCount() );
+ TKeyArrayFix cmpKey( 0, ECmpCollated );
+ for ( TInt a( 0 ); a < listCount; ++a )
+ {
+ MCAContactList& contactList = aContactStorage->ListAt( a );
+ TInt contactCount( contactList.Count() );
+ for ( TInt b( 0 ); b < contactCount; ++b )
+ {
+ TPtrC userId( contactList[ b ].UserId() );
+ TInt pos( KErrNotFound );
+ if ( userId.Length() > 0 )
+ {
+ // user id exists
+ if ( contactsArray->FindIsq( userId, cmpKey, pos ) != 0 )
+ {
+ // user id not found already from the list, so let's add it
+ contactsArray->InsertIsqL( userId, cmpKey );
+ }
+ }
+ }
+ }
+ return contactsArray;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::PushModelArrayL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::PushModelArrayL(
+ RPointerArray<MPEngPresenceAttrModel2>& aArray, TBool aOwnsItems )
+ {
+ if ( aOwnsItems )
+ {
+ CleanupStack::PushL( TCleanupItem( DestroyCloseModelArray, &aArray ) );
+ }
+ else
+ {
+ CleanupStack::PushL( TCleanupItem( CloseModelArray, &aArray ) );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::DecodeAttrModelsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CAPresenceUtils::DecodeAttrModelsL( struct TDecodeAttrParams& aParams )
+ {
+ CHAT_DP_TXT( "CAPresenceUtils::DecodeAttrModelsL Enter" );
+ // unpack the structure for easier access
+ RPointerArray<CCAState>* states = aParams.iPresenceStates;
+ RPointerArray< MPEngPresenceAttrModel2 >& array = aParams.iArray;
+ MCAStoredContacts* contactStorage = aParams.iContactStorage;
+ MCAWatcherObserver* watcherObserver = aParams.iWatcherObserver;
+ CDesCArray* stateOnline = aParams.iStateOnline;
+ CDesCArray* stateOffline = aParams.iStateOffline;
+ CDesCArray* stateUnknown = aParams.iStateUnknown;
+ TInt& entryIndex = aParams.iEntryIndex;
+
+ TBool done( EFalse ); // flag for loop termination
+ TBool updateUserData( EFalse );
+
+ MPEngPresenceAttrModel2* model = NULL;
+ RPointerArray<MPEngPresenceAttrModel2> attributes;
+ CAPresenceUtils::PushModelArrayL( attributes, EFalse );
+
+ // alias support preparations
+ TPtrC aliasPtr( NULL, 0 );
+ HBufC* dummy = NULL;
+
+ if ( aParams.iServerPrefers.iAliasUsed )
+ {
+ // have alias support
+ // alias ptr must point to non-NULL
+ dummy = HBufC::NewL( 1 );
+ CleanupStack::PushL( dummy );
+ aliasPtr.Set( dummy->Des() );
+ }
+ else
+ {
+ // no alias support
+ aliasPtr.Set( NULL, 0 );
+ }
+ TPtrC statusText( NULL, 0 );
+
+ TStorageManagerGlobals::TPresenceStatus newPresenceStatus =
+ TStorageManagerGlobals::EUnknown;
+ TStorageManagerGlobals::TPresenceStatus oldPresenceStatus =
+ TStorageManagerGlobals::EUnknown;
+ TStorageManagerGlobals::TClientType clientType =
+ TStorageManagerGlobals::EUnknownClient;
+
+ TInt attrCount( array.Count() );
+ const TDesC* lastID = NULL;
+
+ CHAT_DP( D_CHAT_LIT( "DecodeAttrModelsL for %d models" ), attrCount );
+
+ // Loop through all attributes received
+ TInt idCount( 0 );
+ do
+ {
+ updateUserData = EFalse;
+
+ if ( entryIndex < attrCount )
+ {
+ model = array[entryIndex];
+
+ // Create initial userID or
+ // Check if all attributes concerning this user has been processed
+ if ( !lastID )
+ {
+ lastID = &model->PresenceID();
+ }
+ else if ( model->PresenceID() != *lastID )
+ {
+ ++idCount;
+ updateUserData = ETrue;
+ }
+ }
+ else
+ {
+ if ( attrCount > 0 )
+ {
+ updateUserData = ETrue;
+ }
+ done = ETrue;
+ }
+
+ // If all attributes concerning certain user have been collected,
+ // then we can update local presence information concerning that user
+ if ( updateUserData )
+ {
+ newPresenceStatus = MapPresenceStateId(
+ DecodeOnlineState( *states, attributes ) );
+
+ CAPresenceUtils::FillArraysL( *lastID, newPresenceStatus,
+ stateOnline, stateOffline,
+ stateUnknown );
+ if ( contactStorage )
+ {
+ MCAStoredContact* updatedContact = contactStorage->UpdatePresenceL(
+ *lastID, newPresenceStatus,
+ clientType, aliasPtr,
+ statusText,
+ oldPresenceStatus );
+
+ if ( updatedContact )
+ {
+ if ( updatedContact->IsWatched()
+ && watcherObserver
+ && ( newPresenceStatus != TStorageManagerGlobals::EUnknown )
+ && !( newPresenceStatus == TStorageManagerGlobals::EOffline
+ && oldPresenceStatus == TStorageManagerGlobals::EUnknown )
+ )
+ {
+ watcherObserver->HandleWatcherEvent( updatedContact );
+ }
+ }
+ }
+
+ // reset attributes
+ attributes.Reset();
+ clientType = TStorageManagerGlobals::EUnknownClient;
+
+ if ( aParams.iServerPrefers.iAliasUsed )
+ {
+ // have alias support
+ // alias ptr must point to non-NULL
+ aliasPtr.Set( dummy->Des() );
+ }
+ statusText.Set( NULL, 0 );
+
+ }
+
+ if ( !done && idCount < KMaxIdAtTheTime )
+ {
+ lastID = &model->PresenceID();
+ CAPresenceUtils::PopulateAttributesL( *model,
+ attributes,
+ clientType,
+ aliasPtr,
+ statusText );
+ }
+
+ ++entryIndex;
+ } while ( !done && idCount < KMaxIdAtTheTime );
+
+
+ --entryIndex;
+
+ if ( aParams.iServerPrefers.iAliasUsed )
+ {
+ CleanupStack::PopAndDestroy( dummy );
+ }
+
+ CleanupStack::PopAndDestroy(); // attributes.Close()
+ CHAT_DP( D_CHAT_LIT( "CAPresenceUtils::DecodeAttrModelsL Done-:%d" ), done );
+ return !done;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::HandleListErrorsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::HandleListErrorsL( TInt aError )
+ {
+ CHAT_DP( D_CHAT_LIT( "CCAPEngListManager::HandleListErrorsL checking \
+ error %d" ), aError );
+
+ if ( aError != KErrNone && aError != KErrNotFound
+ && aError != KErrAlreadyExists )
+ {
+ CHAT_DP_TXT( "Error can not be ignored, leaving..." );
+ User::Leave( aError );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::CompareAttrModelArray
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CAPresenceUtils::CompareAttrModelArray(
+ const MPEngPresenceAttrModel2& aFirst,
+ const MPEngPresenceAttrModel2& aSecond )
+ {
+ return aFirst.PresenceID().CompareC( aSecond.PresenceID(), KCollationLevel,
+ NULL );
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::CloseModelArray
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::CloseModelArray( TAny* aObject )
+ {
+ reinterpret_cast<RPointerArray<MPEngPresenceAttrModel2>*>( aObject )->
+ Close();
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::DestroyCloseModelArray
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::DestroyCloseModelArray( TAny* aObject )
+ {
+ reinterpret_cast<RPointerArray<MPEngPresenceAttrModel2>*>( aObject )->
+ ResetAndDestroy();
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::FillArraysL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::FillArraysL(
+ const TDesC& aUserId,
+ TStorageManagerGlobals::TPresenceStatus aOnlineStatus,
+ CDesCArray *aStateOnline,
+ CDesCArray *aStateOffline,
+ CDesCArray *aStateUnknown )
+ {
+ if ( aUserId == KNullDesC )
+ {
+ // if userID == KNullDesC then this is probably our own presence notify
+ // no need to do anything here
+ return;
+ }
+
+ switch ( aOnlineStatus )
+ {
+ case TStorageManagerGlobals::EOnline:
+ case TStorageManagerGlobals::EAway:
+ case TStorageManagerGlobals::EBusy: // flow through
+ {
+ if ( aStateOnline )
+ {
+ aStateOnline->AppendL( aUserId );
+ }
+ break;
+ }
+ case TStorageManagerGlobals::EOffline:
+ {
+ if ( aStateOffline )
+ {
+ aStateOffline->AppendL( aUserId );
+ }
+ break;
+ }
+ case TStorageManagerGlobals::EUnknown:
+ {
+ if ( aStateUnknown )
+ {
+ aStateUnknown->AppendL( aUserId );
+ }
+ break;
+ }
+ default:
+ {
+ // Unknown state, ignore
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::HandleTransactionStatusL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::HandleTransactionStatusL( MPEngTransactionStatus2&
+ aStatus, CCAPresenceErrors& aErrorContainer )
+ {
+ CHAT_DP_TXT( "CAPresenceUtils::HandleTransactionStatusL" );
+
+ // Reset the container
+ aErrorContainer.Reset();
+ aErrorContainer.SetError( CAPresenceUtils::MapErrorPECtoCSP(
+ aStatus.Status() ) );
+
+ // If partially successful, then fill the local information
+ if ( aErrorContainer.Error() == ECSPPartiallySuccessful )
+ {
+ CHAT_DP_TXT( "CAPresenceUtils::HandleTransactionStatusL, received \
+ ECSPPartiallySuccessful" );
+ const MPEngDetailedResultEntry2* detailed = NULL;
+ TPtrC data;
+
+ TInt count( aStatus.DetailedResultCount() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ detailed = &aStatus.DetailedResult( i );
+ detailed->GetDetailedDesc( data, EPEngDTPresenceID );
+ CCAPresenceError* error =
+ CCAPresenceError::NewLC( CAPresenceUtils::MapErrorPECtoCSP(
+ detailed->Error() ), data );
+ CHAT_DP( D_CHAT_LIT( "Detailed result (%d): %d: %S" ), i,
+ error->ErrorCode(), &data );
+
+ // Ownership is passed to error container
+ aErrorContainer.AddDetailedErrorL( error );
+ CleanupStack::Pop( error );
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::MapErrorPECtoCSP
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CAPresenceUtils::MapErrorPECtoCSP( TInt aError )
+ {
+ TInt error( aError );
+
+ // Map everything between KPEngErrorWVServerResponseBase and KPEngErrorBase
+ // to Imps_ERROR_BASE
+ if ( aError < KPEngErrorWVServerResponseBase &&
+ aError > KPEngErrorBase )
+ {
+ error = aError - KPEngErrorWVServerResponseBase + Imps_ERROR_BASE;
+ }
+
+ return error;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::AppendContactsL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CAPresenceUtils::AppendContactsL( MPEngContactList2* aContactList,
+ CDesCArray* aWVIds,
+ CDesCArray* aNicknames,
+ MCAStoredContacts* aContactStorage,
+ TInt& aEntryIndex,
+ MCAContactList& aCaContactList,
+ MCAPresenceUpdater& aPresenceUpdater )
+ {
+ // Fill arrays
+ TInt idCount( 0 );
+ TInt count( aContactList->Count() );
+ if ( aEntryIndex >= count )
+ {
+ // list has been changed, possibly we ran out of memory
+ aEntryIndex = count - 1;
+ }
+
+ if ( aWVIds && aNicknames )
+ {
+ while ( ( idCount < KMaxIdAtTheTime ) && ( aEntryIndex >= 0 ) )
+ {
+ MPEngContactItem& contact = aContactList->ContactItem( aEntryIndex );
+ TPtrC id = contact.Id();
+ TPtrC nick( contact.NickName() );
+ // append to lists
+ aWVIds->AppendL( id );
+ aNicknames->AppendL( nick );
+ ++idCount;
+ --aEntryIndex;
+ }
+ }
+ else
+ {
+ RPointerArray<MPEngPresenceAttrModel2> attrModels;
+ CAPresenceUtils::PushModelArrayL( attrModels, ETrue );
+ RPointerArray<MPEngPresenceAttrModel2> onlineStateModels;
+ CAPresenceUtils::PushModelArrayL( onlineStateModels, EFalse );
+
+ TPtrC aliasPtr( NULL, 0 );
+ TPtrC statusText( NULL, 0 );
+ TStorageManagerGlobals::TClientType clientType =
+ TStorageManagerGlobals::EUnknownClient;
+ const RPointerArray<CCAState>& presenceStates = aPresenceUpdater.PresenceStates();
+ TStorageManagerGlobals::TPresenceStatus presenceStatus =
+ TStorageManagerGlobals::EUnknown;
+
+ while ( ( idCount < KMaxIdAtTheTime ) && ( aEntryIndex >= 0 ) )
+ {
+ MPEngContactItem& contact = aContactList->ContactItem( aEntryIndex );
+ TPtrC uderId = contact.Id();
+ TPtrC nick( contact.NickName() );
+
+ // fetch attribute for this contact and add it all at once
+ aPresenceUpdater.ExtractAttributeModelsForUserL( uderId, attrModels );
+ // populate attributes
+ TInt attrCount( attrModels.Count() );
+ for ( TInt x( 0 ) ; x < attrCount ; ++x )
+ {
+ CAPresenceUtils::PopulateAttributesL( *attrModels[x],
+ onlineStateModels,
+ clientType,
+ aliasPtr,
+ statusText );
+ }
+
+ presenceStatus = MapPresenceStateId(
+ DecodeOnlineState( presenceStates, onlineStateModels ) );
+
+
+ // update directly to storage
+ aContactStorage->CreateContactL( aCaContactList,
+ nick,
+ uderId,
+ presenceStatus,
+ clientType,
+ aliasPtr,
+ statusText );
+
+ // reset attributes
+ onlineStateModels.Reset();
+ attrModels.ResetAndDestroy();
+
+ clientType = TStorageManagerGlobals::EUnknownClient;
+ statusText.Set( NULL, 0 );
+ aliasPtr.Set( KNullDesC );
+
+ ++idCount;
+ --aEntryIndex;
+ }
+ CleanupStack::PopAndDestroy( 2 ); // attrModels, onlineStateModels
+ }
+
+ // if aEntryIndex is -1, then we are done
+ return ( aEntryIndex != -1 );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::ReadAttributeL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TCAAttribute CAPresenceUtils::ReadAttributeL( TResourceReader& aReader )
+ {
+ TInt attribute( aReader.ReadInt16() );
+ TInt qualifier( aReader.ReadInt16() );
+ TInt value( aReader.ReadInt16() );
+
+ TCAAttribute attr;
+ attr.iQualifier = ( qualifier == EIMQualifierTrue );
+ attr.iData = KErrNotFound;
+ attr.iField = KErrNotFound;
+ attr.iGroup = KPEngDefaultAttrValueGroup;
+
+ switch ( attribute )
+ {
+ case EIMOnlineAttr:
+ {
+ attr.iAttribute = KUidPrAttrOnlineStatus;
+ attr.iField = EPEngOnlineStatus;
+ switch ( value )
+ {
+ case EIMOnlineNoChange:
+ {
+ // by default, value isn't used
+ break;
+ }
+ case EIMOnlineTrue:
+ {
+ attr.iData = EPEngOnlineStatusOnline;
+ break;
+ }
+ case EIMOnlineFalse:
+ {
+ attr.iData = EPEngOnlineStatusOffline;
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ break;
+ }
+ case EIMUserAvailabilityAttr:
+ {
+ attr.iAttribute = KUidPrAttrUserAvailability;
+ attr.iField = EPEngUsrAvailability;
+ switch ( value )
+ {
+ case EIMUserAvailabilityNoChange:
+ {
+ // by default, value isn't used
+ break;
+ }
+ case EIMUserAvailabilityNotAvailable:
+ {
+ attr.iData = EPEngUsrAvailabilityOffline;
+ break;
+ }
+ case EIMUserAvailabilityDiscreet:
+ {
+ attr.iData = EPEngUsrAvailabilityDiscreet;
+ break;
+ }
+ case EIMUserAvailabilityAvailable:
+ {
+ attr.iData = EPEngUsrAvailabilityOnline;
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ break;
+ }
+ case EIMCommCapAttr:
+ {
+ attr.iAttribute = KUidPrAttrCommCap;
+ attr.iField = EPEngCommCapStatus;
+ attr.iGroup = EPEngCommCapIMClient;
+ switch ( value )
+ {
+ case EIMCommCapNoChange:
+ {
+ // by default, value isn't used
+ break;
+ }
+ case EIMCommCapClosed:
+ {
+ attr.iData = EPEngCommCapStatusClosed;
+ break;
+ }
+ case EIMCommCapOpen:
+ {
+ attr.iData = EPEngCommCapStatusOpen;
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ break;
+ }
+ case EIMStatusTextAttr:
+ {
+ attr.iAttribute = KUidPrAttrStatusText;
+ switch ( value )
+ {
+ case EIMStatusTextNoChange:
+ {
+ // by default, value isn't used
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ return attr;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::MapStateId
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CAPresenceUtils::MapStateId( TInt aResourceStateId )
+ {
+ MCAPresence::TPresenceStatus ret( MCAPresence::EUnknown );
+ switch ( aResourceStateId )
+ {
+ case EIMStateAvailable:
+ {
+ ret = MCAPresence::EOnline;
+ break;
+ }
+ case EIMStateAway:
+ {
+ ret = MCAPresence::EAway;
+ break;
+ }
+ case EIMStateBusy:
+ {
+ ret = MCAPresence::EBusy;
+ break;
+ }
+ case EIMStateInvisible: // flowthrough at the moment
+ case EIMStateOffline:
+ {
+ ret = MCAPresence::EOffline;
+ break;
+ }
+ default:
+ {
+ User::Panic( KPanicAttribute, KErrArgument );
+ }
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::MapPresenceStateId
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TStorageManagerGlobals::TPresenceStatus CAPresenceUtils::MapPresenceStateId(
+ MCAPresence::TPresenceStatus aPresenceStateId )
+ {
+ TStorageManagerGlobals::TPresenceStatus ret( TStorageManagerGlobals::EUnknown );
+ switch ( aPresenceStateId )
+ {
+ case MCAPresence::EOnline:
+ {
+ ret = TStorageManagerGlobals::EOnline;
+ break;
+ }
+ case MCAPresence::EOffline:
+ {
+ ret = TStorageManagerGlobals::EOffline;
+ break;
+ }
+ case MCAPresence::EAway:
+ {
+ ret = TStorageManagerGlobals::EAway;
+ break;
+ }
+ case MCAPresence::EBusy:
+ {
+ ret = TStorageManagerGlobals::EBusy;
+ break;
+ }
+ default:
+ {
+ // nothing to do
+ }
+ }
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::ReadStatesFromResourceL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CAPresenceUtils::ReadStatesFromResourceL( TInt aResourceId,
+ RPointerArray<CCAState>& aStates )
+ {
+ TResourceReader reader;
+ CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
+
+ // reset array
+ aStates.ResetAndDestroy();
+
+ // read states
+ TInt stateCount( reader.ReadInt16() );
+ for ( TInt stateIndex( 0 ); stateIndex < stateCount; ++stateIndex )
+ {
+ // read state id and create state for it
+ TInt stateId( MapStateId( reader.ReadInt16() ) );
+
+ CCAState* state = new( ELeave )CCAState( stateId );
+ CleanupStack::PushL( state );
+
+ // and attributes
+ TInt attributeCount( reader.ReadInt16() );
+ for ( TInt i( 0 ); i < attributeCount; ++i )
+ {
+ state->iAttributes.AppendL( ReadAttributeL( reader ) );
+ }
+
+ // finished
+ aStates.AppendL( state );
+ CleanupStack::Pop( state );
+ }
+
+ CleanupStack::PopAndDestroy(); // reader
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::FindState
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CCAState* CAPresenceUtils::FindStateL( TInt aState, const RPointerArray<CCAState>& aStates )
+ {
+ CCAState* tmp = new( ELeave )CCAState( aState );
+ CleanupStack::PushL( tmp );
+
+ CCAState* ret = NULL;
+ TIdentityRelation< CCAState > equals( CAPresenceUtils::EqualStates );
+
+ TInt index( aStates.Find( tmp, equals ) );
+ if ( index != KErrNotFound )
+ {
+ ret = aStates[index];
+ }
+
+ CleanupStack::PopAndDestroy( tmp );
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::FindAttrL
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+const MPEngPresenceAttrModel2* CAPresenceUtils::FindAttr( TInt aType,
+ const RPointerArray<MPEngPresenceAttrModel2>& aArray )
+ {
+ TInt count( aArray.Count() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ const MPEngPresenceAttrModel2* attr = aArray[i];
+ if ( attr->Type() == aType )
+ {
+ return attr;
+ }
+ }
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CAPresenceUtils::EqualStates
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TBool CAPresenceUtils::EqualStates( const CCAState& aState1, const CCAState& aState2 )
+ {
+ return ( aState1.iStateId == aState2.iStateId );
+ }
+
+
+// End of File