ncdengine/provider/client/src/ncdnodepurchaseproxy.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006 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:  
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <e32base.h>
       
    20 
       
    21 #include "ncdnodepurchaseproxy.h"
       
    22 
       
    23 #include "ncdpurchaseoptionproxy.h"
       
    24 #include "ncdpurchaseoperationproxy.h"
       
    25 #include "ncdsubscriptionmanagerproxy.h"
       
    26 #include "ncdclientpartofsubscription.h"
       
    27 #include "ncdclientsubscribablecontent.h"
       
    28 #include "ncdnodemanagerproxy.h"
       
    29 
       
    30 #include "ncdnodeproxy.h"
       
    31 #include "ncdnodemetadataproxy.h"
       
    32 #include "ncdoperationmanagerproxy.h"
       
    33 #include "ncdoperationimpl.h"
       
    34 #include "catalogsclientserver.h"
       
    35 #include "ncdnodeidentifier.h"
       
    36 #include "ncdnodefunctionids.h"
       
    37 #include "ncdnodeclassids.h"
       
    38 #include "catalogsinterfaceidentifier.h"
       
    39 #include "catalogsutils.h"
       
    40 #include "catalogsdebug.h"
       
    41 #include "catalogsconstants.h"
       
    42 #include "ncderrors.h"
       
    43 
       
    44 
       
    45 // ======== MEMBER FUNCTIONS ========
       
    46 
       
    47 
       
    48 CNcdNodePurchaseProxy::CNcdNodePurchaseProxy(
       
    49     MCatalogsClientServer& aSession,
       
    50     TInt aHandle,
       
    51     CNcdNodeMetadataProxy& aMetadata )
       
    52     : CNcdInterfaceBaseProxy( aSession, aHandle, &aMetadata ),
       
    53       iMetadata( aMetadata )
       
    54     {
       
    55     // This would be faster in the construct list but because
       
    56     // resetting is needed also elsewhere it is better to keep
       
    57     // the reset values only in one place.
       
    58     ResetHistoryData();
       
    59     }
       
    60 
       
    61 void CNcdNodePurchaseProxy::ConstructL()
       
    62     {
       
    63     DLTRACEIN((""));
       
    64     
       
    65     // Register the interface
       
    66     MNcdNodePurchase* purchase( this );
       
    67     AddInterfaceL( CCatalogsInterfaceIdentifier::NewL(
       
    68                         purchase,
       
    69                         this,
       
    70                         MNcdNodePurchase::KInterfaceUid ) );
       
    71     // Try to internalize already here. And if it fails,
       
    72     // then let it leave.
       
    73     InternalizeL();
       
    74 
       
    75     DLTRACEOUT(("Success. Options: %d", iPurchaseOptions.Count()));
       
    76     }
       
    77 
       
    78 
       
    79 CNcdNodePurchaseProxy* CNcdNodePurchaseProxy::NewL( 
       
    80     MCatalogsClientServer& aSession,
       
    81     TInt aHandle,
       
    82     CNcdNodeMetadataProxy& aMetadata )
       
    83     {
       
    84     CNcdNodePurchaseProxy* self = 
       
    85         CNcdNodePurchaseProxy::NewLC( aSession,
       
    86                                       aHandle,
       
    87                                       aMetadata );
       
    88     CleanupStack::Pop( self );
       
    89     return self;
       
    90     }
       
    91 
       
    92 
       
    93 CNcdNodePurchaseProxy* CNcdNodePurchaseProxy::NewLC( 
       
    94     MCatalogsClientServer& aSession,
       
    95     TInt aHandle,
       
    96     CNcdNodeMetadataProxy& aMetadata )
       
    97     {
       
    98     CNcdNodePurchaseProxy* self =
       
    99         new( ELeave ) CNcdNodePurchaseProxy( aSession,
       
   100                                              aHandle,
       
   101                                              aMetadata );
       
   102     // Using PushL because the object does not have any references yet
       
   103     CleanupStack::PushL( self );
       
   104     self->ConstructL();
       
   105     return self;
       
   106     }
       
   107 
       
   108 
       
   109 CNcdNodePurchaseProxy::~CNcdNodePurchaseProxy()
       
   110     {
       
   111     DLTRACEIN((""));
       
   112     // Remove interfaces implemented by this class from the interface list.
       
   113     // So, the interface list is up to date when this class object is deleted.
       
   114     RemoveInterface( MNcdNodePurchase::KInterfaceUid );
       
   115 
       
   116     delete iSubscribableContent;
       
   117     iSubscribableContent = NULL;
       
   118 
       
   119     // When purchase is destroyed, also purchaseoptions go
       
   120     // with it if no references are left to them.
       
   121     DeletePurchaseOptions();
       
   122     
       
   123     ResetHistoryData();
       
   124 
       
   125     DLTRACEOUT((""));
       
   126     }
       
   127 
       
   128 void CNcdNodePurchaseProxy::InternalizeL()
       
   129     {
       
   130     DLTRACEIN((""));    
       
   131     
       
   132     TRAPD( error,
       
   133            {
       
   134            InternalizeMeansL();
       
   135            InternalizeHistoryL();
       
   136            } );
       
   137     if ( error != KErrNone )
       
   138         {
       
   139         DLERROR(("Purchase internalize error"));
       
   140         // Because we can't fully construct the purchase info,
       
   141         // we don't give even parts of info to the user because it could
       
   142         // be misleading.
       
   143         DeletePurchaseOptions();
       
   144         ResetHistoryData();
       
   145         User::Leave( error );
       
   146         }
       
   147     DLTRACEOUT((""));    
       
   148     }
       
   149 
       
   150 
       
   151 void CNcdNodePurchaseProxy::InternalizeMeansL()
       
   152     {
       
   153     DLTRACEIN((""));
       
   154 
       
   155     // Request the purchase option ids from server side
       
   156     CDesCArray* poIds = RequestPurchaseOptionIdsL();
       
   157     CleanupStack::PushL( poIds );
       
   158     
       
   159     // Delete purchase options that don't exist in server side.
       
   160     ReleaseMissingPurchaseOptions( *poIds );
       
   161 
       
   162     // Reinternalize purchase options that existed already.
       
   163     InternalizeExistingPurchaseOptionsL();
       
   164     
       
   165     // Create purchase options that exists in the server side but not
       
   166     // in proxy side.
       
   167     CDesCArray* newPurchaseOptions = new( ELeave ) CDesCArrayFlat( 5 );
       
   168     CleanupStack::PushL( newPurchaseOptions );
       
   169     
       
   170     // Find the purchase options that don't exist in the proxy side.
       
   171     for ( TInt i = 0; i < poIds->Count(); i++ ) 
       
   172         {
       
   173         TPtrC id = (*poIds)[i];
       
   174         if ( !HasPurchaseOption( id ) ) 
       
   175             {
       
   176             newPurchaseOptions->AppendL( id );
       
   177             }
       
   178         }
       
   179 
       
   180     InternalizeMeansL( *newPurchaseOptions );
       
   181     CleanupStack::PopAndDestroy( newPurchaseOptions );
       
   182     newPurchaseOptions = NULL;
       
   183     CleanupStack::PopAndDestroy( poIds );
       
   184     poIds = NULL;
       
   185 
       
   186     DLTRACEOUT((""));    
       
   187     }
       
   188 
       
   189 
       
   190 void CNcdNodePurchaseProxy::InternalizeHistoryL()
       
   191     {
       
   192     DLTRACEIN((""));
       
   193 
       
   194     HBufC8* data( NULL );
       
   195         
       
   196     // Because we do not know the exact size of the data id, use
       
   197     // the alloc method, which creates the buffer of the right size
       
   198     // and sets the pointer to point to the created buffer.
       
   199     User::LeaveIfError(
       
   200             ClientServerSession().
       
   201                 SendSyncAlloc( NcdNodeFunctionIds::ENcdInternalizePurchaseHistory,
       
   202                                KNullDesC8,
       
   203                                data,
       
   204                                Metadata().Handle(),
       
   205                                0 ) );
       
   206 
       
   207     if ( data == NULL )
       
   208         {
       
   209         User::Leave( KErrNotFound );
       
   210         }
       
   211 
       
   212     CleanupStack::PushL( data );
       
   213 
       
   214 
       
   215     // Read the data from the stream
       
   216     RDesReadStream stream( *data );
       
   217     CleanupClosePushL( stream );
       
   218     
       
   219     TRAPD( error, InternalizeHistoryDataL( stream ) );
       
   220     if ( error != KErrNone )
       
   221         {
       
   222         User::Leave( error );
       
   223         }
       
   224         
       
   225     // Closes the stream
       
   226     CleanupStack::PopAndDestroy( &stream ); 
       
   227     CleanupStack::PopAndDestroy( data );
       
   228     
       
   229     DLTRACEOUT((""));    
       
   230     }
       
   231 
       
   232 CNcdNodeMetadataProxy& CNcdNodePurchaseProxy::Metadata() const
       
   233     {
       
   234     return iMetadata;
       
   235     }
       
   236 
       
   237 const CNcdClientSubscribableContent*
       
   238     CNcdNodePurchaseProxy::SubscribableContent() const
       
   239     {
       
   240     DLTRACEIN((""));
       
   241     DLTRACEOUT((""));
       
   242     return iSubscribableContent;    
       
   243     }
       
   244 
       
   245 
       
   246 
       
   247 // ---------------------------------------------------------------------------
       
   248 // From class MNcdNodePurchase.
       
   249 // In this function we return purchaseoptions to ui that are available for
       
   250 // the client at the moment.
       
   251 // ---------------------------------------------------------------------------
       
   252 //
       
   253 RCatalogsArray<MNcdPurchaseOption>
       
   254     CNcdNodePurchaseProxy::PurchaseOptionsL() const
       
   255     {
       
   256     DLTRACEIN(( "" ));
       
   257     
       
   258     RCatalogsArray<MNcdPurchaseOption> options;
       
   259     
       
   260     // in case of leave, destroy its contents (release)
       
   261     CleanupResetAndDestroyPushL( options );
       
   262 
       
   263     
       
   264     TInt optionsCount( iPurchaseOptions.Count() );
       
   265     TInt optionsIndexer( 0 );
       
   266     while ( optionsIndexer < optionsCount )
       
   267         {
       
   268         DASSERT( iPurchaseOptions[optionsIndexer] );
       
   269 
       
   270         // Purchaseoption that we handle at the moment        
       
   271         CNcdPurchaseOptionProxy* purchaseOption =
       
   272             iPurchaseOptions[optionsIndexer];
       
   273             
       
   274         // Type of the purchaseoption
       
   275         MNcdPurchaseOption::TType purchaseoptionType =
       
   276             purchaseOption->PurchaseOptionType();
       
   277             
       
   278         // dataentity to whome the purchaseoption belongs to
       
   279         CNcdNodeMetadataProxy& meta =
       
   280             purchaseOption->ParentNodePurchase()->Metadata();
       
   281 
       
   282         
       
   283 
       
   284         // NOTICE: At the moment this function does not take into count
       
   285         //         situations where purchaseoption could be of several
       
   286         //         types like ESubscription and ESubscriptionPurchase
       
   287         
       
   288 
       
   289         // Can purchase of the item be done if it is already 
       
   290         // purchased?
       
   291 
       
   292 
       
   293         if ( purchaseoptionType == MNcdPurchaseOption::EPurchase )
       
   294             {
       
   295 
       
   296             // Should check if parentfolder has separately purchaseable
       
   297             // false and if it has then do not show normal purchase
       
   298             // purchaseoptions to ui
       
   299 
       
   300             options.AppendL( purchaseOption );        
       
   301             TInt ref = purchaseOption->AddRef();            
       
   302             DLTRACE(("Purchase option ref count after addref: %d", ref));
       
   303             }
       
   304         else if ( purchaseoptionType == 
       
   305                       MNcdPurchaseOption::ESubscriptionPurchase )
       
   306             {
       
   307             // Part of subscription -type purchaseoptions are
       
   308             // always shown to ui
       
   309             options.AppendL( purchaseOption );        
       
   310             purchaseOption->AddRef(); 
       
   311             }
       
   312         else if ( purchaseoptionType ==
       
   313                       MNcdPurchaseOption::ESubscription )
       
   314             {
       
   315             // If this subscription is already bought, we can't show
       
   316             // it to ui.
       
   317             
       
   318             TBool isBought = 
       
   319                 Metadata().Node().NodeManager().
       
   320                 SubscriptionManager().
       
   321                 ActiveSubscriptionExists( meta.Id(),
       
   322                                           meta.Namespace(),
       
   323                                           purchaseOption->Id() );
       
   324 
       
   325             if ( !isBought )
       
   326                 {
       
   327                 options.AppendL( purchaseOption );        
       
   328                 purchaseOption->AddRef();
       
   329                 }
       
   330             }
       
   331         else if ( purchaseoptionType ==
       
   332                       MNcdPurchaseOption::ESubscriptionUpgrade )
       
   333             {
       
   334             // If target of the purchaseoption is not bought, upgrade
       
   335             // cannot be used
       
   336             if ( purchaseOption->IsUsableL() )
       
   337                 {
       
   338                 options.AppendL( purchaseOption );        
       
   339                 purchaseOption->AddRef();
       
   340                 }
       
   341             }
       
   342         else
       
   343             {
       
   344             // Not supported
       
   345             DASSERT( false );
       
   346             }
       
   347             
       
   348         ++optionsIndexer;
       
   349         }
       
   350         
       
   351     
       
   352     CleanupStack::Pop( &options );
       
   353     
       
   354     DLTRACEOUT(( "" ));
       
   355     return options;
       
   356     }
       
   357 
       
   358 // ---------------------------------------------------------------------------
       
   359 // From class MNcdNodePurchase.
       
   360 // ?implementation_description
       
   361 // ---------------------------------------------------------------------------
       
   362 //
       
   363 MNcdPurchaseOption* CNcdNodePurchaseProxy::PurchaseOptionL(
       
   364     const TDesC& aPurchaseOptionId ) const
       
   365     {
       
   366     DLTRACEIN((""));
       
   367     TInt optionsCount( iPurchaseOptions.Count() );
       
   368     TInt optionsIndexer( 0 );
       
   369     while ( optionsIndexer < optionsCount )
       
   370         {
       
   371         DASSERT( iPurchaseOptions[optionsIndexer] );
       
   372         
       
   373         if ( iPurchaseOptions[optionsIndexer]->Id() == aPurchaseOptionId )
       
   374             {
       
   375             iPurchaseOptions[optionsIndexer]->AddRef();
       
   376             
       
   377             DLTRACEOUT(( "" ));
       
   378             return iPurchaseOptions[optionsIndexer];
       
   379             }
       
   380         
       
   381         ++optionsIndexer;
       
   382         }
       
   383     
       
   384     DLTRACEOUT(( "" ));
       
   385     return NULL;
       
   386     }
       
   387 
       
   388 
       
   389 // ---------------------------------------------------------------------------
       
   390 // From class MNcdNodePurchase.
       
   391 // Notice that this function accepts purchase options also from other nodes
       
   392 // than into which this interface belongs to. Could be changed to accept
       
   393 // only purchase options from this interface, but at the moment UI
       
   394 // does not permit this in case of subscription.
       
   395 // ---------------------------------------------------------------------------
       
   396 //
       
   397 MNcdPurchaseOperation* CNcdNodePurchaseProxy::PurchaseL(
       
   398         MNcdPurchaseOption& aPurchaseOption,
       
   399         MNcdPurchaseOperationObserver& aObserver )
       
   400     {
       
   401     DLTRACEIN((""));
       
   402 
       
   403         
       
   404     CNcdPurchaseOperationProxy* operation( NULL );
       
   405     
       
   406     CNcdPurchaseOptionProxy& option =
       
   407         *static_cast<CNcdPurchaseOptionProxy*>( &aPurchaseOption );
       
   408 
       
   409 
       
   410     // Given purchaseoption is old and should not be used anymore
       
   411     if ( option.IsObsolete() )
       
   412         {
       
   413         User::Leave( KNcdErrorObsolete );
       
   414         }
       
   415 
       
   416 
       
   417     // Now if validuntil for subscription has passed, we should not allow it
       
   418     // to be bought anymore
       
   419     if ( option.PurchaseOptionType() == MNcdPurchaseOption::ESubscription )
       
   420         {
       
   421         TTime now;
       
   422         now.HomeTime();
       
   423         
       
   424         // The time until the node is subscribable is stored in the
       
   425         // subscribable content of the NodePurchase interface where to
       
   426         // the GIVEN PURCHASEOPTION belongs to.
       
   427         const CNcdClientSubscribableContent* subscribableContent =
       
   428             option.ParentNodePurchase()->SubscribableContent();
       
   429 
       
   430         DASSERT( subscribableContent );
       
   431         if ( subscribableContent &&
       
   432              subscribableContent->ValidUntilSet() &&
       
   433              now > subscribableContent->ValidUntil() )
       
   434             {
       
   435             User::Leave( KNcdErrorSubscriptionNotSubscribableAnymore );
       
   436             }
       
   437 
       
   438         }
       
   439 
       
   440 
       
   441     DLTRACE(( _L("Purchase started with option whose name is: %S"),
       
   442               &option.Name() ));
       
   443   
       
   444   
       
   445     // NOTICE: In the case of subscription or upgrade the purchaseoption
       
   446     //         can be from another node. That is why we give
       
   447     //         node-reference from the purchaseoption.
       
   448     operation = 
       
   449         Metadata().Node().OperationManager().
       
   450         CreatePurchaseOperationL( option.ParentNodePurchase()->Metadata().Node(), 
       
   451                                   option,
       
   452                                   &aObserver );
       
   453 
       
   454     // It is enough that the observer is informed
       
   455     // when the file operation is ready. So, no need to add
       
   456     // node or this class object to be observers.
       
   457 
       
   458     // No need to increase the operation ref count here because
       
   459     // it should be initially one.
       
   460 
       
   461     DLTRACEOUT((""));
       
   462         
       
   463     return operation;
       
   464     }
       
   465 
       
   466 // ---------------------------------------------------------------------------
       
   467 // From class MNcdNodePurchase.
       
   468 // ?implementation_description
       
   469 // ---------------------------------------------------------------------------
       
   470 //
       
   471 TBool CNcdNodePurchaseProxy::IsPurchased() const
       
   472     {
       
   473     return iIsPurchased;
       
   474     }
       
   475 
       
   476     
       
   477 // ---------------------------------------------------------------------------
       
   478 // From class MNcdNodePurchase.
       
   479 // ?implementation_description
       
   480 // ---------------------------------------------------------------------------
       
   481 //
       
   482 MNcdPurchaseOption* CNcdNodePurchaseProxy::PurchasedOptionL() const
       
   483     {
       
   484     if ( !IsPurchased() )
       
   485         {
       
   486         return NULL;
       
   487         }
       
   488 
       
   489     return PurchaseOptionL( *iPurchasedOptionId );
       
   490     }
       
   491     
       
   492 // ---------------------------------------------------------------------------
       
   493 // From class MNcdNodePurchase.
       
   494 // ?implementation_description
       
   495 // ---------------------------------------------------------------------------
       
   496 //
       
   497 TTime CNcdNodePurchaseProxy::TimeOfPurchaseL() const
       
   498     {
       
   499     if ( !IsPurchased() )
       
   500         {
       
   501         User::Leave( KErrNotFound );
       
   502         }
       
   503     
       
   504     return iTimeOfPurchase;    
       
   505     }
       
   506 
       
   507 // ---------------------------------------------------------------------------
       
   508 // From class MNcdNodePurchase.
       
   509 // ?implementation_description
       
   510 // ---------------------------------------------------------------------------
       
   511 //
       
   512 const TDesC& CNcdNodePurchaseProxy::PurchasedPriceL() const
       
   513     {
       
   514     if ( !IsPurchased() )
       
   515         {
       
   516         User::Leave( KErrNotFound );
       
   517         }
       
   518     
       
   519     return *iPurchasedPrice;
       
   520     }    
       
   521     
       
   522     
       
   523 void CNcdNodePurchaseProxy::InternalizeMeansDataL( RReadStream& aStream )
       
   524     {
       
   525     DLTRACEIN((""));
       
   526         
       
   527     // Subscribable content is read into its own class
       
   528     TBool subscribableContentFound( aStream.ReadInt32L() );
       
   529     if ( subscribableContentFound )
       
   530         {
       
   531         if ( iSubscribableContent == NULL )
       
   532             {
       
   533             iSubscribableContent = CNcdClientSubscribableContent::NewL();
       
   534             }        
       
   535         iSubscribableContent->InternalizeL( aStream );
       
   536         }
       
   537 
       
   538     
       
   539     TInt handleCount = aStream.ReadInt32L();
       
   540     DLINFO((( "handle count: %d" ), handleCount ));
       
   541     
       
   542     for ( TInt i = 0; i < handleCount; i++ ) 
       
   543         {
       
   544         TInt tmpProxyHandle = aStream.ReadInt32L();
       
   545         CNcdPurchaseOptionProxy* tmpPurchaseOption = 
       
   546             CNcdPurchaseOptionProxy::NewLC( 
       
   547                 ClientServerSession(),
       
   548                 tmpProxyHandle,
       
   549                 *this );
       
   550         
       
   551         TRAPD( addError, iPurchaseOptions.AppendL( tmpPurchaseOption ) );
       
   552         if ( addError != KErrNone )
       
   553             {
       
   554             CleanupStack::PopAndDestroy( tmpPurchaseOption );
       
   555             User::Leave( addError );
       
   556             }
       
   557             
       
   558         CleanupStack::Pop( tmpPurchaseOption );
       
   559         tmpPurchaseOption->InternalizeL();
       
   560         }
       
   561 
       
   562     DLTRACEOUT((""));
       
   563     }
       
   564 
       
   565 
       
   566 void CNcdNodePurchaseProxy::InternalizeHistoryDataL( RReadStream& aStream )
       
   567     {
       
   568     DLTRACEIN((""));
       
   569     
       
   570     // Reset values so that if we receive message that for some reason
       
   571     // does not contain purchase history info, we don't keep the old
       
   572     // purchase history info in memory.
       
   573     ResetHistoryData();
       
   574     
       
   575     // Node class id. Not actually needed.
       
   576     aStream.ReadInt32L();
       
   577     
       
   578     
       
   579     iIsPurchased = aStream.ReadInt32L();
       
   580     if ( iIsPurchased == EFalse )
       
   581         {
       
   582         return;
       
   583         }
       
   584 
       
   585     InternalizeDesL( iPurchasedOptionId, aStream );
       
   586 
       
   587     TInt64 integerTimeOfPurchase( 0 );
       
   588     // Store framework provides the necessary implementation for 
       
   589     // the operator>> to internalise the 64-bit integer
       
   590     aStream >> integerTimeOfPurchase;
       
   591     iTimeOfPurchase = TTime( integerTimeOfPurchase );
       
   592 
       
   593     InternalizeDesL( iPurchasedPrice, aStream );
       
   594 
       
   595 
       
   596     DLTRACEOUT((""));
       
   597     }
       
   598 
       
   599 
       
   600 void CNcdNodePurchaseProxy::DeletePurchaseOptions()
       
   601     {
       
   602     DLTRACEIN(("Handling %d purchase options", iPurchaseOptions.Count() ));
       
   603     for ( TInt i = iPurchaseOptions.Count() - 1; i >= 0; --i )
       
   604         {
       
   605         CNcdPurchaseOptionProxy* tmpOption = iPurchaseOptions[i];
       
   606         
       
   607         if ( tmpOption->MyTotalRefCount() > 0 )
       
   608             {
       
   609             // to prevent loops remove purchaseoption first
       
   610             // so it won't become deleted            
       
   611             iPurchaseOptions.Remove( i );
       
   612             
       
   613             tmpOption->SetObsolete(); 
       
   614             // Remove the purchase option from the interface parent.
       
   615             // This will update the parent reference count.
       
   616             // Because purchase option does not provide any interfaces for
       
   617             // the parent, it is safe to use this function.
       
   618             tmpOption->RemoveFromParent();
       
   619             if ( tmpOption->TotalRefCount() == 0 )
       
   620                 {
       
   621                 DLINFO(("Purchase option can be deleted here."));
       
   622                 delete tmpOption;
       
   623                 }
       
   624             }
       
   625         }
       
   626     DLTRACE(("Deleting %d purchase options", iPurchaseOptions.Count() ));
       
   627     iPurchaseOptions.ResetAndDestroy();    
       
   628     }
       
   629 
       
   630 void CNcdNodePurchaseProxy::ResetHistoryData()
       
   631     {
       
   632     iIsPurchased = EFalse;
       
   633     delete iPurchasedOptionId;
       
   634     iPurchasedOptionId = NULL;
       
   635     iTimeOfPurchase = TTime( 0 );    
       
   636     delete iPurchasedPrice;
       
   637     iPurchasedPrice = NULL;
       
   638     }
       
   639 
       
   640 CDesCArray* CNcdNodePurchaseProxy::RequestPurchaseOptionIdsL() 
       
   641     {
       
   642     DLTRACEIN((""));
       
   643     
       
   644     HBufC8* data( NULL );
       
   645         
       
   646     // Because we do not know the exact size of the data, use
       
   647     // the alloc method, which creates the buffer of the right size
       
   648     // and sets the pointer to point to the created buffer.
       
   649     User::LeaveIfError(
       
   650             ClientServerSession().
       
   651                 SendSyncAlloc( NcdNodeFunctionIds::ENcdPurchaseOptionIds,
       
   652                                KNullDesC8,
       
   653                                data,
       
   654                                Handle(),
       
   655                                0 ) );
       
   656 
       
   657     if ( data == NULL )
       
   658         {
       
   659         User::Leave( KErrNotFound );
       
   660         }
       
   661 
       
   662     CleanupStack::PushL( data );
       
   663 
       
   664     // Read the data from the stream
       
   665     RDesReadStream stream( *data );
       
   666     CleanupClosePushL( stream );
       
   667     
       
   668     TInt purchaseOptionCount = stream.ReadInt32L();
       
   669     CDesCArray* array = new( ELeave ) CDesCArrayFlat( 5 );
       
   670     CleanupStack::PushL( array );
       
   671     for ( TInt i = 0; i < purchaseOptionCount; i++ ) 
       
   672         {
       
   673         HBufC* des( NULL );
       
   674         InternalizeDesL( des, stream );
       
   675         CleanupStack::PushL( des );
       
   676         array->AppendL( *des );
       
   677         CleanupStack::PopAndDestroy( des );
       
   678         }
       
   679         
       
   680     CleanupStack::Pop( array );
       
   681     CleanupStack::PopAndDestroy( &stream );
       
   682     CleanupStack::PopAndDestroy( data );
       
   683     
       
   684     return array;
       
   685     }
       
   686     
       
   687 void CNcdNodePurchaseProxy::ReleaseMissingPurchaseOptions(
       
   688     const CDesCArray& aPurchaseOptionIds ) 
       
   689     {
       
   690     DLTRACEIN((""));
       
   691     
       
   692     for ( TInt i = iPurchaseOptions.Count() - 1; i >= 0; i-- ) 
       
   693         {
       
   694         TInt index;
       
   695         if ( aPurchaseOptionIds.Find( iPurchaseOptions[i]->Id(), index ) != 0 ) 
       
   696             {
       
   697             iPurchaseOptions[i]->SetObsolete();
       
   698             // Remove the purchase option from the interface parent.
       
   699             // This will update the parent reference count.
       
   700             // Because purchase option does not provide any interfaces for
       
   701             // the parent, it is safe to use this function.
       
   702             iPurchaseOptions[i]->RemoveFromParent();
       
   703             if ( iPurchaseOptions[ i ]->TotalRefCount() == 0 )
       
   704                 {
       
   705                 DLINFO(("Purchase option can be deleted."));
       
   706                 delete iPurchaseOptions[ i ];
       
   707                 }
       
   708             iPurchaseOptions.Remove( i );
       
   709             }
       
   710         }
       
   711     }
       
   712     
       
   713 void CNcdNodePurchaseProxy::InternalizeExistingPurchaseOptionsL() 
       
   714     {
       
   715     DLTRACEIN((""));
       
   716     
       
   717     for ( TInt i = 0; i < iPurchaseOptions.Count(); i++ ) 
       
   718         {
       
   719         iPurchaseOptions[i]->InternalizeL();
       
   720         }
       
   721     }
       
   722     
       
   723 void CNcdNodePurchaseProxy::InternalizeMeansL(
       
   724     const CDesCArray& aPurchaseOptionIds ) 
       
   725     {
       
   726     DLTRACEIN((""));
       
   727 
       
   728     CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
       
   729     CleanupStack::PushL( buf );
       
   730                 
       
   731     RBufWriteStream writeStream( *buf );
       
   732     CleanupClosePushL( writeStream );
       
   733     writeStream.WriteInt32L( aPurchaseOptionIds.Count() );
       
   734     for ( TInt i = 0; i < aPurchaseOptionIds.Count(); i++ ) 
       
   735         {
       
   736         ExternalizeDesL( aPurchaseOptionIds[i], writeStream );     
       
   737         }
       
   738     
       
   739     CleanupStack::PopAndDestroy( &writeStream );
       
   740     HBufC8* messageToSend = HBufC8::NewL( buf->Size() );
       
   741     messageToSend->Des().Copy( buf->Ptr( 0 ) );
       
   742     
       
   743     CleanupStack::PopAndDestroy( buf );
       
   744     CleanupStack::PushL( messageToSend );
       
   745     
       
   746     // Request handles to the new purchase options.
       
   747     HBufC8* data( NULL );
       
   748         
       
   749     // Because we do not know the exact size of the data, use
       
   750     // the alloc method, which creates the buffer of the right size
       
   751     // and sets the pointer to point to the created buffer.
       
   752     User::LeaveIfError(
       
   753             ClientServerSession().
       
   754                 SendSyncAlloc( NcdNodeFunctionIds::ENcdInternalizePurchaseMeans,
       
   755                                *messageToSend,
       
   756                                data,
       
   757                                Handle(),
       
   758                                0 ) );
       
   759                                
       
   760     CleanupStack::PopAndDestroy( messageToSend );
       
   761     messageToSend = NULL;
       
   762 
       
   763     if ( data == NULL )
       
   764         {
       
   765         User::Leave( KErrNotFound );
       
   766         }
       
   767 
       
   768     CleanupStack::PushL( data );
       
   769 
       
   770     // Read the data from the stream
       
   771     RDesReadStream stream( *data );
       
   772     CleanupClosePushL( stream );
       
   773 
       
   774     InternalizeMeansDataL( stream );
       
   775 
       
   776     CleanupStack::PopAndDestroy( &stream );
       
   777     CleanupStack::PopAndDestroy( data );
       
   778     }
       
   779     
       
   780 TBool CNcdNodePurchaseProxy::HasPurchaseOption( const TDesC& aId ) const 
       
   781     {
       
   782     DLTRACEIN((""));
       
   783     for ( TInt i = 0; i < iPurchaseOptions.Count(); i++ ) 
       
   784         {
       
   785         if ( iPurchaseOptions[i]->Id() == aId ) 
       
   786             {
       
   787             return ETrue;
       
   788             }
       
   789         }
       
   790         
       
   791     return EFalse;
       
   792     }