ximpfw/presence/srcpresencedatamodel/presentitygroups/grouplistsubscriptionitem.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:54:49 +0200
changeset 0 e6b17d312c8b
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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 list subscription implementation.
*
*/


#include <badesca.h>

#include "grouplistsubscriptionitem.h"
#include "presenceinfofilterimp.h"
#include "ximpitemparent.h"
#include "ximppanics.h"
#include "ximppsccontext.h"
#include "documentutils.h"
#include "presentitygrouplisteventimp.h"
#include "presencetypehelpers.h"
#include "presentitygroupinfoimp.h"
//#include "ximpapieventbase.h"

#include "ximptrace.h"
// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::CGroupListSubscriptionItem()
// ---------------------------------------------------------------------------
//
CGroupListSubscriptionItem::CGroupListSubscriptionItem( MXIMPItemParentBase& aParent )
: CXIMPSubscriptionItemBase( aParent )
    {
    }


// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::ConstructL()
// ---------------------------------------------------------------------------
//
void CGroupListSubscriptionItem::ConstructL()
    {
    BaseConstructL();
    // empty lists must always exist
    iCurrentList = new ( ELeave) RPrGrpInfoImpArray;

    iCreated = new ( ELeave ) RPrGrpInfoImpArray;
    iUpdated = new ( ELeave ) RPrGrpInfoImpArray;
    iDeleted = new ( ELeave ) RPrGrpInfoImpArray;
    }


// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::NewL()
// ---------------------------------------------------------------------------
//
CGroupListSubscriptionItem* CGroupListSubscriptionItem::NewLC( MXIMPItemParentBase& aParent )
    {
    CGroupListSubscriptionItem* self = new( ELeave ) CGroupListSubscriptionItem( aParent );
    CleanupClosePushL( *self );
    self->ConstructL();
    return self;
    }


// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::~CGroupListSubscriptionItem()
// ---------------------------------------------------------------------------
//
CGroupListSubscriptionItem::~CGroupListSubscriptionItem()
    {
        MXIMPItemParent* presCache = static_cast<MXIMPItemParent*>(iParent.GetInterface(PRESENCE_ITEM_PARENT));
    presCache->RemoveMe( this );

    if( iCurrentList )
        {
        iCurrentList->Close();
        }
    delete iCurrentList;

    Clean();
    // just in case
    delete iCreated;
    delete iDeleted;
    delete iUpdated;
    }

// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::SynthesiseSubscriptionEventTo()
// ---------------------------------------------------------------------------
//
void CGroupListSubscriptionItem::SynthesiseSubscriptionEventToL(
        MXIMPPscContext* aContext, TBool aForceEvent )
    {
    TRACE_1( _L("CGroupListSubscriptionItem::SynthesiseSubscriptionEventTo() aForce=%d"), aForceEvent );
    CXIMPDataSubscriptionStateImp* status = StatusLC( aContext );

    if( status->DataState() == MXIMPDataSubscriptionState::EDataAvailable || aForceEvent )
        {
        CPresentityGroupListEventImp* newEvent = CPresentityGroupListEventImp::NewL(
                iCreated,
                iUpdated,
                iDeleted,
                aForceEvent ? iCurrentList : 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.
    }


// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::SetNewListL
// ---------------------------------------------------------------------------
//
EXPORT_C void CGroupListSubscriptionItem::SetNewListL(
        RPrGrpInfoImpArray* aGroupList )
    {
    TRACE_1( _L("CGroupListSubscriptionItem::SetNewListL() aGroupList Count=%d"), aGroupList->Count() );
    // we will eventually take ownership to this
    RPrGrpInfoImpArray* tmp = aGroupList;
    CleanupDeletePushL( 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):
    //   - aGroupList length M
    //   - iCurrentList 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 iDeleted and iCurrentList
    //     = 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<CPresentityGroupInfoImp>
        linearOrder( CPresentityGroupInfoImp::GroupIdLinearOrder );

    for ( TInt i = 0; i < tmp->Count(); i++ )
        {
        // compare against current list
        CPresentityGroupInfoImp* info = (*tmp)[ i ];
        TInt pos = iCurrentList->FindInOrder( info, linearOrder );

        if ( pos == KErrNotFound )
            {
            // not found in current list
            // so must be a fresh created list name
            iCreated->InsertInOrderL( info, linearOrder );
            }
        else
            {
            // found in current list, so it must be an updated list name
            iUpdated->InsertInOrderL( info, linearOrder );

            delete (*iCurrentList)[ pos ];
            iCurrentList->Remove( pos );

            // we must remove the found ones from iCurrentList,
            // otherwise we will not know what was left. and finding out
            // the deleted items will be difficult.
            }
        }

    // what's left in iCurrentList contains the deleted ones.
    delete iDeleted;
    iDeleted = iCurrentList;

    // the given list becomes the new list
    iCurrentList = tmp;
    CleanupStack::Pop( tmp );
    iSubscriptionState->SetDataStateL( MXIMPDataSubscriptionState::EDataAvailable );
    }

// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::SetCreatedListL
// ---------------------------------------------------------------------------
//
EXPORT_C void CGroupListSubscriptionItem::SetCreatedListL(
        RPrGrpInfoImpArray* aGroupList )
    {
    TRACE_1( _L("CGroupListSubscriptionItem::SetCreatedListL() aGroupList Count=%d"), aGroupList->Count() );
    // we took ownership to the given list
    RPrGrpInfoImpArray* tmp = aGroupList;
    CleanupDeletePushL( tmp );

    // see also SetNewListL.

    // the list is already sorted. when a copy was made in datacacheimp, the
    // InsertInOrder method was used
    TLinearOrder<CPresentityGroupInfoImp>
        linearOrder( CPresentityGroupInfoImp::GroupIdLinearOrder );

    // update the list of created and updated groups
    for ( TInt i = 0; i < tmp->Count(); i++ )
        {
        // compare against current list
        CPresentityGroupInfoImp* info = (*tmp)[ i ];
        TInt pos = iCurrentList->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.
            iCurrentList->InsertInOrderL( info, linearOrder );
            ( *tmp )[ i ] = NULL;
            iCreated->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
            (*iCurrentList)[ pos ]->SetGroupDisplayNameL( info->GroupDisplayName() );

            // found in current list, so it must be an updated list name
            iUpdated->InsertInOrderL( (*iCurrentList)[ 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 );
    }

// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::SetDeletedListL
// ---------------------------------------------------------------------------
//
EXPORT_C void CGroupListSubscriptionItem::SetDeletedListL(
        RPrGrpInfoImpArray* aGroupList )
    {
    TRACE_1( _L("CGroupListSubscriptionItem::SetDeletedListL() aGroupList Count=%d"), aGroupList->Count() );
    // we will eventually take ownership to this
    RPrGrpInfoImpArray* tmp = aGroupList;
    CleanupDeletePushL( tmp );

    // see also SetNewListL.

    // the list is already sorted. when a copy was made in datacacheimp, the
    // InsertInOrder method was used
    TLinearOrder<CPresentityGroupInfoImp>
        linearOrder( CPresentityGroupInfoImp::GroupIdLinearOrder );

    // remove the deleted ones from the current list
    for ( TInt i = 0; i < tmp->Count(); i++ )
        {
        // compare against current list
        CPresentityGroupInfoImp* info = (*tmp)[ i ];
        TInt pos = iCurrentList->FindInOrder( info, linearOrder );

        // found in current list, so it must be a deleted list name
        if ( pos != KErrNotFound )
            {
            // remove from current list
            delete (*iCurrentList)[ pos ];
            iCurrentList->Remove( pos );
            }
        }

    // the given list becomes the new list of
    // deleted ones
    delete iDeleted;
    iDeleted = tmp;
    CleanupStack::Pop( tmp );
    iSubscriptionState->SetDataStateL( MXIMPDataSubscriptionState::EDataAvailable );
    }

// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::Clean
// ---------------------------------------------------------------------------
//
EXPORT_C void CGroupListSubscriptionItem::Clean()
    {
    TRACE( _L("CGroupListSubscriptionItem::Clean()") );
    // empty the lists.
    // the lists must stay valid for use

    // iCreated and iUpdated are collection from currentlist. Do not delete items.
    // iDeleted is only place for items. Delete those.

    iCreated->Reset();
    iUpdated->Reset();
    iDeleted->Close();
    }

// ---------------------------------------------------------------------------
// CGroupListSubscriptionItem::CleanExpired()
// ---------------------------------------------------------------------------
//
void CGroupListSubscriptionItem::CleanExpired()
    {

    }
// End of file