ximpfw/presence/srcpresencedatamodel/presentitygroups/groupcontentsubscriptionitem.cpp
changeset 51 61fad867f68e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ximpfw/presence/srcpresencedatamodel/presentitygroups/groupcontentsubscriptionitem.cpp	Wed Nov 03 09:32:20 2010 +0530
@@ -0,0 +1,545 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Presence Service Connection group member subscription implementation.
+*
+*/
+
+
+#include <badesca.h>
+
+#include "groupcontentsubscriptionitem.h"
+#include "presenceinfofilterimp.h"
+#include "ximpitemparent.h"
+#include "ximppanics.h"
+#include "ximppsccontext.h"
+#include "documentutils.h"
+#include "presentitygroupcontenteventimp.h"
+#include "presencetypehelpers.h"
+#include "ximpobjecthelpers.h"
+#include "presentitygroupmemberinfoimp.h"
+#include "ximpidentityimp.h"
+#include "groupcontenteventobserver.h"
+
+#include "ximptrace.h"
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::CGroupContentSubscriptionItem()
+// ---------------------------------------------------------------------------
+//
+CGroupContentSubscriptionItem::CGroupContentSubscriptionItem( MXIMPItemParentBase& aParent )
+: CXIMPSubscriptionItemBase( aParent )
+    {
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::ConstructL( const CXIMPIdentityImp& aGroupId )
+    {
+    BaseConstructL();
+    
+    iGroupId = TXIMPObjectCloner< CXIMPIdentityImp >::CloneL( aGroupId );
+
+    // empty lists must always exist
+    iCurrentMembers = new ( ELeave) RPrGrpMemInfoImpArray;
+
+    iAdded = new ( ELeave ) RPrGrpMemInfoImpArray;
+    iUpdated = new ( ELeave ) RPrGrpMemInfoImpArray;
+    iRemoved = new ( ELeave ) RPrGrpMemInfoImpArray;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::NewLC()
+// ---------------------------------------------------------------------------
+//
+CGroupContentSubscriptionItem*
+        CGroupContentSubscriptionItem::NewLC( MXIMPItemParentBase& aParent,
+                                                     const CXIMPIdentityImp& aGroupId )
+    {
+    CGroupContentSubscriptionItem* self =
+                new( ELeave ) CGroupContentSubscriptionItem( aParent );
+    CleanupClosePushL( *self );
+    self->ConstructL( aGroupId );
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::~CGroupContentSubscriptionItem()
+// ---------------------------------------------------------------------------
+//
+CGroupContentSubscriptionItem::~CGroupContentSubscriptionItem()
+    {
+        MXIMPItemParent* presCache = static_cast<MXIMPItemParent*>(iParent.GetInterface(PRESENCE_ITEM_PARENT));
+    presCache->RemoveMe( this );
+
+
+    if ( iCurrentMembers )
+        {
+        iCurrentMembers->Close();
+        }
+    delete iCurrentMembers;
+
+    Clean();
+    delete iAdded;
+    delete iUpdated;
+    delete iRemoved;
+
+    delete iGroupId;
+
+    iEventObservers.Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::AddOrRenewSubscriberL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CGroupContentSubscriptionItem::AddOrRenewSubscriberL(
+        MXIMPPscContext* aContext )
+    {
+    TInt index = iContexts.Find( aContext );
+    if( index == KErrNotFound )
+        {
+        iContexts.AppendL( aContext );
+        User::LeaveIfError( Open() );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::GroupId()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C const CXIMPIdentityImp& CGroupContentSubscriptionItem::GroupId() const
+    {
+    return *iGroupId;
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::Order()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CGroupContentSubscriptionItem::Order(
+                        const CGroupContentSubscriptionItem& aA,
+                        const CGroupContentSubscriptionItem& aB )
+    {
+    return IdentityOrder( aA.iGroupId, aB );
+    }
+// ---------------------------------------------------------------------------
+// CPresentityPresenceSubscriptionItem::Order()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CGroupContentSubscriptionItem::IdentityOrder(
+                        const CXIMPIdentityImp* aA,
+                        const CGroupContentSubscriptionItem& aB )
+    {
+    return aA->Compare( *aB.iGroupId );
+    }
+
+// ---------------------------------------------------------------------------
+// From MXIMPSubscriptionItem class.
+// CGroupContentSubscriptionItem::SynthesiseSubscriptionEventTo()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToL(
+        MXIMPPscContext* aContext, TBool aForceEvent )
+    {
+    TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventTo() aForce=%d"), aForceEvent );
+    CXIMPDataSubscriptionStateImp* status = StatusLC( aContext );
+
+    if( status->DataState() == MXIMPDataSubscriptionState::EDataAvailable || aForceEvent )
+        {
+        CPresentityGroupContentEventImp* newEvent =
+            CPresentityGroupContentEventImp::NewL( *iGroupId,
+                    iAdded,
+                    iUpdated,
+                    iRemoved,
+                    aForceEvent ? iCurrentMembers : NULL,
+                    status
+                    );
+        CleanupStack::Pop(); //status
+        CleanupStack::PushL( newEvent );
+        MXIMPItemParent* presCache = static_cast<MXIMPItemParent*>(iParent.GetInterface(PRESENCE_ITEM_PARENT));
+        presCache->AddEventL( *newEvent, aContext );
+        }        
+    CleanupStack::PopAndDestroy(); // status || newEvent. Depending on branch.
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL()
+{
+
+TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL() iEventObservers.Count()=%d"), iEventObservers.Count() );
+TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL() iAdded->Count()=%d"), iAdded->Count() );
+TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL() iUpdated->Count()=%d"), iUpdated->Count() );
+TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL() iRemoved->Count()=%d"), iRemoved->Count() );
+
+    TInt count = iEventObservers.Count();
+    if( count && iAdded->Count() )
+    {
+        for( TInt a = 0; a < count; ++a )
+        {
+        TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL() observer = iEventObservers[ a ] =%d"), a );
+            MGroupContentEventObserver* observer = iEventObservers[ a ];
+        TInt error ( KErrNone );
+        TRAP( error, observer->HandleSynthesiseL( *iAdded ););
+        TRACE_1( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL()  TRAPD( error, observer->HandleSynthesiseL =%d"), error );
+        }
+    }
+
+  TRACE( _L("CGroupContentSubscriptionItem::SynthesiseSubscriptionEventToAllCtxsL - Call to CXIMPSubscriptionItemBase::SynthesiseSubscriptionEventToAllCtxsL Now ") );
+    CXIMPSubscriptionItemBase::SynthesiseSubscriptionEventToAllCtxsL();
+}
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::SetNewListL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CGroupContentSubscriptionItem::SetNewListL(
+        RPrGrpMemInfoImpArray* aMemberList )
+    {
+    TRACE_1( _L("CGroupContentSubscriptionItem::SetNewListL() aMemberList Count=%d"), aMemberList->Count() );
+    // we will eventually take ownership to this
+    RPrGrpMemInfoImpArray* tmp = aMemberList;
+    CleanupStack::PushL( tmp );
+
+    // the list is already sorted. when a copy was made in datacacheimp, the
+    // InsertInOrder method was used
+
+    // The below algorithm has complexity of (roughly):
+    //   - aMemberList length M
+    //   - iCurrentMembers final length N
+    //
+    //   Final complexity:
+    //     M*(    1     // indexed accessor
+    //          + logN  // find (ordered)
+    //          + logN  // insert in order (find+insert)
+    //          + O(1)  // delete
+    //          + O(1)  // remove
+    //        ) + O(1)  // updating iRemoved and iCurrentMembers
+    //     = M(2logN+3) + 2MlogN+3M = O(cMlogM).
+    //
+    // Should be fast enough. The complexity is not fully accurate because
+    // array size grows as we insert into it.
+    //
+    TLinearOrder<CPresentityGroupMemberInfoImp>
+        linearOrder( CPresentityGroupMemberInfoImp::GroupIdLinearOrder );
+
+    for ( TInt i = 0; i < tmp->Count(); i++ )
+        {
+        // compare against current list
+        CPresentityGroupMemberInfoImp* info = (*tmp)[ i ];
+        TInt pos = iCurrentMembers->FindInOrder( info, linearOrder );
+
+        if ( pos == KErrNotFound )
+            {
+            // not found in current list
+            // so must be a fresh created list name
+            iAdded->InsertInOrderL( info, linearOrder );
+            }
+        else
+            {
+            // found in current list, so it must be an updated list name
+            iUpdated->InsertInOrderL( info, linearOrder );
+
+            delete (*iCurrentMembers)[ pos ];
+            iCurrentMembers->Remove( pos );
+
+            // we must remove the found ones from iCurrentMembers,
+            // otherwise we will not know what was left. and finding out
+            // the removed items will be difficult.
+            }
+        }
+
+    // what's left in iCurrentMembers contains the deleted ones.
+    delete iRemoved;
+    iRemoved = iCurrentMembers;
+
+    // the given list becomes the new list
+    iCurrentMembers = tmp;
+    CleanupStack::Pop( tmp );
+    iSubscriptionState->SetDataStateL( MXIMPDataSubscriptionState::EDataAvailable );
+    InformObserversL();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::SetAddedListL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CGroupContentSubscriptionItem::SetAddedListL(
+        RPrGrpMemInfoImpArray* aMemberList )
+    {
+    TRACE_1( _L("CGroupContentSubscriptionItem::SetAddedListL() aMemberList Count=%d"), aMemberList->Count() );
+    // we took ownership to the given list
+    RPrGrpMemInfoImpArray* tmp = aMemberList;
+    CleanupDeletePushL( tmp );
+
+    // see also SetNewListL.
+
+    // the list is already sorted. when a copy was made in datacacheimp, the
+    // InsertInOrder method was used
+    TLinearOrder<CPresentityGroupMemberInfoImp>
+        linearOrder( CPresentityGroupMemberInfoImp::GroupIdLinearOrder );
+
+    // update the list of created and updated groups
+    for ( TInt i = 0; i < tmp->Count(); i++ )
+        {
+        // compare against current list
+        CPresentityGroupMemberInfoImp* info = (*tmp)[ i ];
+        TInt pos = iCurrentMembers->FindInOrder( info, linearOrder );
+
+        if ( pos == KErrNotFound )
+            {
+            // not found in current list
+            // so must be a fresh created list name.
+            // this cannot come when the HandleDisplayNameUpdatedListL method
+            // is called.
+            iCurrentMembers->InsertInOrderL( info, linearOrder );
+            ( *tmp )[ i ] = NULL;
+            iAdded->InsertInOrderL( info, linearOrder );
+            }
+        else
+            {
+            // This can be checked if really had changed if needed. Now
+            // we trust server that changes are reasonable.
+            
+            // change the display name of the updated group in the current list
+            (*iCurrentMembers)[ pos ]->SetGroupMemberDisplayNameL( info->GroupMemberDisplayName() );
+
+            // found in current list, so it must be an updated list name
+            iUpdated->InsertInOrderL( (*iCurrentMembers)[ pos ], linearOrder );
+            }
+        }
+
+    // current list may get updated display name to the existing elements,
+    // otherwise the list is unchanged. list of deleted groups stays empty.
+    // updated and created lists were updated. the input parameter list can be
+    // deleted
+    CleanupStack::PopAndDestroy( tmp );
+    iSubscriptionState->SetDataStateL( MXIMPDataSubscriptionState::EDataAvailable );
+
+    InformObserversL();
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::SetRemovedListL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CGroupContentSubscriptionItem::SetRemovedListL(
+        RPrGrpMemInfoImpArray* aMemberList )
+    {
+    TRACE_1( _L("CGroupContentSubscriptionItem::SetRemovedListL() aMemberList Count=%d"), aMemberList->Count() );
+    // we will eventually take ownership to this
+    RPrGrpMemInfoImpArray* tmp = aMemberList;
+    CleanupStack::PushL( tmp );
+
+    // see also SetNewListL.
+
+    // the list is already sorted. when a copy was made in datacacheimp, the
+    // InsertInOrder method was used
+    TLinearOrder<CPresentityGroupMemberInfoImp>
+        linearOrder( CPresentityGroupMemberInfoImp::GroupIdLinearOrder );
+
+    // remove the deleted ones from the current list
+    for ( TInt i = 0; i < tmp->Count(); i++ )
+        {
+        // compare against current list
+        CPresentityGroupMemberInfoImp* info = (*tmp)[ i ];
+        TInt pos = iCurrentMembers->FindInOrder( info, linearOrder );
+
+        // found in current list, so it must be a deleted list name
+        if ( pos != KErrNotFound )
+            {
+            // remove from current list
+            delete (*iCurrentMembers)[ pos ];
+            iCurrentMembers->Remove( pos );
+            }
+        }
+
+    // the given list becomes the new list of
+    // removed ones
+    delete iRemoved;
+    iRemoved = tmp;
+    CleanupStack::Pop( tmp );
+    iSubscriptionState->SetDataStateL( MXIMPDataSubscriptionState::EDataAvailable );
+    InformObserversL();
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::Clean()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CGroupContentSubscriptionItem::Clean()
+    {
+    TRACE( _L("CGroupContentSubscriptionItem::Clean") );
+    // empty the lists.
+    // the lists must stay valid for use
+
+    // iAdded and iUpdated are collection from currentlist. Do not delete items.
+    // iRemoved is only place for items. Delete those.
+
+    iAdded->Reset();
+    iUpdated->Reset();
+    iRemoved->Close();
+    }
+
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::GroupMemberExistsL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TBool CGroupContentSubscriptionItem::GroupMemberExistsL(
+                            CPresentityGroupMemberInfoImp& aMemberInfo ) const
+    {
+    TBool found( EFalse );
+
+    CPresentityGroupMemberInfoImp* memberInfo =
+        TXIMPObjectCloner< CPresentityGroupMemberInfoImp >::CloneL( aMemberInfo );
+    CleanupStack::PushL( memberInfo );
+
+
+    TLinearOrder<CPresentityGroupMemberInfoImp>
+        linearOrder( CPresentityGroupMemberInfoImp::GroupIdLinearOrder );
+    TInt pos = iCurrentMembers->FindInOrder( memberInfo, linearOrder );
+    if ( pos != KErrNotFound )
+        {
+        found = ETrue;
+        }
+
+    CleanupStack::PopAndDestroy( memberInfo );
+    TRACE_1( _L("CGroupContentSubscriptionItem::GroupMemberExistsL() returns=%d"), found );
+    return found;
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::IsGroupMemberUpdatedL()
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TBool CGroupContentSubscriptionItem::IsGroupMemberUpdatedL(
+                            CPresentityGroupMemberInfoImp& aMemberInfo ) const
+    {
+    TBool updated( EFalse );
+
+    if ( !GroupMemberExistsL( aMemberInfo ) )
+        {
+        return updated;
+        }
+
+    CPresentityGroupMemberInfoImp* memberInfo =
+        TXIMPObjectCloner< CPresentityGroupMemberInfoImp >::CloneL( aMemberInfo );
+    CleanupStack::PushL( memberInfo );
+
+
+    TLinearOrder<CPresentityGroupMemberInfoImp>
+        linearOrder( CPresentityGroupMemberInfoImp::GroupIdLinearOrder );
+    TInt pos = iCurrentMembers->FindInOrder( memberInfo, linearOrder );
+    // it exists, otherwise we would've returned after GroupMemberExistsL call
+
+    CPresentityGroupMemberInfoImp* foundMember = (*iCurrentMembers)[ pos ];
+    // Compare identity and displayname
+    if ( memberInfo->GroupMemberId().Identity().Compare(
+                            foundMember->GroupMemberId().Identity() ) != 0
+                            ||
+         memberInfo->GroupMemberDisplayName().Compare(
+                            foundMember->GroupMemberDisplayName() ) != 0 )
+        {
+        updated = ETrue;
+        }
+
+    CleanupStack::PopAndDestroy( memberInfo );
+    TRACE_1( _L("CGroupContentSubscriptionItem::IsGroupMemberUpdatedL() returns=%d"), updated );
+    return updated;
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::MemberCount()
+// ---------------------------------------------------------------------------
+//
+TInt CGroupContentSubscriptionItem::MemberCount() const
+    {
+    TRACE_1( _L("CGroupContentSubscriptionItem::MemberCount() returns=%d"), iCurrentMembers->Count() );
+    return iCurrentMembers->Count();
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::MemberAt()
+// ---------------------------------------------------------------------------
+//
+CPresentityGroupMemberInfoImp& CGroupContentSubscriptionItem::MemberAt( TInt aIndex )
+    {
+    return *( *iCurrentMembers )[ aIndex ];
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::RegisterEventObserverL()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::RegisterEventObserverL(
+                        MGroupContentEventObserver* aEventObserver )
+    {
+    TInt indexOfObserver = iEventObservers.Find( aEventObserver );
+    if( indexOfObserver == KErrNotFound )
+        {
+        iEventObservers.AppendL( aEventObserver );
+        User::LeaveIfError( Open() );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::UnregisterEventObserver()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::UnregisterEventObserver(
+                        MGroupContentEventObserver* aEventObserver )
+    {
+    TInt indexOfObserver = iEventObservers.Find( aEventObserver );
+    if( indexOfObserver != KErrNotFound )
+        {
+        iEventObservers.Remove( indexOfObserver );
+        Close();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::CleanExpired()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::CleanExpired()
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CGroupContentSubscriptionItem::InformObserversL()
+// ---------------------------------------------------------------------------
+//
+void CGroupContentSubscriptionItem::InformObserversL()
+    {
+    TInt count = iEventObservers.Count();
+    if( count && ( iAdded->Count() || iRemoved->Count() ) )
+        {
+        for( TInt a = 0; a < count; ++a )
+            {
+            MGroupContentEventObserver* observer = iEventObservers[ a ];
+            observer->HandleChangeL( *iAdded, *iRemoved );
+            }
+        }
+    }
+
+// End of file