wvuing/wvuieng/EngSrc/CCAGroupManager.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:  Network operations for chat group handling.
       
    15  *
       
    16 */
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include "ChatDebugPrint.h"
       
    20 
       
    21 #include "CCAGroupManager.h"
       
    22 
       
    23 #include "CCAStorageManagerFactory.h"
       
    24 #include "MCASettings.h"
       
    25 #include "MCASearchData.h"
       
    26 #include "MCASearchInterface.h"
       
    27 #include "MCAStoredGroups.h"
       
    28 #include "MCAStoredGroup.h"
       
    29 #include "MCAExtendedStoredGroup.h"
       
    30 #include "MCAGroupOperations.h"
       
    31 #include "CCAGroupWrapper.h"
       
    32 #include "PrivateEngineDefinitions.h"
       
    33 #include "TStorageManagerGlobals.h"
       
    34 #include "CCARequest.h"
       
    35 #include "CCARequestMapper.h"
       
    36 #include "MCAChatInterface.h"
       
    37 #include "MCAMessagesWriteInterface.h"
       
    38 #include "MCAMessageUtils.h"
       
    39 #include "MCAMessageCreator.h"
       
    40 #include "ImpsCSPAllErrors.h"
       
    41 #include "MCAImpsFactory.h"
       
    42 
       
    43 #include "CAUtils.h"
       
    44 #include "camessageutil.h"
       
    45 
       
    46 #include <e32keys.h>
       
    47 #include <ImpsFundamental.h>
       
    48 #include <ImpsGroupProps.h>
       
    49 
       
    50 // for resources
       
    51 #include <caengineNG.rsg>
       
    52 #include <stringloader.h>
       
    53 
       
    54 // CONSTANTS
       
    55 const TInt KCCAGMGroupWrappersGranularity = 5;
       
    56 const TInt KSearchPairsSmallGranularity = 1;
       
    57 const TInt KMaxUserSearchLimit = 100;
       
    58 
       
    59 // indexes to additional data array inside request
       
    60 const TInt KReqCreateIndexGroupId    = 0;
       
    61 const TInt KReqCreateIndexScreenName = 2;
       
    62 const TInt KReqCreateIndexWelcomeMsg = 3;
       
    63 const TInt KReqCreateIndexGroupTopic = 4;
       
    64 
       
    65 const TInt KReqJoinIndexGroupId    = 0;
       
    66 const TInt KReqJoinIndexScreenName = 1;
       
    67 
       
    68 // how many times should we try to generate unique group id
       
    69 const TInt KMaxGroupIds = 100;
       
    70 
       
    71 // maximum groups in search result. If search results
       
    72 // exceeds this then "too many search results" is shown
       
    73 const TInt KMaxGroupSearchLimit = 50;
       
    74 
       
    75 
       
    76 // ================= MEMBER FUNCTIONS =======================
       
    77 
       
    78 // Symbian OS default constructor can leave.
       
    79 void CCAGroupManager::ConstructL()
       
    80     {
       
    81     iStoredGroups = CCAStorageManagerFactory::GroupListInterfaceL();
       
    82     }
       
    83 
       
    84 // Two-phased constructor.
       
    85 CCAGroupManager* CCAGroupManager::NewL(
       
    86     MCASearchInterface& aSearchAPI,
       
    87     MCASettings& aSettingsAPI,
       
    88     CCARequestMapper& aRequestMapper,
       
    89     MCAImpsFactory* aIMPSFactory,
       
    90     MCAChatInterface& aChatInterface,
       
    91     MCAMessageUtils& aMessageUtils )
       
    92     {
       
    93     CCAGroupManager* self = new ( ELeave ) CCAGroupManager( aSearchAPI,
       
    94                                                             aSettingsAPI, aRequestMapper, aIMPSFactory,
       
    95                                                             aChatInterface, aMessageUtils );
       
    96 
       
    97     CleanupStack::PushL( self );
       
    98     self->ConstructL();
       
    99     CleanupStack::Pop( self );
       
   100 
       
   101     return self;
       
   102     }
       
   103 
       
   104 // Destructor
       
   105 CCAGroupManager::~CCAGroupManager()
       
   106     {
       
   107     iGroupWrappers.ResetAndDestroy();
       
   108     delete iProperties;
       
   109     delete iPrivProperties;
       
   110     }
       
   111 
       
   112 // C++ default constructor can NOT contain any code, that
       
   113 // might leave.
       
   114 //
       
   115 CCAGroupManager::CCAGroupManager(
       
   116     MCASearchInterface& aSearchAPI,
       
   117     MCASettings& aSettingsAPI,
       
   118     CCARequestMapper& aRequestMapper,
       
   119     MCAImpsFactory* aIMPSFactory,
       
   120     MCAChatInterface& aChatInterface,
       
   121     MCAMessageUtils& aMessageUtils   )
       
   122         : iRequestMapper( aRequestMapper ),
       
   123         iSettingsAPI( aSettingsAPI ),
       
   124         iSearchAPI( aSearchAPI ),
       
   125         iImpsFactory( aIMPSFactory ),
       
   126         iChatInterface( aChatInterface ),
       
   127         iMessageUtils( aMessageUtils ),
       
   128         iGroupWrappers( KCCAGMGroupWrappersGranularity )
       
   129     {
       
   130     }
       
   131 
       
   132 // ---------------------------------------------------------
       
   133 // CCAGroupManager::PopulateCreatedGroupsL
       
   134 // ---------------------------------------------------------
       
   135 //
       
   136 TInt CCAGroupManager::PopulateCreatedGroupsL( CDesCArray& aGroupList ) const
       
   137     {
       
   138     CHAT_DP_FUNC_ENTER( "PopulateCreatedGroupsL" );
       
   139 
       
   140     // Reset the given array to be sure that it will be valid
       
   141     aGroupList.Reset();
       
   142 
       
   143     HBufC* loggedUserId = iSettingsAPI.ValueL( MCASettings::EOwnWVUserID );
       
   144     CleanupStack::PushL( loggedUserId );
       
   145 
       
   146     CSearchPairs* pairs =
       
   147         new ( ELeave ) CSearchPairs( KSearchPairsSmallGranularity );
       
   148     CleanupStack::PushL( pairs );
       
   149 
       
   150     CImpsSearchRequest* request = CImpsSearchRequest::NewL();
       
   151     CleanupStack::PushL( request );
       
   152 
       
   153     request->SetRequestL( EImpsGroupUserIDOwner, *loggedUserId );
       
   154     pairs->AppendL( request );
       
   155 
       
   156     // If there is error in search, return so we don't send stop error request
       
   157     TInt searchError( KErrNone );
       
   158     searchError = iSearchAPI.StartSearchL( *pairs, KMaxUserSearchLimit, NULL );
       
   159     if ( searchError != KErrNone )
       
   160         {
       
   161         CHAT_DP( D_CHAT_LIT( "CCAGroupManager::PopulateCreatedGroupsL - error \
       
   162                               from StartSearchL %d" ), searchError );
       
   163         // request, pairs, loggedUserId
       
   164         CleanupStack::PopAndDestroy( 3, loggedUserId );
       
   165         return searchError;
       
   166         }
       
   167 
       
   168     TInt resultCount( iSearchAPI.SearchDataInterface()->SearchDataCount() );
       
   169 
       
   170     // just add all found groups to the group list
       
   171     for ( TInt counter( 0 ); counter < resultCount; counter++ )
       
   172         {
       
   173         TPtrC pGroupId(
       
   174             iSearchAPI.SearchDataInterface()->SearchData( counter ) );
       
   175         aGroupList.AppendL( pGroupId );
       
   176         }
       
   177 
       
   178     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::PopulateCreatedGroupsL - found %d \
       
   179                           groups from joined user" ), aGroupList.Count() );
       
   180 
       
   181     CleanupStack::PopAndDestroy( 3, loggedUserId );
       
   182 
       
   183     CHAT_DP_FUNC_DONE( "PopulateCreatedGroupsL" );
       
   184 
       
   185     return KErrNone;
       
   186     }
       
   187 
       
   188 // ---------------------------------------------------------
       
   189 // CCAGroupManager::JoinedGroups
       
   190 // ---------------------------------------------------------
       
   191 //
       
   192 TInt CCAGroupManager::JoinedGroups()
       
   193     {
       
   194     return iNumJoinedGroups;
       
   195     }
       
   196 
       
   197 
       
   198 // we just wrap the Handle*L routines by passing them
       
   199 // on to the correct group wrapper
       
   200 
       
   201 // ---------------------------------------------------------
       
   202 // CCAGroupManager::HandleErrorL
       
   203 // ---------------------------------------------------------
       
   204 //
       
   205 void CCAGroupManager::HandleErrorL(
       
   206     TInt aStatus,
       
   207     TInt aOpId,
       
   208     const TDesC* /* aDescription */,
       
   209     const CImpsDetailed* /* aDetailedRes */,
       
   210     TImpsCspIdentifier& /*aCspId*/ )
       
   211     {
       
   212     CHAT_DP_FUNC_ENTER( "HandleErrorL" );
       
   213     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleErrorL - opid=%d, status=%d" ),
       
   214              aOpId, aStatus );
       
   215 
       
   216     CHAT_DP_FUNC_DONE( "HandleErrorL" );
       
   217     }
       
   218 
       
   219 // ---------------------------------------------------------
       
   220 // CCAGroupManager::HandleCompleteL()
       
   221 // ---------------------------------------------------------
       
   222 //
       
   223 void CCAGroupManager::HandleCompleteL(
       
   224     TInt aOpId,
       
   225     TImpsCspIdentifier& aCspId )
       
   226     {
       
   227     CHAT_DP_FUNC_ENTER( "HandleCompleteL" );
       
   228     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleCompleteL - opid=%d" ), aOpId );
       
   229 
       
   230     CCAGroupWrapper* wrapper = FindGroupWrapper( aOpId );
       
   231 
       
   232     if ( ! wrapper )
       
   233         {
       
   234         // no such wrapper
       
   235         CHAT_DP_FUNC_DP( "HandleCompleteL", "No wrapper, leaving" );
       
   236         User::Leave( KErrNotFound );
       
   237         }
       
   238 
       
   239     CCARequest* request = wrapper->Request();
       
   240     __ASSERT_DEBUG( request, User::Panic( KCAEnginePanicCategory,
       
   241                                           KErrNotFound ) );
       
   242     if ( !request )
       
   243         {
       
   244         User::Leave( KErrNotFound );
       
   245         }
       
   246     const MDesCArray* dataArray = request->AdditionalData();
       
   247 
       
   248     switch ( request->RequestType() )
       
   249         {
       
   250         case ECreateAndJoinGroup :
       
   251             {
       
   252             __ASSERT_DEBUG( dataArray, User::Panic( KCAEnginePanicCategory,
       
   253                                                     KErrNotFound ) );
       
   254             if ( !dataArray )
       
   255                 {
       
   256                 // can't use User::LeaveIfNull for const pointers
       
   257                 User::Leave( KErrGeneral );
       
   258                 }
       
   259 
       
   260             CHAT_DP_FUNC_DP( "HandleCompleteL", "Creating chat data for group" );
       
   261 
       
   262             MCAMessagesWriteInterface& groupChat =
       
   263                 iChatInterface.MessageWriteInterfaceL( KNullDesC, KNullDesC,
       
   264                                                        dataArray->MdcaPoint( KReqCreateIndexGroupId ),
       
   265                                                        MCAMessagesReadInterface::EGroupContainer );
       
   266 
       
   267             groupChat.SetScreenNameL( dataArray->MdcaPoint(
       
   268                                           KReqCreateIndexScreenName ) );
       
   269 
       
   270             // Write welcome message to chat
       
   271             TPtrC welcome = dataArray->MdcaPoint( KReqCreateIndexWelcomeMsg );
       
   272             TPtrC topic = dataArray->MdcaPoint( KReqCreateIndexGroupTopic );
       
   273 
       
   274             CHAT_DP_FUNC_DP( "HandleCompleteL", "Showing welcome message" );
       
   275             MCAStoredGroup& group = wrapper->Group();
       
   276             TPtrC groupIdentifier =
       
   277                 group.GroupName().Length() > 0 ? group.GroupName() :
       
   278                 CAUtils::DisplayId( group.GroupId() );
       
   279 
       
   280             WriteWelcomeMessageL( welcome, groupIdentifier, topic, groupChat );
       
   281 
       
   282             // note, it suffices to increase the number of created groups
       
   283             // when CreateGroupL is called
       
   284             break;
       
   285             }
       
   286 
       
   287         default:
       
   288             {
       
   289             break;
       
   290             }
       
   291 
       
   292         }
       
   293 
       
   294     wrapper->HandleCompleteL( aOpId, aCspId );
       
   295 
       
   296     CHAT_DP_FUNC_DONE( "HandleCompleteL" );
       
   297     }
       
   298 
       
   299 // ---------------------------------------------------------
       
   300 // CCAGroupManager::HandleJoinL()
       
   301 // ---------------------------------------------------------
       
   302 //
       
   303 void CCAGroupManager::HandleJoinL(
       
   304     TInt aOpId,
       
   305     const MDesCArray& aUserList,
       
   306     const MDesCArray& aScreenNames,
       
   307     const TDesC& aWelcomeText,
       
   308     TImpsCspIdentifier& aCspId )
       
   309     {
       
   310     CHAT_DP_FUNC_ENTER( "HandleJoinL" );
       
   311     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleJoinL - opid=%d" ), aOpId );
       
   312 
       
   313     CCAGroupWrapper* wrapper = FindGroupWrapper( aOpId );
       
   314 
       
   315     if ( ! wrapper )
       
   316         {
       
   317         // no wrapper
       
   318         CHAT_DP_FUNC_DP( "HandleJoinL", "No wrapper, leaving" );
       
   319         User::Leave( KErrNotFound );
       
   320         }
       
   321 
       
   322     CCARequest* request = wrapper->Request();
       
   323     __ASSERT_DEBUG( request, User::Panic( KCAEnginePanicCategory,
       
   324                                           KErrNotFound ) );
       
   325     if ( !request )
       
   326         {
       
   327         User::Leave( KErrNotFound );
       
   328         }
       
   329     const MDesCArray* dataArray = request->AdditionalData();
       
   330 
       
   331     __ASSERT_DEBUG( dataArray, User::Panic( KCAEnginePanicCategory,
       
   332                                             KErrNotFound ) );
       
   333     if ( !dataArray )
       
   334         {
       
   335         // can't use User::LeaveIfError for const pointers
       
   336         User::Leave( KErrGeneral );
       
   337         }
       
   338 
       
   339     CHAT_DP_FUNC_DP( "HandleJoinL", "Creating chat data for group" );
       
   340 
       
   341     MCAMessagesWriteInterface& groupChat =
       
   342         iChatInterface.MessageWriteInterfaceL( KNullDesC, KNullDesC,
       
   343                                                dataArray->MdcaPoint( KReqJoinIndexGroupId ),
       
   344                                                MCAMessagesReadInterface::EGroupContainer );
       
   345     groupChat.SetScreenNameL( dataArray->MdcaPoint( KReqJoinIndexScreenName ) );
       
   346 
       
   347 
       
   348     CImpsCommonGroupProps* commonProps = NULL;
       
   349     CImpsPrivateGroupProps* privProps = NULL;
       
   350     // ownership is preserved in wrapper
       
   351     wrapper->LocalProperties( commonProps, privProps );
       
   352 
       
   353     TPtrC topic( KNullDesC );
       
   354     if ( commonProps )
       
   355         {
       
   356         topic.Set( commonProps->Topic() );
       
   357         }
       
   358 
       
   359     // Show welcome message
       
   360     MCAStoredGroup& group = wrapper->Group();
       
   361     TPtrC groupIdentifier =
       
   362         group.GroupName().Length() > 0 ? group.GroupName() :
       
   363         CAUtils::DisplayId( group.GroupId() );
       
   364     TRAPD( err, WriteWelcomeMessageL( aWelcomeText, groupIdentifier, topic, groupChat ) );
       
   365     if ( err == KErrNoMemory )
       
   366         {
       
   367         // Handle no memory error here
       
   368         request->SetErrorCode( err );
       
   369         request->StopWaitIfNeeded();
       
   370         return;
       
   371         }
       
   372     else
       
   373         {
       
   374         User::LeaveIfError( err );
       
   375         }
       
   376 
       
   377     // Topic was shown in WriteWelcomeMessageL
       
   378     if ( topic.Length() > 0 )
       
   379         {
       
   380         wrapper->SetTopicShown( ETrue );
       
   381         }
       
   382 
       
   383     // make sure it's marked as joined in the UI
       
   384     MCAExtendedStoredGroup& grp =
       
   385         static_cast<MCAExtendedStoredGroup&>( wrapper->Group() );
       
   386     if ( !grp.IsJoined() )
       
   387         {
       
   388         grp.SetJoined( ETrue );
       
   389         iNumJoinedGroups++;
       
   390         }
       
   391 
       
   392     CHAT_DP_FUNC_DP( "HandleJoinL", "Passing on to wrapper" );
       
   393     wrapper->HandleJoinL( aOpId, aUserList, aScreenNames,
       
   394                           aWelcomeText, aCspId );
       
   395 
       
   396     // show the joined-messages
       
   397     TInt numNames = aScreenNames.MdcaCount();
       
   398     for ( TInt index = 0; index < numNames; index++ )
       
   399         {
       
   400         HBufC* newUser = aScreenNames.MdcaPoint( index ).AllocLC();
       
   401 
       
   402         HBufC* finalNewUserText =
       
   403             StringLoader::LoadLC( R_SYSTEM_MESSAGE_JOIN,
       
   404                                   *newUser );
       
   405 
       
   406         CHAT_DP_FUNC_DP( "HandleJoinL", "Initiating new users message" );
       
   407 
       
   408         MCAMessage* newUserMsg =
       
   409             iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   410                 MCAMessage::ESystemMessageNewUsers,
       
   411                 *finalNewUserText );
       
   412 
       
   413         // Append message
       
   414         TRAPD( err, CAMessageUtil::AppendMessageWithDateStampL(
       
   415                    *newUserMsg,
       
   416                    groupChat,
       
   417                    iMessageUtils.MessageCreator() ) );
       
   418 
       
   419         if ( err == KErrNoMemory )
       
   420             {
       
   421             // Handle no memory error here
       
   422             CleanupStack::PopAndDestroy( 2, newUser ); // finalNewUserText, newUser
       
   423             request->SetErrorCode( err );
       
   424             request->StopWaitIfNeeded();
       
   425             return;
       
   426             }
       
   427         else
       
   428             {
       
   429             User::LeaveIfError( err );
       
   430             }
       
   431 
       
   432         CleanupStack::PopAndDestroy( 2, newUser ); // finalNewUserText, newUser
       
   433         }
       
   434 
       
   435     CHAT_DP_FUNC_DONE( "HandleJoinL" );
       
   436     }
       
   437 
       
   438 // ---------------------------------------------------------
       
   439 // CCAGroupManager::HandleGroupMembersL()
       
   440 // ---------------------------------------------------------
       
   441 //
       
   442 void CCAGroupManager::HandleGroupMembersL(
       
   443     TInt aOpId,
       
   444     const MDesCArray& aUserList,
       
   445     const MDesCArray& aScreenNames,
       
   446     const MDesCArray& aModers,
       
   447     const MDesCArray& aAdmins,
       
   448     TImpsCspIdentifier& aCspId )
       
   449     {
       
   450     CHAT_DP_FUNC_ENTER( "HandleGroupMembersL" );
       
   451     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleGroupMembersL - opid=%d" ),
       
   452              aOpId );
       
   453 
       
   454     CCAGroupWrapper* wrapper = FindGroupWrapper( aOpId );
       
   455     if ( ! wrapper )
       
   456         {
       
   457         CHAT_DP_FUNC_DP( "HandleGroupMembersL", "No wrapper, leaving" );
       
   458         User::Leave( KErrNotFound );
       
   459         }
       
   460 
       
   461     CHAT_DP_FUNC_DP( "HandleGroupMembersL", "Passing on to wrapper" );
       
   462     wrapper->HandleGroupMembersL( aOpId, aUserList, aScreenNames, aModers,
       
   463                                   aAdmins, aCspId );
       
   464 
       
   465     CHAT_DP_FUNC_DONE( "HandleGroupMembersL" );
       
   466     }
       
   467 
       
   468 // ---------------------------------------------------------
       
   469 // CCAGroupManager::HandleGroupPropertiesL()
       
   470 // ---------------------------------------------------------
       
   471 //
       
   472 void CCAGroupManager::HandleGroupPropertiesL(
       
   473     TInt aOpId,
       
   474     const TDesC& aGroupId,
       
   475     const CImpsCommonGroupProps& aGroupProps,
       
   476     const CImpsPrivateGroupProps& aOwnProps,
       
   477     TImpsCspIdentifier& aCspId )
       
   478     {
       
   479     CHAT_DP_FUNC_ENTER( "HandleGroupPropertiesL" );
       
   480     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleGroupPropertiesL - opid=%d" ),
       
   481              aOpId );
       
   482 
       
   483     CCAGroupWrapper* wrapper = NULL;
       
   484     TPtrC groupId( aGroupId );
       
   485 
       
   486     if ( aOpId != 0 )
       
   487         {
       
   488         // aGroupId is empty
       
   489         wrapper = FindGroupWrapper( aOpId );
       
   490 
       
   491         if ( !wrapper )
       
   492             {
       
   493             CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "No wrapper, leaving" );
       
   494             User::Leave( KErrNotFound );
       
   495             }
       
   496 
       
   497         groupId.Set( wrapper->Group().GroupId() );
       
   498         }
       
   499     else
       
   500         {
       
   501         // aGroupId is valid
       
   502         wrapper = FindGroupWrapper( aGroupId );
       
   503         }
       
   504 
       
   505     if ( ! wrapper )
       
   506         {
       
   507         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "No wrapper, leaving" );
       
   508         User::Leave( KErrNotFound );
       
   509         }
       
   510 
       
   511     CImpsCommonGroupProps* common = NULL;
       
   512     CImpsPrivateGroupProps* priv = NULL;
       
   513 
       
   514     // does the wrapper have the properties already?
       
   515     wrapper->LocalProperties( common, priv );
       
   516 
       
   517     if ( ( !common ) && ( !priv ) )
       
   518         {
       
   519         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "No existing properties" );
       
   520 
       
   521         // no existing properties, so create new ones
       
   522         common = CImpsCommonGroupProps::NewL();
       
   523         CleanupStack::PushL( common );
       
   524 
       
   525         priv = CImpsPrivateGroupProps::NewL();
       
   526         CleanupStack::Pop( common );
       
   527 
       
   528         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "Created new properties" );
       
   529 
       
   530         // transfer ownership
       
   531         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "Setting the properties" );
       
   532         wrapper->SetLocalProperties( common, priv );
       
   533         }
       
   534 
       
   535     // set the admin status
       
   536     CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "Setting administrator status" );
       
   537     MCAExtendedStoredGroup& group =
       
   538         static_cast<MCAExtendedStoredGroup&>( wrapper->Group() );
       
   539 
       
   540     if ( aOwnProps.Privileges() == EImpsAdmin )
       
   541         {
       
   542         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL",
       
   543                          "User is administrator in group" );
       
   544         group.SetAdmin( ETrue );
       
   545         }
       
   546     else if ( aOwnProps.Privileges() != EImpsUserUndef )
       
   547         {
       
   548         CHAT_DP_FUNC_DP( "HandleGroupPropertiesL",
       
   549                          "User is not administrator in group" );
       
   550         group.SetAdmin( EFalse );
       
   551         }
       
   552 
       
   553     if ( aGroupProps.GroupName().Length() > 0 )
       
   554         {
       
   555         if ( aGroupProps.GroupName().CompareC( group.GroupName() ) != 0 )
       
   556             {
       
   557             // group name has changed, so update it and signal UI
       
   558             group.SetGroupNameL( aGroupProps.GroupName() );
       
   559             iStoredGroups->SignalGroupChangedL( group.GroupId() );
       
   560             }
       
   561         }
       
   562     // if the group is stored in persistent storage, save changes to disk also
       
   563     if ( group.StorageType() == TStorageManagerGlobals::EStoragePersistent )
       
   564         {
       
   565         group.SaveChangesL();
       
   566         }
       
   567 
       
   568 
       
   569     // see if anything changed
       
   570     MCAMessagesWriteInterface& groupChat =
       
   571         iChatInterface.MessageWriteInterfaceL( KNullDesC, KNullDesC, groupId );
       
   572 
       
   573     // Ignore empty topics. We must only react to push messages
       
   574     // React also when topic was not shown in HandleJoinL while joining
       
   575     if ( ( ( aOpId == 0 ) && ( aGroupProps.Topic().Length() > 0 ) )
       
   576          || ( !( wrapper->IsTopicShown() ) && ( aOpId == iPropsOpIdWhileJoining ) ) )
       
   577         {
       
   578         // there is a topic, but has it changed?
       
   579 
       
   580         if ( ( ( 0 != aGroupProps.Topic().CompareC( common->Topic() ) ) ||
       
   581                !( wrapper->IsTopicShown() ) // Topic changed by user, compare gives 0
       
   582              )
       
   583              && aOpId == 0 )
       
   584             {
       
   585             // Check the group topic again, if length > 0, then display the topic
       
   586             if ( aGroupProps.Topic().Length() > 0 )
       
   587                 {
       
   588                 // it has changed
       
   589                 CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "Topic has changed" );
       
   590 
       
   591                 // Topic has changed so initiate system message
       
   592                 HBufC* newTopic = aGroupProps.Topic().AllocLC();
       
   593 
       
   594                 HBufC* finalNewTopic =
       
   595                     StringLoader::LoadLC( R_SYSTEM_MESSAGE_TOPIC,
       
   596                                           *newTopic );
       
   597 
       
   598                 MCAMessage* topicChgMsg =
       
   599                     iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   600                         MCAMessage::ESystemMessageTopicChanged,
       
   601                         *finalNewTopic );
       
   602 
       
   603                 // Append message
       
   604                 CAMessageUtil::AppendMessageWithDateStampL(
       
   605                     *topicChgMsg,
       
   606                     groupChat,
       
   607                     iMessageUtils.MessageCreator() );
       
   608 
       
   609                 wrapper->SetTopicShown( ETrue );
       
   610 
       
   611                 CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleGroupPropertiesL - \
       
   612                                   topic is %S" ), finalNewTopic );
       
   613 
       
   614                 CleanupStack::PopAndDestroy( 2, newTopic );//finalNewTopic, newTopic
       
   615                 }
       
   616             }
       
   617         else if ( aGroupProps.Topic().Length() > 0
       
   618                   && aOpId == iPropsOpIdWhileJoining )
       
   619             {
       
   620             // Show topic of group when joining
       
   621             iPropsOpIdWhileJoining = KErrNotFound;
       
   622             HBufC* topicText =
       
   623                 StringLoader::LoadLC( R_SYSTEM_MESSAGE_TOPIC_TEXT,
       
   624                                       aGroupProps.Topic() );
       
   625             groupChat.AppendL(
       
   626                 iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   627                     MCAMessage::ESystemMessageWelcome, *topicText ) );
       
   628 
       
   629             wrapper->SetTopicShown( ETrue );
       
   630             CleanupStack::PopAndDestroy( topicText );
       
   631             }
       
   632         }
       
   633 
       
   634     // Private (whispering) state change. We must only react to push messages
       
   635     if ( ( aOpId == 0 ) && ( aGroupProps.IsPrivateAllowed() == EImpsPropYes ) )
       
   636         {
       
   637         // The state is active, but has it changed?
       
   638         if ( aGroupProps.IsPrivateAllowed() != common->IsPrivateAllowed() )
       
   639             {
       
   640             // private flag has changed
       
   641             CHAT_DP_FUNC_DP( "HandleGroupPropertiesL",
       
   642                              "Private messaging turn on" );
       
   643             HBufC* privatMessaging =
       
   644                 StringLoader::LoadLC( R_SYSTEM_MESSAGE_PRIVAT_ON );
       
   645 
       
   646             MCAMessage* privateChgMsg =
       
   647                 iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   648                     MCAMessage::ESystemMessagePrivatChanged,
       
   649                     *privatMessaging );
       
   650 
       
   651             // Append message
       
   652             CAMessageUtil::AppendMessageWithDateStampL(
       
   653                 *privateChgMsg,
       
   654                 groupChat,
       
   655                 iMessageUtils.MessageCreator() );
       
   656 
       
   657             CleanupStack::PopAndDestroy( privatMessaging );
       
   658             }
       
   659         }
       
   660     else
       
   661         {
       
   662         // we must only react to push messages
       
   663         if ( ( aOpId == 0 ) &&
       
   664              ( aGroupProps.IsPrivateAllowed() != EImpsPropUndef ) )
       
   665             {
       
   666             // the flag is in some non-empty, valid, non-Yes state
       
   667             // (currently only one such possibility)
       
   668 
       
   669             if ( aGroupProps.IsPrivateAllowed() != common->IsPrivateAllowed() )
       
   670                 {
       
   671                 CHAT_DP_FUNC_DP( "HandleGroupPropertiesL",
       
   672                                  "Private messaging turn off" );
       
   673 
       
   674                 HBufC* privatMessaging = StringLoader::LoadLC(
       
   675                                              R_SYSTEM_MESSAGE_PRIVAT_OFF );
       
   676 
       
   677                 MCAMessage* privateChgMsg =
       
   678                     iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   679                         MCAMessage::ESystemMessagePrivatChanged,
       
   680                         *privatMessaging );
       
   681 
       
   682                 // Append message
       
   683                 CAMessageUtil::AppendMessageWithDateStampL(
       
   684                     *privateChgMsg,
       
   685                     groupChat,
       
   686                     iMessageUtils.MessageCreator() );
       
   687 
       
   688                 CleanupStack::PopAndDestroy( privatMessaging );
       
   689                 }
       
   690             }
       
   691         }
       
   692 
       
   693     CHAT_DP_FUNC_DP( "HandleGroupPropertiesL", "Passing on to wrapper" );
       
   694     wrapper->HandleGroupPropertiesL( aOpId, groupId, aGroupProps,
       
   695                                      aOwnProps, aCspId );
       
   696 
       
   697     CHAT_DP_FUNC_DONE( "HandleGroupPropertiesL" );
       
   698     }
       
   699 
       
   700 // ---------------------------------------------------------
       
   701 // CCAGroupManager::HandleRejectListL()
       
   702 // ---------------------------------------------------------
       
   703 //
       
   704 void CCAGroupManager::HandleRejectListL(
       
   705     TInt aOpId,
       
   706     const MDesCArray& aUserList,
       
   707     TImpsCspIdentifier& aCspId )
       
   708     {
       
   709     CHAT_DP_FUNC_ENTER( "HandleRejectListL" );
       
   710     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleRejectListL - opid=%d" ),
       
   711              aOpId );
       
   712 
       
   713     CCAGroupWrapper* wrapper = FindGroupWrapper( aOpId );
       
   714     if ( ! wrapper )
       
   715         {
       
   716         CHAT_DP_FUNC_DP( "HandleRejectListL", "No wrapper, leaving" );
       
   717         User::Leave( KErrNotFound );
       
   718         }
       
   719 
       
   720     CHAT_DP_FUNC_DP( "HandleRejectListL", "Passing on to wrapper" );
       
   721     wrapper->HandleRejectListL( aOpId, aUserList, aCspId );
       
   722 
       
   723     CHAT_DP_FUNC_DONE( "HandleRejectListL" );
       
   724     }
       
   725 
       
   726 // ---------------------------------------------------------
       
   727 // CCAGroupManager::HandleSubscriptionL()
       
   728 // ---------------------------------------------------------
       
   729 //
       
   730 void CCAGroupManager::HandleSubscriptionL(
       
   731     TInt aOpId,
       
   732     TBool aIsSubscribed,
       
   733     TImpsCspIdentifier& aCspId )
       
   734     {
       
   735     CHAT_DP_FUNC_ENTER( "HandleSubscriptionL" );
       
   736     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleSubscriptionL - opid=%d" ),
       
   737              aOpId );
       
   738 
       
   739     // can't be a push message
       
   740     CCAGroupWrapper* wrapper = FindGroupWrapper( aOpId );
       
   741     if ( ! wrapper )
       
   742         {
       
   743         CHAT_DP_FUNC_DP( "HandleSubscriptionL", "No wrapper, leaving" );
       
   744         User::Leave( KErrNotFound );
       
   745         }
       
   746 
       
   747     CHAT_DP_FUNC_DP( "HandleSubscriptionL", "Passing on to wrapper" );
       
   748     wrapper->HandleSubscriptionL( aOpId, aIsSubscribed, aCspId );
       
   749 
       
   750     CHAT_DP_FUNC_DONE( "HandleSubscriptionL" );
       
   751     }
       
   752 
       
   753 // ---------------------------------------------------------
       
   754 // CCAGroupManager::HandleNewUsersL()
       
   755 // ---------------------------------------------------------
       
   756 //
       
   757 void CCAGroupManager::HandleNewUsersL(
       
   758     const TDesC& aGroupId,
       
   759     const MDesCArray& aUserList,
       
   760     const MDesCArray& aScreenNames,
       
   761     TImpsCspIdentifier& aCspId )
       
   762     {
       
   763     CHAT_DP_FUNC_ENTER( "HandleNewUsersL" );
       
   764     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleNewUsersL " ) );
       
   765 
       
   766     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
   767 
       
   768     if ( ! wrapper )
       
   769         {
       
   770         CHAT_DP_FUNC_DP( "HandleNewUsersL", "No wrapper, leaving" );
       
   771         User::Leave( KErrNotFound );
       
   772         }
       
   773 
       
   774     // print the user and screen names list
       
   775 #ifdef _DEBUG
       
   776     TInt i( 0 );
       
   777     TInt count( aUserList.MdcaCount() );
       
   778     CHAT_DP_FUNC_DP( "HandleNewUsersL", "User list:" );
       
   779     for ( i = 0; i < count; i++ )
       
   780         {
       
   781         TPtrC p = TPtrC( aUserList.MdcaPoint( i ) );
       
   782         CHAT_DP( D_CHAT_LIT( "   %S" ), &p );
       
   783         }
       
   784 
       
   785     count = aScreenNames.MdcaCount();
       
   786     CHAT_DP_FUNC_DP( "HandleNewUsersL", "Screen names list:" );
       
   787     for ( i = 0; i < count; i++ )
       
   788         {
       
   789         TPtrC p = TPtrC( aScreenNames.MdcaPoint( i ) );
       
   790         CHAT_DP( D_CHAT_LIT( "   %S" ), &p );
       
   791         }
       
   792 #endif
       
   793 
       
   794     // get the list of participants
       
   795     MCAStoredGroup& group = wrapper->Group();
       
   796 
       
   797     // this granularity is as good as any
       
   798     CDesCArrayFlat* participants =
       
   799         new ( ELeave ) CDesCArrayFlat( KJoinedMembersArrayGranularity );
       
   800     CleanupStack::PushL( participants );
       
   801     group.GetParticipantsL( *participants );
       
   802 
       
   803     TInt numNames( aScreenNames.MdcaCount() );
       
   804 
       
   805     // list has names
       
   806     for ( TInt index = 0; index < numNames; index++ )
       
   807         {
       
   808         // don't show joined-message for persons already joined to the group
       
   809         TInt posIgnored = 0;
       
   810         if ( participants->Find( aScreenNames.MdcaPoint( index ),
       
   811                                  posIgnored, ECmpFolded ) )
       
   812             {
       
   813             // a new user, show the message
       
   814             HBufC* newUser = aScreenNames.MdcaPoint( index ).AllocLC();
       
   815 
       
   816             HBufC* finalNewUserText =
       
   817                 StringLoader::LoadLC( R_SYSTEM_MESSAGE_JOIN,
       
   818                                       *newUser );
       
   819 
       
   820             CHAT_DP_FUNC_DP( "HandleNewUsersL",
       
   821                              "Initiating new users message" );
       
   822 
       
   823             MCAMessagesWriteInterface& groupChat =
       
   824                 iChatInterface.MessageWriteInterfaceL( KNullDesC,
       
   825                                                        KNullDesC, aGroupId );
       
   826 
       
   827             MCAMessage* newUserMsg =
       
   828                 iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   829                     MCAMessage::ESystemMessageNewUsers,
       
   830                     *finalNewUserText );
       
   831 
       
   832             // Append message
       
   833             CAMessageUtil::AppendMessageWithDateStampL(
       
   834                 *newUserMsg,
       
   835                 groupChat,
       
   836                 iMessageUtils.MessageCreator() );
       
   837 
       
   838             // finalNewUserText, newUser
       
   839             CleanupStack::PopAndDestroy( 2, newUser );
       
   840             }
       
   841         }
       
   842 
       
   843     CleanupStack::PopAndDestroy( participants );
       
   844 
       
   845     CHAT_DP_FUNC_DP( "HandleNewUsersL", "Passing on to wrapper" );
       
   846     wrapper->HandleNewUsersL( aGroupId, aUserList, aScreenNames, aCspId );
       
   847 
       
   848     CHAT_DP_FUNC_DONE( "HandleNewUsersL" );
       
   849     }
       
   850 
       
   851 // ---------------------------------------------------------
       
   852 // CCAGroupManager::HandleLeftUsersL()
       
   853 // ---------------------------------------------------------
       
   854 //
       
   855 void CCAGroupManager::HandleLeftUsersL(
       
   856     const TDesC& aGroupId,
       
   857     const MDesCArray& aUserList,
       
   858     const MDesCArray& aScreenNames,
       
   859     TImpsCspIdentifier& aCspId )
       
   860     {
       
   861     CHAT_DP_FUNC_ENTER( "HandleLeftUsersL" );
       
   862     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleLeftUsersL" ) );
       
   863 
       
   864     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
   865 
       
   866     if ( ! wrapper )
       
   867         {
       
   868         CHAT_DP_FUNC_DP( "HandleLeftUsersL", "No wrapper, leaving" );
       
   869         User::Leave( KErrNotFound );
       
   870         }
       
   871 
       
   872     CHAT_DP_FUNC_DP( "HandleLeftUsersL", "Passing on to wrapper" );
       
   873     wrapper->HandleLeftUsersL( aGroupId, aUserList, aScreenNames, aCspId );
       
   874 
       
   875     TInt numNames( aScreenNames.MdcaCount() );
       
   876     // list has names
       
   877     for ( TInt index = 0; index < numNames; index++ )
       
   878         {
       
   879         HBufC* leftUser = aScreenNames.MdcaPoint( index ).AllocLC();
       
   880 
       
   881         HBufC* finalLeftUserText =
       
   882             StringLoader::LoadLC( R_SYSTEM_MESSAGE_LEAVE,
       
   883                                   *leftUser );
       
   884 
       
   885         CHAT_DP_FUNC_DP( "HandleLeftUsersL", "Initiating left users message" );
       
   886 
       
   887         MCAMessagesWriteInterface& groupChat =
       
   888             iChatInterface.MessageWriteInterfaceL( KNullDesC,
       
   889                                                    KNullDesC, aGroupId );
       
   890 
       
   891         MCAMessage* userLeftMsg =
       
   892             iMessageUtils.MessageCreator().CreateSystemMessageL(
       
   893                 MCAMessage::ESystemMessageLeftUsers, *finalLeftUserText );
       
   894 
       
   895         // Append message
       
   896         CAMessageUtil::AppendMessageWithDateStampL(
       
   897             *userLeftMsg,
       
   898             groupChat,
       
   899             iMessageUtils.MessageCreator() );
       
   900 
       
   901         CleanupStack::PopAndDestroy( 2, leftUser ); // finalLeftUserText, leftUser
       
   902         }
       
   903 
       
   904     CHAT_DP_FUNC_DONE( "HandleLeftUsersL" );
       
   905     }
       
   906 
       
   907 // ---------------------------------------------------------
       
   908 // CCAGroupManager::HandleLeaveL()
       
   909 // ---------------------------------------------------------
       
   910 //
       
   911 void CCAGroupManager::HandleLeaveL(
       
   912     TInt aOpId,
       
   913     const TDesC& aGroupId,
       
   914     const TDesC& aDescription,
       
   915     TImpsCspIdentifier& aCspId )
       
   916     {
       
   917     CHAT_DP_FUNC_ENTER( "HandleLeaveL" );
       
   918     CHAT_DP( D_CHAT_LIT( "CCAGroupManager::HandleLeaveL - opid=%d" ), aOpId );
       
   919 
       
   920     CCAGroupWrapper* wrapper = NULL;
       
   921     if ( aOpId != 0 )
       
   922         {
       
   923         // operation id is valid
       
   924         wrapper = FindGroupWrapper( aOpId );
       
   925         }
       
   926     else
       
   927         {
       
   928         // group id is valid
       
   929         wrapper = FindGroupWrapper( aGroupId );
       
   930         }
       
   931 
       
   932     if ( ! wrapper )
       
   933         {
       
   934         CHAT_DP_FUNC_DP( "HandleLeaveL", "No wrapper, leaving" );
       
   935         User::Leave( KErrNotFound );
       
   936         }
       
   937 
       
   938     // handle the leave in wrapper
       
   939     MCAExtendedStoredGroup& gr =
       
   940         static_cast<MCAExtendedStoredGroup&>( wrapper->Group() );
       
   941 
       
   942     // Work with copy of group id, as wrapper gets deleted soon.
       
   943     // Also, group id is not valid in push.
       
   944     HBufC* grId = gr.GroupId().AllocLC();
       
   945 
       
   946     CHAT_DP_FUNC_DP( "HandleLeaveL", "Passing on to wrapper" );
       
   947 
       
   948     wrapper->LastImpsError( iLastImpsError );
       
   949     //reset/consume last error
       
   950     iLastImpsError = KErrNone;
       
   951 
       
   952     wrapper->HandleLeaveL( aOpId, *grId, aDescription, aCspId );
       
   953 
       
   954     if ( aOpId == 0 )
       
   955         {
       
   956         CHAT_DP_FUNC_DP( "HandleLeaveL",
       
   957                          "Push message, cleaning up in HandleLeaveL" );
       
   958         // push messages we cleanup here,
       
   959         // pull messages in the LeaveGroupL which originated
       
   960         // this call chain
       
   961         CleanupLeaveGroupL( *grId );
       
   962         }
       
   963 
       
   964     CleanupStack::PopAndDestroy( grId );
       
   965     CHAT_DP_FUNC_DONE( "HandleLeaveL" );
       
   966     }
       
   967 
       
   968 // set group as un-joined, and delete wrapper, group and associated
       
   969 // group chat data
       
   970 void CCAGroupManager::CleanupLeaveGroupL( const TDesC& aGroupId )
       
   971     {
       
   972     CHAT_DP_FUNC_ENTER( "CleanupLeaveGroupL" );
       
   973 
       
   974     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
   975     if ( !wrapper )
       
   976         {
       
   977         CHAT_DP_FUNC_DP( "CleanupLeaveGroupL", "no wrapper, nothing to do!" );
       
   978         return;
       
   979         }
       
   980     MCAExtendedStoredGroup& gr =
       
   981         static_cast<MCAExtendedStoredGroup&>( wrapper->Group() );
       
   982 
       
   983     CHAT_DP_FUNC_DP( "CleanupLeaveGroupL", "Leaving group" );
       
   984 
       
   985     if ( gr.IsJoined() )
       
   986         {
       
   987         gr.SetJoined( EFalse );
       
   988         iNumJoinedGroups--;
       
   989         }
       
   990 
       
   991     if ( ( !gr.IsOwnGroup() ) &&
       
   992          ( gr.StorageType() != TStorageManagerGlobals::EStoragePersistent ) )
       
   993         {
       
   994         // not own, not stored and not joined (after CleanupLeaveGroupL)
       
   995         // aWrappers shouldn't be on the list, so delete also from storage
       
   996         // (not from server)
       
   997         CHAT_DP_FUNC_DP( "CleanupLeaveGroupL", "Deleting aWrapper and group" );
       
   998         // delete returns error code of network delete operation
       
   999         // in case of group leave it is not import if group deleting fails
       
  1000         // from server, return code ignored
       
  1001         DeleteGroupL( aGroupId, EFalse );
       
  1002         }
       
  1003     else
       
  1004         {
       
  1005         // delete all server-related things:
       
  1006         // members, participants, admin status, whispering, etc.
       
  1007         gr.ResetMembersLocally();
       
  1008         gr.ResetParticipantsL();
       
  1009 
       
  1010         gr.SetAdmin( EFalse );
       
  1011 
       
  1012         // delete wrapper
       
  1013         DeleteGroupWrapper( aGroupId );
       
  1014         RemoveChatDataL( aGroupId );
       
  1015         }
       
  1016 
       
  1017     CHAT_DP_FUNC_DONE( "CleanupLeaveGroupL" );
       
  1018     }
       
  1019 
       
  1020 
       
  1021 
       
  1022 // ---------------------------------------------------------
       
  1023 // CCAGroupManager::NumberOfCreatedGroupsDuringSession
       
  1024 // ---------------------------------------------------------
       
  1025 //
       
  1026 TInt CCAGroupManager::NumberOfCreatedGroupsDuringSession() const
       
  1027     {
       
  1028     return iNumCreatedGroups;
       
  1029     }
       
  1030 
       
  1031 // ---------------------------------------------------------
       
  1032 // CCAGroupManager::GroupOperations
       
  1033 // ---------------------------------------------------------
       
  1034 //
       
  1035 MCAGroupOperations* CCAGroupManager::GroupOperationsL( const TDesC& aId )
       
  1036     {
       
  1037     CHAT_DP_FUNC_ENTER( "GroupOperationsL" );
       
  1038 
       
  1039     CCAGroupWrapper* groupWrapper = FindGroupWrapper( aId );
       
  1040     if ( groupWrapper )
       
  1041         {
       
  1042         // found an existing wrapper
       
  1043         CHAT_DP_FUNC_DONE( "GroupOperationsL" );
       
  1044         return groupWrapper;
       
  1045         }
       
  1046 
       
  1047     CHAT_DP_FUNC_DONE( "GroupOperationsL" );
       
  1048 
       
  1049     // no existing wrapper. make a new one, store it and return it
       
  1050     return CreateWrapperL( aId );
       
  1051     }
       
  1052 
       
  1053 // ---------------------------------------------------------
       
  1054 // CCAGroupManager::SetGroupEventObserver
       
  1055 // Call with NULL observer is safely handled at all times
       
  1056 // ---------------------------------------------------------
       
  1057 //
       
  1058 void CCAGroupManager::SetGroupEventObserverL( const TDesC& aId,
       
  1059                                               MCAGroupEventObserver* aObserver )
       
  1060     {
       
  1061     CHAT_DP_FUNC_ENTER( "SetGroupEventObserverL" );
       
  1062 
       
  1063     CCAGroupWrapper* groupWrapper = FindGroupWrapper( aId );
       
  1064 
       
  1065     if ( ! groupWrapper )
       
  1066         {
       
  1067         // not found
       
  1068         if ( aObserver )
       
  1069             {
       
  1070             // valid observer
       
  1071             CHAT_DP_FUNC_DP( "SetGroupEventObserverL", "Creating new wrapper" );
       
  1072             groupWrapper = CreateWrapperL( aId );
       
  1073             }
       
  1074         }
       
  1075 
       
  1076     if ( groupWrapper )
       
  1077         {
       
  1078         // no new wrappers are to be created for null observers - in
       
  1079         // such a case there's no observer anyway!
       
  1080         CHAT_DP_FUNC_DP( "SetGroupEventObserverL", "Setting event observer" );
       
  1081         groupWrapper->RegisterEventObserver( aObserver );
       
  1082         }
       
  1083 
       
  1084     CHAT_DP_FUNC_DONE( "SetGroupEventObserverL" );
       
  1085     }
       
  1086 
       
  1087 // ---------------------------------------------------------
       
  1088 // CCAGroupManager::CreateGroupL
       
  1089 // ---------------------------------------------------------
       
  1090 //
       
  1091 HBufC* CCAGroupManager::CreateGroupL(
       
  1092     CImpsCommonGroupProps* aProperties,
       
  1093     CImpsPrivateGroupProps* aPrivProperties,
       
  1094     const TDesC& aScreenName,
       
  1095     TBool aJoinGroup,
       
  1096     TBool aIsWhisperingEnabled,
       
  1097     TInt& aErrorCode
       
  1098 )
       
  1099     {
       
  1100     CHAT_DP_FUNC_ENTER( "CreateGroupL" );
       
  1101 
       
  1102     if ( !aProperties || !aPrivProperties )
       
  1103         {
       
  1104         User::Leave( KErrArgument );
       
  1105         }
       
  1106     // 1. create group to storage
       
  1107     // 2. invent a group name for the newly created group
       
  1108     // 3. create a group wrapper
       
  1109     // 4. pass this method on to the group wrapper
       
  1110     // 5. return the group id
       
  1111 
       
  1112 
       
  1113     // deleting old values, just in case that previous CreateGroup has failed
       
  1114     delete iProperties;
       
  1115     delete iPrivProperties;
       
  1116     iProperties = aProperties;
       
  1117     iPrivProperties = aPrivProperties;
       
  1118 
       
  1119     // create group
       
  1120     MCAExtendedStoredGroup* exGrp = iStoredGroups->CreateGroupL();
       
  1121     // Check memory level, leaves group creation with KErrDiskFull
       
  1122     // now if new group cannot be added to persistent database
       
  1123     TRAPD( err, iStoredGroups->CheckFreespaceLevelL( exGrp ) );
       
  1124     if ( err == KErrDiskFull )
       
  1125         {
       
  1126         // Make sure nothing is left to storage
       
  1127         iStoredGroups->DeleteGroupL( exGrp );
       
  1128         User::Leave( err );
       
  1129         }
       
  1130     exGrp->SetAdmin( ETrue );
       
  1131     exGrp->SetGroupNameL( aProperties->GroupName() );
       
  1132 
       
  1133     CHAT_DP( D_CHAT_LIT( "Group whisper, common=%d, priv=%d" ),
       
  1134              aProperties->IsPrivateAllowed(),
       
  1135              aPrivProperties->IsPrivateAllowed() );
       
  1136 
       
  1137     TBool allDone = EFalse;
       
  1138     TInt maxTries( KMaxGroupIds );   // fail-safe to prevent infinite loop
       
  1139 
       
  1140     CCAGroupWrapper* grOp = NULL;
       
  1141     while ( ( ! allDone ) && ( maxTries > 0 ) )
       
  1142         {
       
  1143         HBufC* groupId = NULL;
       
  1144         while ( !groupId )
       
  1145             {
       
  1146             groupId = GenerateGroupIdLC( aProperties->GroupName() );
       
  1147             if ( iStoredGroups->FindGroup( *groupId ) )
       
  1148                 {
       
  1149                 // group was found from storage, so let's
       
  1150                 // delete it and try next one
       
  1151                 CleanupStack::PopAndDestroy( groupId );
       
  1152                 groupId = NULL;
       
  1153                 }
       
  1154             }
       
  1155 
       
  1156         // now we have a unique group id that is not in storage,
       
  1157         exGrp->SetGroupIdL( *groupId );
       
  1158         CleanupStack::PopAndDestroy( groupId );
       
  1159         groupId = NULL;
       
  1160 
       
  1161         if ( !grOp )
       
  1162             {
       
  1163             // we don't have a wrapper yet, so let's
       
  1164             // create it for the group and set the properties
       
  1165             grOp = static_cast<CCAGroupWrapper*>( GroupOperationsL(
       
  1166                                                       exGrp->GroupId() ) );
       
  1167             // wrapper takes the ownership of properties from now on
       
  1168             grOp->SetLocalProperties( aProperties, aPrivProperties );
       
  1169             iProperties = NULL;
       
  1170             iPrivProperties = NULL;
       
  1171             }
       
  1172 
       
  1173 
       
  1174         // finalize group creation to the network
       
  1175         CHAT_DP_FUNC_DP( "CreateGroupL", "Creating group to network" );
       
  1176         aErrorCode = grOp->CreateGroupL( aScreenName, aJoinGroup );
       
  1177 
       
  1178         if ( ( aErrorCode == KErrNone )
       
  1179              || ( aErrorCode == ECSPPartiallySuccessful )  )
       
  1180             {
       
  1181             // search groups from server, in order to get the new groupid
       
  1182             // begin
       
  1183             HBufC* loggedUserId = iSettingsAPI.ValueL( MCASettings::EOwnWVUserID );
       
  1184             CleanupStack::PushL( loggedUserId );
       
  1185             
       
  1186             CSearchPairs* tempPairs = 
       
  1187 				new ( ELeave ) CSearchPairs( KSearchPairsSmallGranularity );
       
  1188             CleanupStack::PushL( tempPairs );
       
  1189             CImpsSearchRequest* tempRequest = CImpsSearchRequest::NewL();
       
  1190             CleanupStack::PushL( tempRequest );
       
  1191             tempRequest->SetRequestL( EImpsGroupUserIDOwner, *loggedUserId );
       
  1192             tempPairs->AppendL( tempRequest );
       
  1193 
       
  1194             // If there is error in search, return so we don't send stop error request
       
  1195             TInt searchError( KErrNone );
       
  1196             TInt err( KErrNone );
       
  1197             TRAP( err, searchError = 
       
  1198 				iSearchAPI.StartSearchL( *tempPairs, KMaxGroupSearchLimit, NULL ) );
       
  1199                 
       
  1200             CleanupStack::PopAndDestroy( 3, loggedUserId );// tempRequest, tempPairs, loggedUserId
       
  1201             
       
  1202             if ( err != KErrNone )
       
  1203             	{
       
  1204             	User::LeaveIfError( err );
       
  1205             	}
       
  1206             else if ( searchError != KErrNone )
       
  1207             	{
       
  1208             	User::LeaveIfError( searchError );
       
  1209             	}
       
  1210             
       
  1211             TInt resultCount( 
       
  1212             		iSearchAPI.SearchDataInterface()->SearchDataCount() );
       
  1213 
       
  1214             for ( TInt counter( 0 ); counter < resultCount; counter++ )
       
  1215             	{
       
  1216             	// see if this group is already in storage
       
  1217             	TPtrC groupId( iSearchAPI.SearchDataInterface()->SearchData( 
       
  1218             			counter ) );
       
  1219             	MCAStoredGroup* group = iStoredGroups->FindGroup( groupId );
       
  1220 
       
  1221             	if ( !group )
       
  1222             		{
       
  1223             		exGrp->SetGroupIdL( groupId );
       
  1224             		break;
       
  1225             		}
       
  1226             	}
       
  1227             // end
       
  1228 
       
  1229             // must update to the server
       
  1230             if ( aIsWhisperingEnabled )
       
  1231                 {
       
  1232                 SetPrivateAllowedL( *grOp, *aPrivProperties );
       
  1233                 }
       
  1234 
       
  1235             // this is our group
       
  1236             exGrp->SetOwnGroup( ETrue );
       
  1237 
       
  1238             if ( !exGrp->IsJoined() && aJoinGroup )
       
  1239                 {
       
  1240                 iNumJoinedGroups++;
       
  1241                 }
       
  1242             // set the joined status
       
  1243             exGrp->SetJoined( aJoinGroup );
       
  1244 
       
  1245             // make it a favorite, automatically
       
  1246             exGrp->SaveChangesL();
       
  1247 
       
  1248             // tell the UI the group has been added
       
  1249             iStoredGroups->SignalGroupAddedL( exGrp->GroupId() );
       
  1250 
       
  1251             aErrorCode = KErrNone; // it's fully successful now...
       
  1252             allDone = ETrue;       // get out too
       
  1253             }
       
  1254         else
       
  1255             {
       
  1256             if ( aErrorCode == ECSPGroupAlreadyExists )
       
  1257                 {
       
  1258                 // group already exists
       
  1259                 CHAT_DP_FUNC_DP( "CreateGroupL",
       
  1260                                  "Wrapper's CreateGroupL failed, trying with another groupid" );
       
  1261 
       
  1262                 maxTries--;
       
  1263                 }
       
  1264             else
       
  1265                 {
       
  1266                 // delete the group from storage if CreateGroupL failed,
       
  1267                 // aErrorCode is already set for use after return
       
  1268                 CHAT_DP_FUNC_DP( "CreateGroupL",
       
  1269                                  "Wrapper's CreateGroupL failed, aborting" );
       
  1270                 // delete return value is network operation error code
       
  1271                 // we are not interested it,
       
  1272                 // because group creation already failed
       
  1273                 DeleteGroupL( exGrp->GroupId(), EFalse );
       
  1274                 // group got deleted, return NULL
       
  1275                 return NULL;
       
  1276                 }
       
  1277             }
       
  1278         }
       
  1279 
       
  1280     // failsafe, if we reached the maximum number of tries
       
  1281     if ( maxTries == 0 )
       
  1282         {
       
  1283         // everything is cleaned up in the loop
       
  1284         return NULL;
       
  1285         }
       
  1286 
       
  1287     // Add creator of group as participant to group.
       
  1288     // Just because creator is participating group.
       
  1289     // Server does not always inform us for this one.
       
  1290     CDesCArrayFlat* participants =
       
  1291         new ( ELeave ) CDesCArrayFlat( KJoinedMembersArrayGranularity );
       
  1292     CleanupStack::PushL( participants );
       
  1293     participants->AppendL( aScreenName );
       
  1294     exGrp->AddParticipantL( *participants );
       
  1295     CleanupStack::PopAndDestroy( participants );
       
  1296 
       
  1297     iNumCreatedGroups++;
       
  1298 
       
  1299     CHAT_DP_FUNC_DONE( "CreateGroupL" );
       
  1300 
       
  1301     return exGrp->GroupId().AllocL(); // ownership is transferred
       
  1302     }
       
  1303 
       
  1304 // ---------------------------------------------------------
       
  1305 // CCAGroupManager::JoinGroupL
       
  1306 // We must wrap JoinL to make sure the properties are
       
  1307 // in place. It can't be done in wrapper as it will
       
  1308 // mess up the message sequences.
       
  1309 // ---------------------------------------------------------
       
  1310 //
       
  1311 TInt CCAGroupManager::JoinGroupL( const TDesC& aGroupId,
       
  1312                                   const TDesC& aScreenName, TBool aUsers,
       
  1313                                   TBool aIsFavourite, TBool aIsWhisperingEnabled )
       
  1314     {
       
  1315     CHAT_DP_FUNC_ENTER( "JoinGroupL" );
       
  1316 
       
  1317     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
  1318 
       
  1319     if ( ! wrapper )
       
  1320         {
       
  1321         // no wrapper, create one
       
  1322         // exists in a internal list, so no need to use cleanupstack
       
  1323         wrapper = CreateWrapperL( aGroupId );
       
  1324         }
       
  1325 
       
  1326     // check if we need to fetch the properties from the network
       
  1327     CImpsCommonGroupProps* commonProps = NULL;
       
  1328     CImpsPrivateGroupProps* privateProps = NULL;
       
  1329     wrapper->LocalProperties( commonProps, privateProps );
       
  1330     // ownership is kept in wrapper
       
  1331 
       
  1332     // now we can join the group
       
  1333     TInt joinStatus = KErrNone;
       
  1334     joinStatus = wrapper->JoinL( aScreenName, aUsers, aIsFavourite );
       
  1335     if ( joinStatus == EOperationCancelled)
       
  1336         {
       
  1337         return joinStatus;    
       
  1338         }
       
  1339     TInt retStatus( KErrNone );
       
  1340     if ( ( !commonProps ) || ( !privateProps ) )
       
  1341         {
       
  1342         // no properties, so request from network
       
  1343         // Store op id of properties request
       
  1344         iPropsOpIdWhileJoining = wrapper->OperationId() + 1;
       
  1345         retStatus = wrapper->GetPropertiesL( commonProps, privateProps );
       
  1346         if ( retStatus == EOperationCancelled)
       
  1347             {
       
  1348             return retStatus;
       
  1349             }
       
  1350         if ( retStatus != ECSPInsufficientGroupPrivileges )
       
  1351             {
       
  1352             if ( ( retStatus != ECSPSuccessful ) && ( retStatus != KErrNone ) )
       
  1353                 {
       
  1354                 // got some failure
       
  1355                 iPropsOpIdWhileJoining = KErrNotFound;  // Init to -1
       
  1356                 return retStatus;
       
  1357                 }
       
  1358 
       
  1359             // fail-safe for buggy server returning NULL to these for some reason
       
  1360             if ( ( ! commonProps ) || ( ! privateProps ) )
       
  1361                 {
       
  1362                 iPropsOpIdWhileJoining = KErrNotFound;  // Init to -1
       
  1363                 return ECSPInsufficientGroupPrivileges;
       
  1364                 }
       
  1365             }
       
  1366         }
       
  1367 
       
  1368     // Note! ChatData is created in HandleJoinL, but HandleJoinL
       
  1369     // is not called if we get 807 ECSPGroupAlreadyJoined. So we must work
       
  1370     // around to recover from that.
       
  1371 
       
  1372     if ( joinStatus == ECSPGroupAlreadyJoined )
       
  1373         {
       
  1374         // Make sure our status is in sync with server
       
  1375         // status, then we can recover from 807 ECSPGroupAlreadyJoined.
       
  1376         // If we get ECSPGroupAlreadyJoined, HandleJoinL is never called,
       
  1377         // but HandleErrorL (Engine) instead!
       
  1378 
       
  1379         // create the chat data, if we don't have it
       
  1380 
       
  1381         MCAMessagesWriteInterface& groupChat =
       
  1382             iChatInterface.MessageWriteInterfaceL(
       
  1383                 KNullDesC, KNullDesC, aGroupId,
       
  1384                 MCAMessagesReadInterface::EGroupContainer );
       
  1385         groupChat.SetScreenNameL( aScreenName );
       
  1386 
       
  1387         // make sure it's marked as joined in the UI
       
  1388         MCAExtendedStoredGroup& grp =
       
  1389             static_cast<MCAExtendedStoredGroup&>( wrapper->Group() );
       
  1390         if ( !grp.IsJoined() )
       
  1391             {
       
  1392             grp.SetJoined( ETrue );
       
  1393             iNumJoinedGroups++;
       
  1394             }
       
  1395         }
       
  1396 
       
  1397     // also update private properties to the group
       
  1398     if ( ( joinStatus == ECSPGroupAlreadyJoined )
       
  1399          || ( joinStatus == ECSPSuccessful )
       
  1400          || ( joinStatus == KErrNone ) )
       
  1401         {
       
  1402         if ( aIsWhisperingEnabled && privateProps )
       
  1403             {
       
  1404             joinStatus = SetPrivateAllowedL( *wrapper, *privateProps );
       
  1405             if ( joinStatus == EOperationCancelled )
       
  1406             	{
       
  1407             	return joinStatus;
       
  1408             	}
       
  1409             }
       
  1410         joinStatus = KErrNone;
       
  1411         }
       
  1412 
       
  1413     CHAT_DP_FUNC_DONE( "JoinGroupL" );
       
  1414 
       
  1415     return joinStatus;
       
  1416     }
       
  1417 
       
  1418 // ---------------------------------------------------------
       
  1419 // CCAGroupManager::LeaveJoinedGroups
       
  1420 // ---------------------------------------------------------
       
  1421 //
       
  1422 void CCAGroupManager::LeaveJoinedGroupsL()
       
  1423     {
       
  1424     TInt count = iGroupWrappers.Count();
       
  1425     for ( TInt i = count - 1; i >= 0; --i )
       
  1426         {
       
  1427         MCAStoredGroup& group = iGroupWrappers[ i ]->Group();
       
  1428         if ( group.IsJoined() )
       
  1429             {
       
  1430             iGroupWrappers[ i ]->LeaveL();
       
  1431             CleanupLeaveGroupL( group.GroupId() );
       
  1432             }
       
  1433         }
       
  1434     }
       
  1435 
       
  1436 // ---------------------------------------------------------
       
  1437 // CCAGroupManager::LeaveGroupL
       
  1438 // We must wrap LeaveL to make sure the UI and
       
  1439 // IMPS engine running in different threads do not
       
  1440 // cause race conditions when UI calls LeaveL directly
       
  1441 // and IMPS engine informs via HandleLeaveL.
       
  1442 // ---------------------------------------------------------
       
  1443 //
       
  1444 TInt CCAGroupManager::LeaveGroupL( const TDesC& aGroupId )
       
  1445     {
       
  1446     CHAT_DP_FUNC_ENTER( "LeaveGroupL" );
       
  1447 
       
  1448     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
  1449 
       
  1450     if ( ! wrapper )
       
  1451         {
       
  1452         // not Leaving with KErrNone due to popular request
       
  1453         return KErrNone;
       
  1454         }
       
  1455 
       
  1456     // leave the group
       
  1457     TInt retStatus = wrapper->LeaveL();
       
  1458 
       
  1459     // nuke the wrappers etc.
       
  1460     CleanupLeaveGroupL( aGroupId );
       
  1461 
       
  1462     CHAT_DP_FUNC_DONE( "LeaveGroupL" );
       
  1463     return retStatus;
       
  1464     }
       
  1465 
       
  1466 // ---------------------------------------------------------
       
  1467 // CCAGroupManager::GenerateGroupIdLC
       
  1468 // XXX cleaned up the forbidden char removal part,
       
  1469 // but can this be cleaned up any more?
       
  1470 // ---------------------------------------------------------
       
  1471 //
       
  1472 HBufC* CCAGroupManager::GenerateGroupIdLC( const TDesC& aResourcePart )
       
  1473     {
       
  1474 
       
  1475     HBufC* groupId = HBufC::NewLC( KMaxGroupIDLength );
       
  1476     TPtr groupIdPtr( groupId->Des() );
       
  1477 
       
  1478     // Retrieve logged user information
       
  1479     HBufC* loggedUserId = iSettingsAPI.ValueL( MCASettings::EOwnWVUserID );
       
  1480     CleanupStack::PushL( loggedUserId );
       
  1481 
       
  1482     // find "@"
       
  1483     TInt atIndex( loggedUserId->FindC( KAt ) );
       
  1484     if ( atIndex == KErrNotFound )
       
  1485         {
       
  1486         atIndex = loggedUserId->Length();
       
  1487         }
       
  1488 
       
  1489     // Find string between ":" and "@"
       
  1490     // If there is no "wv:" start from beginning of user id
       
  1491     TInt startPosition = 0;
       
  1492     if ( KWV().CompareC( loggedUserId->Left( KWV().Length() ),
       
  1493                          KCollationLevel, NULL ) == 0 )
       
  1494         {
       
  1495         startPosition = KWV().Length();
       
  1496         }
       
  1497 
       
  1498     TPtrC userBaseName( loggedUserId->Mid(
       
  1499                             startPosition, atIndex - startPosition ) );
       
  1500 
       
  1501     // We must get rid of the unneeded "@" characters
       
  1502     TPtrC groupBaseName;
       
  1503     HBufC* temp = CAUtils::GenerateIdLC( aResourcePart );
       
  1504     TPtr tempPtr( temp->Des() );
       
  1505 
       
  1506     // group name empty? If it is, use userBaseName after "/" in group id
       
  1507     if ( aResourcePart.Length() < 1 )
       
  1508         {
       
  1509         groupBaseName.Set( userBaseName );
       
  1510         }
       
  1511     else
       
  1512         {
       
  1513         // Sanity check. We removed characters, is there anything in the string?
       
  1514         if ( tempPtr.Length() < 1 )
       
  1515             {
       
  1516             groupBaseName.Set( userBaseName );
       
  1517             }
       
  1518         else
       
  1519             {
       
  1520             groupBaseName.Set( tempPtr );
       
  1521             }
       
  1522 
       
  1523         CHAT_DP( D_CHAT_LIT( "Group base name is %S" ), &groupBaseName );
       
  1524         }
       
  1525 
       
  1526     // Add "wv:" at the beginning
       
  1527     groupIdPtr.Copy( KWV );
       
  1528 
       
  1529     // Add "middle" part of WV user ID
       
  1530     //
       
  1531     // EXAMPLE 1:
       
  1532     // User id = wv:jari20@domain.com
       
  1533     // Group name = grouppi
       
  1534     // Group id becomes wv:jari20/grouppi
       
  1535     //
       
  1536     // EXAMPLE 2:
       
  1537     // User id = wv:jari20@domain.com
       
  1538     // Group name is empty
       
  1539     // Group id becomes wv:jari20/jari20
       
  1540 
       
  1541     groupIdPtr += userBaseName;
       
  1542 
       
  1543     // Add separator "/"
       
  1544     groupIdPtr += KResourceSeparator;
       
  1545 
       
  1546     TInt groupInsertIndex( groupIdPtr.Length() );
       
  1547 
       
  1548     // don't add ordinal the first time
       
  1549     if ( iGroupIdOrdinal > 0 )
       
  1550         {
       
  1551         // Format ordinal, 5 is enough
       
  1552         TBuf<5> ordinal;
       
  1553         ordinal.Num( iGroupIdOrdinal );
       
  1554         // Add ordinal
       
  1555         groupIdPtr += ordinal;
       
  1556         }
       
  1557 
       
  1558     // Add domain part
       
  1559     groupIdPtr += loggedUserId->Mid( atIndex );
       
  1560 
       
  1561     // Add groupId last so we can know how much it can be inserted.
       
  1562     groupIdPtr.Insert( groupInsertIndex,
       
  1563                        groupBaseName.Left(
       
  1564                            KMaxGroupIDLength - groupIdPtr.Length() ) );
       
  1565 
       
  1566     CleanupStack::PopAndDestroy( temp );
       
  1567     CleanupStack::PopAndDestroy( loggedUserId );
       
  1568 
       
  1569     // Increase ordinal
       
  1570     ++iGroupIdOrdinal;
       
  1571 
       
  1572     return groupId;
       
  1573     }
       
  1574 
       
  1575 
       
  1576 // ---------------------------------------------------------
       
  1577 // CCAGroupManager::DeleteGroupL
       
  1578 // ---------------------------------------------------------
       
  1579 //
       
  1580 TInt CCAGroupManager::DeleteGroupL( const TDesC& aGroupId,
       
  1581                                     TBool aDeleteFromNetwork )
       
  1582     {
       
  1583     CHAT_DP_FUNC_ENTER( "DeleteGroupL" );
       
  1584 
       
  1585     TBuf<KMaxGroupNameLength> groupid;
       
  1586     groupid.Copy( aGroupId.Left( groupid.MaxLength() ) );
       
  1587 
       
  1588     TInt retVal( KErrNone );
       
  1589     CCAGroupWrapper* wrapper = NULL;
       
  1590 
       
  1591     if ( aDeleteFromNetwork )
       
  1592         {
       
  1593         // delete from network
       
  1594 
       
  1595         wrapper = FindGroupWrapper( aGroupId );
       
  1596 
       
  1597         if ( ! wrapper )
       
  1598             {
       
  1599             // no wrapper, create one
       
  1600             wrapper = CreateWrapperL( aGroupId );   // CSI: 35 # Ownership is not transferred to caller.
       
  1601             }
       
  1602 
       
  1603         retVal = wrapper->DeleteFromNetworkL();
       
  1604         }
       
  1605     else
       
  1606         {
       
  1607         // deleting locally, see if we have a wrapper
       
  1608         wrapper = FindGroupWrapper( aGroupId );
       
  1609         }
       
  1610 
       
  1611     if ( wrapper )
       
  1612         {
       
  1613         // have wrapper, delete it
       
  1614         DeleteGroupWrapper( aGroupId );
       
  1615         }
       
  1616 
       
  1617     // delete from storage manager
       
  1618     CHAT_DP_FUNC_DP( "DeleteGroupL", "Deleting from storage" );
       
  1619 
       
  1620     MCAStoredGroup* group = iStoredGroups->FindGroup( aGroupId );
       
  1621 
       
  1622     if ( retVal == KErrNone || retVal == ECSPGroupDoesNotExist )
       
  1623         {
       
  1624         if ( group )
       
  1625             {
       
  1626             iStoredGroups->DeleteGroupL( group );
       
  1627             }
       
  1628         }
       
  1629 
       
  1630     // delete the chat data
       
  1631     RemoveChatDataL( groupid );
       
  1632     CHAT_DP_FUNC_DONE( "DeleteGroupL" );
       
  1633 
       
  1634     return retVal;
       
  1635     }
       
  1636 
       
  1637 // ---------------------------------------------------------
       
  1638 // CCAGroupManager::IsAllowedAccessL
       
  1639 // check access to given group
       
  1640 // ---------------------------------------------------------
       
  1641 //
       
  1642 TBool CCAGroupManager::IsAllowedAccessL( const TDesC& aGroupId,
       
  1643                                          const CDesCArray& aCheckUsers,
       
  1644                                          CDesCArray& aNotInList )
       
  1645     {
       
  1646     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
  1647     if ( !wrapper )
       
  1648         {
       
  1649         // This should never happen, but just in case...
       
  1650         CHAT_DP_TXT( "CCAGroupManager::IsAllowedAccessL - \
       
  1651                       wrapper doesn't exist" );
       
  1652         return EFalse;
       
  1653         }
       
  1654     MCAStoredGroup& group = wrapper->Group();
       
  1655 
       
  1656     aNotInList.Reset();
       
  1657 
       
  1658     // all users, including administrators
       
  1659     CDesCArray* allGroupUsers =
       
  1660         new ( ELeave ) CDesCArrayFlat( KJoinedMembersArrayGranularity );
       
  1661     CleanupStack::PushL( allGroupUsers );
       
  1662     group.GetMembersL( *allGroupUsers );
       
  1663 
       
  1664     TInt checkCount( aCheckUsers.Count() );
       
  1665     TInt position( 0 );
       
  1666 
       
  1667     if ( ! IsGroupOpenL( aGroupId ) )
       
  1668         {
       
  1669         // closed group, so check access
       
  1670 
       
  1671         CHAT_DP_TXT( "IsAllowedAccessL, checking for valid access" );
       
  1672         // Go through list of users to check and see if
       
  1673         // they're in the list of all users
       
  1674         for ( TInt i( 0 ); i < checkCount; ++i )
       
  1675             {
       
  1676             if ( allGroupUsers->Find( aCheckUsers[i], position, ECmpCollated ) )
       
  1677                 {
       
  1678                 aNotInList.AppendL( aCheckUsers[i] );
       
  1679                 }
       
  1680             }
       
  1681         }
       
  1682 
       
  1683     CImpsCommonGroupProps* commonProps = NULL;
       
  1684     CImpsPrivateGroupProps* privProps = NULL;
       
  1685     GetPropertiesL( aGroupId, commonProps, privProps );
       
  1686 
       
  1687     TBool isLoggedUserAdmin = group.IsAdmin();
       
  1688 
       
  1689     CleanupStack::PopAndDestroy( allGroupUsers );
       
  1690 
       
  1691     return isLoggedUserAdmin;
       
  1692     }
       
  1693 
       
  1694 // check if group is open or closed
       
  1695 TBool CCAGroupManager::IsGroupOpenL( const TDesC& aGroupId )
       
  1696     {
       
  1697     CImpsCommonGroupProps* commonProps = NULL;
       
  1698     CImpsPrivateGroupProps* privProps = NULL;
       
  1699     GetPropertiesL( aGroupId, commonProps, privProps );
       
  1700 
       
  1701     return commonProps->IsOpen();
       
  1702     }
       
  1703 
       
  1704 // map group id to group name
       
  1705 HBufC* CCAGroupManager::GroupNameL( const TDesC& aGroupId )
       
  1706     {
       
  1707     CImpsCommonGroupProps* commonProps = NULL;
       
  1708     CImpsPrivateGroupProps* privProps = NULL;
       
  1709     GetPropertiesL( aGroupId, commonProps, privProps );
       
  1710 
       
  1711     HBufC* buf = NULL;
       
  1712     if ( commonProps )
       
  1713         {
       
  1714         buf = commonProps->GroupName().AllocL();    // CSI: 35 # No leaving code after allocation, ownership transferred to caller.
       
  1715         }
       
  1716     else
       
  1717         {
       
  1718         // can't get group name from properties
       
  1719         // returning empty groupname
       
  1720         buf = KNullDesC().AllocL();
       
  1721         }
       
  1722 
       
  1723     return buf;
       
  1724     }
       
  1725 
       
  1726 // handles logout event
       
  1727 void CCAGroupManager::HandleNetworkStateChangeL( TNetworkState  aState )
       
  1728     {
       
  1729     if ( aState == ELoggedOut )
       
  1730         {
       
  1731         RPointerArray<MCAStoredGroup> groups;
       
  1732         CleanupClosePushL( groups );
       
  1733         iStoredGroups->PopulateGroupsListL( groups );
       
  1734 
       
  1735         // loop through all the groups
       
  1736         TInt count( groups.Count() );
       
  1737         for ( TInt i( 0 ); i < count; i++ )
       
  1738             {
       
  1739             MCAExtendedStoredGroup* exGrp =
       
  1740                 static_cast<MCAExtendedStoredGroup*>( groups[ i ] );
       
  1741             if ( exGrp->IsJoined() )
       
  1742                 {
       
  1743                 // the group is joined, so leave it and perform cleanup
       
  1744                 exGrp->SetJoined( EFalse );
       
  1745                 iNumJoinedGroups--;
       
  1746                 CleanupLeaveGroupL( exGrp->GroupId() );
       
  1747                 }
       
  1748             }
       
  1749         CleanupStack::PopAndDestroy(); // groups.Close()
       
  1750         }
       
  1751     }
       
  1752 
       
  1753 // ---------------------------------------------------------
       
  1754 // CCAGroupManager::LastImpsError
       
  1755 // ---------------------------------------------------------
       
  1756 //
       
  1757 void CCAGroupManager::LastImpsError( TInt aError )
       
  1758     {
       
  1759     iLastImpsError = aError;
       
  1760     }
       
  1761 
       
  1762 // used internally to find the proper group wrapper
       
  1763 CCAGroupWrapper* CCAGroupManager::FindGroupWrapper( TInt aOpId )
       
  1764     {
       
  1765     TInt count( iGroupWrappers.Count() );
       
  1766 
       
  1767     for ( TInt i( 0 ); i < count; i++ )
       
  1768         {
       
  1769         CCAGroupWrapper* wrapper = iGroupWrappers[i];
       
  1770         if ( aOpId == wrapper->OperationId() )
       
  1771             {
       
  1772             // found it
       
  1773             return wrapper;
       
  1774             }
       
  1775         }
       
  1776 
       
  1777     // didn't find it
       
  1778     return NULL;
       
  1779     }
       
  1780 
       
  1781 // used internally to find the proper group wrapper based on group id
       
  1782 CCAGroupWrapper* CCAGroupManager::FindGroupWrapper( const TDesC& aGroupId )
       
  1783     {
       
  1784     TInt count( iGroupWrappers.Count() );
       
  1785 
       
  1786     for ( TInt i( 0 ); i < count; i++ )
       
  1787         {
       
  1788         CCAGroupWrapper* wrapper = iGroupWrappers[i];
       
  1789 
       
  1790         // get the group the wrapper wraps
       
  1791         MCAStoredGroup& g = wrapper->Group();
       
  1792 
       
  1793         if ( 0 == CAUtils::NeutralCompare( g.GroupId(), aGroupId ) )
       
  1794             {
       
  1795             // found it
       
  1796             return wrapper;
       
  1797             }
       
  1798         }
       
  1799 
       
  1800     // didn't find it
       
  1801     return NULL;
       
  1802     }
       
  1803 
       
  1804 // used internally to delete the proper group wrapper based on group id
       
  1805 void CCAGroupManager::DeleteGroupWrapper( const TDesC& aGroupId )
       
  1806     {
       
  1807     CHAT_DP_FUNC_ENTER( "DeleteGroupWrapper" );
       
  1808 
       
  1809     TInt count( iGroupWrappers.Count() );
       
  1810 
       
  1811     for ( TInt i( 0 ); i < count; i++ )
       
  1812         {
       
  1813         CCAGroupWrapper* wrapper = iGroupWrappers[i];
       
  1814 
       
  1815         // get the group the wrapper wraps
       
  1816         MCAStoredGroup& g = wrapper->Group();
       
  1817 
       
  1818         if ( 0 == g.GroupId().CompareC( aGroupId, KCollationLevel, NULL ) )
       
  1819             {
       
  1820             CHAT_DP_FUNC_DP( "DeleteGroupWrapper", "Found wrapper, deleting it" );
       
  1821             // found it! delete it
       
  1822             iGroupWrappers.Remove( i );
       
  1823             delete wrapper;
       
  1824             iGroupWrappers.Compress();
       
  1825             return;
       
  1826             }
       
  1827         }
       
  1828 
       
  1829     // didn't find it
       
  1830     CHAT_DP_TXT( "CCAGroupManager::DeleteGroupWrapper tried to delete wrapper \
       
  1831                   that doesn't exist!" );
       
  1832 
       
  1833     CHAT_DP_FUNC_DONE( "DeleteGroupWrapper" );
       
  1834     }
       
  1835 
       
  1836 // get properties for the given group
       
  1837 void CCAGroupManager::GetPropertiesL( const TDesC& aGroupId,
       
  1838                                       CImpsCommonGroupProps*& aCommonProps,
       
  1839                                       CImpsPrivateGroupProps*& aPrivProps )
       
  1840     {
       
  1841     CHAT_DP_FUNC_ENTER( "PropertiesL" );
       
  1842 
       
  1843     TBool tempGroup( EFalse );
       
  1844     MCAStoredGroup* group = iStoredGroups->FindGroup( aGroupId );
       
  1845     if ( !group )
       
  1846         {
       
  1847         group = iStoredGroups->CreateGroupL();  // CSI: 35 # Ownership is not transferred to caller.
       
  1848         static_cast<MCAExtendedStoredGroup*>( group )->SetGroupIdL( aGroupId );
       
  1849         static_cast<MCAExtendedStoredGroup*>( group )->SetVisible( EFalse );
       
  1850         tempGroup = ETrue;
       
  1851         }
       
  1852 
       
  1853     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
  1854     if ( ! wrapper )
       
  1855         {
       
  1856         wrapper = CreateWrapperL( aGroupId );   // CSI: 35 # Ownership is not transferred to caller.
       
  1857         }
       
  1858 
       
  1859     // ownership does not get transferred
       
  1860     wrapper->GetPropertiesL( aCommonProps, aPrivProps );
       
  1861 
       
  1862     if ( tempGroup )
       
  1863         {
       
  1864         DeleteGroupL( aGroupId, EFalse );
       
  1865         }
       
  1866 
       
  1867     CHAT_DP_FUNC_DONE( "PropertiesL" );
       
  1868     }
       
  1869 
       
  1870 // create a group wrapper
       
  1871 CCAGroupWrapper* CCAGroupManager::CreateWrapperL( const TDesC& aGroupId )
       
  1872     {
       
  1873     CHAT_DP_FUNC_ENTER( "CreateWrapperL" );
       
  1874 
       
  1875     // wrapper needs a group
       
  1876     MCAStoredGroup* group = iStoredGroups->FindGroup( aGroupId );
       
  1877     if ( !group )
       
  1878         {
       
  1879         // no such group at all
       
  1880         CHAT_DP_FUNC_DP( "CreateWrapperL", "No group!!" );
       
  1881         User::Leave( KErrNotFound );
       
  1882         }
       
  1883 
       
  1884     CHAT_DP_FUNC_DP( "CreateWrapperL", "Found group" );
       
  1885 
       
  1886     // create a new wrapper
       
  1887     CHAT_DP_FUNC_DP( "CreateWrapperL", "Creating group wrapper" );
       
  1888 
       
  1889     CCAGroupWrapper* groupWrapper = CCAGroupWrapper::NewL( iSettingsAPI,
       
  1890                                                            static_cast<MCAExtendedStoredGroup&>( *group ), iRequestMapper,
       
  1891                                                            iImpsFactory->CreateGroupClientL() );
       
  1892     CleanupStack::PushL( groupWrapper );
       
  1893 
       
  1894     // ownership transferred to array
       
  1895     TInt retVal( iGroupWrappers.Append( groupWrapper ) );
       
  1896 
       
  1897     User::LeaveIfError( retVal );
       
  1898     CleanupStack::Pop( groupWrapper );
       
  1899 
       
  1900     CHAT_DP_FUNC_DONE( "CreateWrapperL" );
       
  1901 
       
  1902     // that's it
       
  1903     return groupWrapper;
       
  1904     }
       
  1905 
       
  1906 // set the private messaging to allowed
       
  1907 TInt CCAGroupManager::SetPrivateAllowedL( CCAGroupWrapper& aWrapper,
       
  1908                                           CImpsPrivateGroupProps& aPrivProps )
       
  1909     {
       
  1910     aPrivProps.SetPrivateAllowed( EImpsPropYes );
       
  1911     // the return value of updateproperties can be ignored because
       
  1912     // there's no point showing "server error" note if the joining
       
  1913     // process was otherwise successful.
       
  1914     TInt operationvalue = aWrapper.UpdatePropertiesL( NULL, &aPrivProps );
       
  1915     
       
  1916     return operationvalue;
       
  1917     }
       
  1918 
       
  1919 // remove the given chat data
       
  1920 void CCAGroupManager::RemoveChatDataL( const TDesC& aGroupId )
       
  1921     {
       
  1922     CHAT_DP_FUNC_ENTER( "RemoveChatDataL" );
       
  1923     iChatInterface.DeleteChatL( KNullDesC, KNullDesC, aGroupId );
       
  1924     CHAT_DP_FUNC_DONE( "RemoveChatDataL" );
       
  1925     }
       
  1926 
       
  1927 // ---------------------------------------------------------
       
  1928 // CCAGroupManager::WriteWelcomeMessageL
       
  1929 // ---------------------------------------------------------
       
  1930 //
       
  1931 void CCAGroupManager::WriteWelcomeMessageL(
       
  1932     const TDesC& aWelcomeMessage,
       
  1933     const TDesC& aGroup,
       
  1934     const TDesC& aTopic,
       
  1935     MCAMessagesWriteInterface& aMessages )
       
  1936     {
       
  1937     // I can't figure out a situation in which these would require a
       
  1938     // datestamp. But if that is the case at some point, use
       
  1939     // CAMessageUtil::AppendMessageWithDateStampL for appending.
       
  1940 
       
  1941     // show customized welcome message
       
  1942     if ( aWelcomeMessage.Length() > 0 )
       
  1943         {
       
  1944         aMessages.AppendL(
       
  1945             iMessageUtils.MessageCreator().CreateSystemMessageL(
       
  1946                 MCAMessage::ESystemMessageWelcome, aWelcomeMessage ) );
       
  1947         }
       
  1948     // show default welcome message
       
  1949     else
       
  1950         {
       
  1951         HBufC* welcome =
       
  1952             StringLoader::LoadLC( R_SYSTEM_MESSAGE_WELCOME_TEXT, aGroup );
       
  1953 
       
  1954         aMessages.AppendL(
       
  1955             iMessageUtils.MessageCreator().CreateSystemMessageL(
       
  1956                 MCAMessage::ESystemMessageWelcome, *welcome ) );
       
  1957 
       
  1958         CleanupStack::PopAndDestroy( welcome );
       
  1959         }
       
  1960 
       
  1961     // Only show real topic
       
  1962     if ( aTopic.Length() > 0 )
       
  1963         {
       
  1964         // load & show default topic string
       
  1965         HBufC* topicText =
       
  1966             StringLoader::LoadLC( R_SYSTEM_MESSAGE_TOPIC_TEXT, aTopic );
       
  1967         aMessages.AppendL(
       
  1968             iMessageUtils.MessageCreator().CreateSystemMessageL(
       
  1969                 MCAMessage::ESystemMessageWelcome, *topicText ) );
       
  1970         CleanupStack::PopAndDestroy( topicText );
       
  1971         }
       
  1972     }
       
  1973 // ---------------------------------------------------------
       
  1974 // CCAGroupManager::CancelGroupOperationL
       
  1975 // ---------------------------------------------------------
       
  1976 //
       
  1977 void CCAGroupManager::CancelGroupOperationL( const TDesC& aGroupId )
       
  1978     {
       
  1979     CCAGroupWrapper* wrapper = FindGroupWrapper( aGroupId );
       
  1980     if ( !wrapper )
       
  1981         {
       
  1982         return;
       
  1983         }
       
  1984    CCARequest* request = wrapper->Request();
       
  1985        if ( request )
       
  1986         {
       
  1987         request->StopWaitIfNeeded(); 
       
  1988         request->SetErrorCode( EOperationCancelled );   
       
  1989         }   
       
  1990     }
       
  1991 //  End of File