ncdengine/provider/client/src/ncdsubscriptionmanagerproxy.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/client/src/ncdsubscriptionmanagerproxy.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,570 @@
+/*
+* 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:   Contains CNcdSubscriptionManagerProxy class implementation
+*
+*/
+
+
+#include "ncdsubscriptionmanagerproxy.h"
+#include "ncdsubscriptiongroupproxy.h"
+#include "ncdsubscriptionproxy.h"
+#include "ncdsubscriptionoperationproxy.h"
+#include "ncdoperationimpl.h"
+#include "ncddownloadoperationproxy.h"
+#include "ncdoperationmanagerproxy.h"
+#include "ncdoperationdatatypes.h"
+#include "catalogsclientserver.h"
+#include "ncdnodeidentifier.h"
+#include "ncdnodefunctionids.h"
+#include "ncdnodeclassids.h"
+#include "catalogsinterfaceidentifier.h"
+#include "catalogsutils.h"
+#include "ncdutils.h"
+#include "catalogsconstants.h"
+#include "ncdsubscriptionmanagerlistener.h"
+
+#include "catalogsdebug.h"
+
+// ======== PUBLIC MEMBER FUNCTIONS ========
+
+CNcdSubscriptionManagerProxy::CNcdSubscriptionManagerProxy(
+    MCatalogsClientServer& aSession,
+    TInt aHandle,
+    CCatalogsInterfaceBase* aParent,
+    CNcdOperationManagerProxy& aOperationManager )
+    : CNcdInterfaceBaseProxy( aSession, aHandle, aParent ),
+      iOperationManager( aOperationManager )
+    {
+    }
+
+
+void CNcdSubscriptionManagerProxy::ConstructL()
+    {
+    DLTRACEIN((""));
+    
+    // Register the interface
+    MNcdSubscriptionManager* interface( this );
+    AddInterfaceL( CCatalogsInterfaceIdentifier::NewL( 
+                        interface, this,
+                        MNcdSubscriptionManager::KInterfaceUid ) );
+                        
+    // Create listener.
+    iListener = CNcdSubscriptionManagerListener::NewL( *this );
+    
+    iInputBuf.CreateL( 1 );
+    iOutputBuf.CreateL( 1 );
+    
+    
+    // Is it ok if internalization fails here?
+    // Earlier comment: Do not let the internalization leave here.
+    //                  This object may be reinternalized later.
+    InternalizeL();
+    
+    // Send an asynchronous message to server side subscription manager to be notified
+    // when subscription states are changed in server side.
+    ClientServerSession().SendAsync(
+        NcdNodeFunctionIds::ENcdListenerEnrollment,
+        iOutputBuf,
+        iInputBuf,
+        Handle(),
+        iListener->iStatus );
+            
+    iListener->Activate();
+        
+    DLTRACEOUT((""));
+    }
+
+
+CNcdSubscriptionManagerProxy* CNcdSubscriptionManagerProxy::NewL(
+    MCatalogsClientServer& aSession,
+    TInt aHandle,
+    CCatalogsInterfaceBase* aParent,
+    CNcdOperationManagerProxy& aOperationManager )
+    {
+    CNcdSubscriptionManagerProxy* self = 
+        CNcdSubscriptionManagerProxy::NewLC( aSession,
+                                             aHandle,
+                                             aParent,
+                                             aOperationManager );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+CNcdSubscriptionManagerProxy* CNcdSubscriptionManagerProxy::NewLC(
+    MCatalogsClientServer& aSession,
+    TInt aHandle,
+    CCatalogsInterfaceBase* aParent,
+    CNcdOperationManagerProxy& aOperationManager )
+    {
+    CNcdSubscriptionManagerProxy* self = 
+        new( ELeave ) CNcdSubscriptionManagerProxy( aSession,
+                                                    aHandle,
+                                                    aParent,
+                                                    aOperationManager );
+    // Using PushL because the object does not have any references yet
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+CNcdSubscriptionManagerProxy::~CNcdSubscriptionManagerProxy()
+    {
+    // Remove interfaces implemented by this class from the interface list.
+    // So, the interface list is up to date when this class object is deleted.
+    RemoveInterface( MNcdSubscriptionManager::KInterfaceUid );
+    
+    iSubscriptionGroups.ResetAndDestroy();
+    
+    delete iListener;
+    iInputBuf.Close();
+    iOutputBuf.Close();
+    }
+
+
+void CNcdSubscriptionManagerProxy::SetNodeManager(
+    CNcdNodeManagerProxy* aManager )
+    {
+    // Not owned so no deletion needed for possible previous object
+    iNodeManager = aManager;
+    }
+
+void CNcdSubscriptionManagerProxy::InternalizeL()
+    {
+    DLTRACEIN((""));
+    
+    // Request the subscription group identifiers from server.
+    RPointerArray<CNcdKeyValuePair> groupIds = SubscriptionGroupIdentifiersL();    
+    CleanupResetAndDestroyPushL( groupIds );
+    
+    DLINFO(("Amount of ids received: %d", groupIds.Count() ));
+    
+    // Release the subscription groups that don't exist in server side.
+    DeleteMissingSubscriptionGroups( groupIds );
+    
+    // Reinternalize existing subscriptiongroup.
+    InternalizeSubscriptionGroupsL();
+    
+    // Remove the subscription groups from the array which are up to date currently.
+    for ( TInt i = groupIds.Count() - 1; i >= 0; i-- ) 
+        {
+        if ( SubscriptionGroup( groupIds[i]->Value(), groupIds[i]->Key() ) != NULL ) 
+            {
+            delete groupIds[i];
+            groupIds.Remove( i );
+            }
+        }
+               
+    // Request handles to the new subscription groups
+    CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
+    CleanupStack::PushL( buf );
+    
+    RBufWriteStream writeStream( *buf );
+    CleanupClosePushL( writeStream );
+    
+    writeStream.WriteInt32L( groupIds.Count() );
+    for ( TInt i = 0; i < groupIds.Count(); i++ ) 
+        {
+        groupIds[i]->ExternalizeL( writeStream );
+        }
+        
+    CleanupStack::PopAndDestroy( &writeStream );
+            
+    
+    HBufC8* dataToSend = HBufC8::NewL( buf->Size() );
+    dataToSend->Des().Copy( buf->Ptr( 0 ) );
+    CleanupStack::PopAndDestroy( buf );
+    CleanupStack::PushL( dataToSend );
+
+    HBufC8* data( NULL );
+    
+    DLINFO(("Request buffer: %S", dataToSend ));
+        
+    // Because we do not know the exact size of the data, use
+    // the alloc method, which creates the buffer of the right size
+    // and sets the pointer to point to the created buffer.
+    // Get all the data that is necessary to internalize this object
+    // from the server side.
+    User::LeaveIfError(
+        ClientServerSession().
+        SendSyncAlloc( NcdNodeFunctionIds::ENcdInternalize,
+                       *dataToSend,
+                       data,
+                       Handle(),
+                       0 ) );
+
+    if ( data == NULL )
+        {
+        DLERROR((""));
+        User::Leave(  KErrNotFound );
+        }
+        
+    CleanupStack::PopAndDestroy( dataToSend );
+    CleanupStack::PushL( data );
+
+    // Read the data from the stream and insert it to the memeber variables
+    RDesReadStream stream( *data );
+    CleanupClosePushL( stream );
+    
+    TRAPD( internalizeError, InternalizeDataL( stream ) );
+    if ( internalizeError != KErrNone )
+        {
+        // Should check that no handles are left to the
+        // stream. If there are, release messages should
+        // be sent to the server side with those handles.
+        iSubscriptionGroups.ResetAndDestroy();
+        User::Leave( internalizeError );
+        }
+    
+    // Closes the stream
+    CleanupStack::PopAndDestroy( &stream ); 
+    CleanupStack::PopAndDestroy( data );
+    CleanupStack::PopAndDestroy( &groupIds );
+
+    DLTRACEOUT((""));    
+    }
+
+
+TBool CNcdSubscriptionManagerProxy::ActiveSubscriptionExists(
+    const TDesC& aEntityId,
+    const TDesC& aNamespace,
+    const TDesC& aPurchaseOptionId )
+    {
+    DLTRACEIN((""));
+    CNcdSubscriptionProxy* searchedSubscription( NULL );
+    searchedSubscription = Subscription( aEntityId,
+                                         aNamespace,
+                                         aPurchaseOptionId );
+
+    if ( searchedSubscription != NULL )
+        {
+        if ( searchedSubscription->SubscriptionStatus() ==
+                 MNcdSubscription::ESubscriptionActive )
+            {
+            DLTRACEOUT(("Return ETrue"));
+            return ETrue;
+            }
+        }    
+    DLTRACEOUT(("Return EFalse"));
+    return EFalse;
+    }
+
+CNcdSubscriptionProxy* CNcdSubscriptionManagerProxy::Subscription(
+    const TDesC& aEntityId,
+    const TDesC& aNamespace,
+    const TDesC& aPurchaseOptionId )
+    {
+    DLTRACEIN((""));    
+    CNcdSubscriptionProxy* resultSubscription( NULL );
+    
+    // First find the subscription group...
+    CNcdSubscriptionGroupProxy* group( NULL );
+    group = SubscriptionGroup( aEntityId, aNamespace );
+    
+    if ( group != NULL )
+        {        
+        // then subscription...
+        resultSubscription = group->Subscription( aPurchaseOptionId );
+        }
+    
+    DLTRACEOUT((""));
+    return resultSubscription;
+    }
+
+void CNcdSubscriptionManagerProxy::SubscriptionsChangedL() 
+    {
+    DLTRACEIN((""));
+    
+    // Send new listener enrollment message to server side.
+    ClientServerSession().SendAsync(
+        NcdNodeFunctionIds::ENcdListenerEnrollment,
+        iOutputBuf,
+        iInputBuf,
+        Handle(),
+        iListener->iStatus );
+    iListener->Activate();
+        
+    // Internalize the data from server.
+    InternalizeL();
+    }
+        
+
+
+// MNcdSubscriptionManager functions
+    
+
+
+// ---------------------------------------------------------------------------
+// Subscriptions are now under subscription groups so they are not
+// kept in one large array.
+// Benefit from the one large array would be that the returning of
+// all subscriptions in this function would be easy but because
+// the array would have to be updated or remade after every
+// update from server (which is always before this function) it seems
+// that keeping up the large array does not benefit us. Atleast
+// not in this function.
+// ---------------------------------------------------------------------------
+//
+RCatalogsArray<MNcdSubscription> 
+    CNcdSubscriptionManagerProxy::SubscriptionsL() const
+    {
+    DLTRACEIN(( "" ));
+    
+    // When ui asks for subscriptions it does it in the
+    // management view so the ui should update the subscriptions
+    // from the server before this function. Update is not done here.
+
+    // Let's make one array out of the subscriptions
+    RCatalogsArray<MNcdSubscription> subscriptions;
+    
+    // in case of leave, destroy its contents (release)
+    CleanupResetAndDestroyPushL( subscriptions );
+
+    
+    TInt groupCount( iSubscriptionGroups.Count() );
+    TInt groupIndexer( 0 );
+    
+    DLINFO(( "Coming to while" ));
+    while ( groupIndexer < groupCount )
+        {
+        // through all groups
+        const RPointerArray<CNcdSubscriptionProxy>& subscriptionsOfGroup
+            = iSubscriptionGroups[groupIndexer]->Subscriptions();
+        
+        TInt subscriptionCount( subscriptionsOfGroup.Count() );
+        TInt subscriptionIndexer( 0 );
+        
+        DLINFO(( "Coming to while2" ));
+        while ( subscriptionIndexer < subscriptionCount )
+            {
+            // through all subscriptions of group
+            subscriptions.AppendL(
+                subscriptionsOfGroup[subscriptionIndexer] );
+            subscriptionsOfGroup[subscriptionIndexer]->AddRef();        
+            ++subscriptionIndexer;
+            }
+        
+        ++groupIndexer;
+        }
+    CleanupStack::Pop( &subscriptions );
+    
+    DLTRACEOUT(( "" ));
+    return subscriptions;
+    }
+
+
+MNcdSubscriptionOperation* 
+    CNcdSubscriptionManagerProxy::RefreshSubscriptionsL(
+        MNcdSubscriptionOperationObserver& aObserver )
+    {
+    DLTRACEIN((""));
+
+    CNcdSubscriptionOperationProxy* operation( NULL );
+
+    operation =
+        iOperationManager.CreateSubscriptionRefreshOperationL( aObserver );
+
+    DLTRACEOUT((""));
+
+    return operation;
+    }
+
+
+
+// Other functions
+
+CNcdOperationManagerProxy&
+    CNcdSubscriptionManagerProxy::OperationManager() const
+    {
+    return iOperationManager;
+    }
+
+
+
+void CNcdSubscriptionManagerProxy::InternalizeDataL( RReadStream& aStream )
+    {
+    DLTRACEIN((""));    
+
+    TInt handleAmount( 0 );
+    handleAmount = aStream.ReadInt32L();
+    
+    DLTRACE(( "Amount of subscriptiongroup handles received: %d",
+              handleAmount ));
+
+    TInt tmpProxyHandle( -1 ); // handle of a proxy read from stream
+    
+    // temporary pointer to subscription group that is going to be
+    // added to subscriptiongroups-array
+    CNcdSubscriptionGroupProxy* tmpSubscriptionGroup( NULL );
+    
+
+    // In error handling, objects with received handles
+    // should be released from the server side session
+    // if proxies for them cannot be created.
+
+    TInt handleIndex( 0 );
+    while ( handleIndex < handleAmount )
+        {
+        tmpProxyHandle = aStream.ReadInt32L();
+        
+        DLTRACE(( "Received subscriptiongroup handle: %i",
+                  tmpProxyHandle ));
+                      
+        tmpSubscriptionGroup = CNcdSubscriptionGroupProxy::NewL( 
+                                ClientServerSession(),
+                                tmpProxyHandle,
+                                OperationManager(),
+                                *iNodeManager );                
+
+        TRAPD( addError, iSubscriptionGroups.AppendL( tmpSubscriptionGroup ) );
+        if ( addError != KErrNone )
+            {
+            delete tmpSubscriptionGroup;
+            User::Leave( addError );
+            }
+
+        ++handleIndex;
+        }
+
+    DLTRACEOUT((""));
+    }
+
+RPointerArray<CNcdKeyValuePair> CNcdSubscriptionManagerProxy::SubscriptionGroupIdentifiersL() const 
+    {
+    DLTRACEIN((""));
+    
+    HBufC8* data( NULL );
+
+    // Because we do not know the exact size of the data, use
+    // the alloc method, which creates the buffer of the right size
+    // and sets the pointer to point to the created buffer.
+    User::LeaveIfError(
+        ClientServerSession().
+        SendSyncAlloc( NcdNodeFunctionIds::ENcdSubscriptionGroupIdentifiers,
+                       KNullDesC8,
+                       data,
+                       Handle(),
+                       0 ) );
+
+    if ( data == NULL )
+        {
+        DLERROR((""));
+        User::Leave(  KErrNotFound );
+        }
+        
+    CleanupStack::PushL( data );
+
+    // Read the data from the stream and insert it to the memeber variables
+    RDesReadStream stream( *data );
+    CleanupClosePushL( stream );
+     
+    TInt32 identifierCount = stream.ReadInt32L();
+    RPointerArray<CNcdKeyValuePair> identifiers;
+    CleanupResetAndDestroyPushL( identifiers );
+    identifiers.ReserveL( identifierCount );
+    for ( TInt i = 0 ; i < identifierCount; i++ ) 
+        {
+        CNcdKeyValuePair* pair = CNcdKeyValuePair::NewL( stream );
+        TInt err = identifiers.Append( pair );
+        // Error should not be possible since there should be enough room to append.
+        DASSERT( err == KErrNone );
+        }
+        
+    CleanupStack::Pop( &identifiers );
+    CleanupStack::PopAndDestroy( &stream );
+    CleanupStack::PopAndDestroy( data );
+     
+    return identifiers;
+    }
+    
+void CNcdSubscriptionManagerProxy::DeleteMissingSubscriptionGroups(
+    const RPointerArray<CNcdKeyValuePair>& aGroupIdentifiers ) 
+    {
+    DLTRACEIN((""));
+    
+    for ( TInt i = iSubscriptionGroups.Count() - 1; i >= 0; i-- ) 
+        {
+        const TDesC& nameSpace = iSubscriptionGroups[i]->Namespace();
+        const TDesC& entityId = iSubscriptionGroups[i]->EntityId();
+        
+        TBool found = EFalse;
+        for ( TInt idIndexer = 0; idIndexer < aGroupIdentifiers.Count(); idIndexer++ ) 
+            {
+            if ( aGroupIdentifiers[idIndexer]->Key() == nameSpace &&
+                 aGroupIdentifiers[idIndexer]->Value() == entityId ) 
+                {
+                found = ETrue;
+                break;
+                }
+            }
+        
+        if ( !found ) 
+            {
+            delete iSubscriptionGroups[i];
+            iSubscriptionGroups.Remove( i );
+            }            
+        }
+    }        
+    
+void CNcdSubscriptionManagerProxy::InternalizeSubscriptionGroupsL() const 
+    {
+    DLTRACEIN((""));
+    for ( TInt i = 0; i < iSubscriptionGroups.Count(); i++ ) 
+        {
+        iSubscriptionGroups[i]->InternalizeL();
+        }
+    }
+
+CNcdSubscriptionGroupProxy* CNcdSubscriptionManagerProxy::SubscriptionGroup(
+    const TDesC& aEntityId,
+    const TDesC& aNamespace )
+    {
+    DLTRACEIN((""));
+    // Search for the subscription group
+
+    TInt groupCount( iSubscriptionGroups.Count() );
+    TInt groupIndexer( 0 );
+    while ( groupIndexer < groupCount )
+        {        
+        const TDesC& groupsEntityId =
+            iSubscriptionGroups[groupIndexer]->EntityId();
+        const TDesC& groupsNamespace =
+            iSubscriptionGroups[groupIndexer]->Namespace();
+
+        DLINFO(( _L("Searched entityid: %S, now entityid: %S"),
+                 &aEntityId,
+                 &groupsEntityId ));        
+        
+        if ( aEntityId == groupsEntityId )
+            {
+
+            DLINFO(( _L("Searched namespace: %S, now namespace: %S"),
+                     &aNamespace,
+                     &groupsNamespace ));
+                 
+            if ( aNamespace == groupsNamespace )
+                {
+                DLTRACEOUT(("Found."));
+                return iSubscriptionGroups[groupIndexer];
+                }
+            
+            }
+        
+        ++groupIndexer;
+        }
+
+    DLTRACEOUT(("Not found."));
+    return NULL;
+    }
+