--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ncdengine/provider/server/src/ncdsubscriptionimpl.cpp Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,758 @@
+/*
+* 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: Implements CNcdSubscription class
+*
+*/
+
+
+#include "ncdsubscriptionimpl.h"
+
+#include "ncdpurchaseoptionimpl.h"
+#include "ncdserversubscription.h"
+#include "ncdserverpartofsubscription.h"
+#include "ncdserverupgrade.h"
+#include "ncd_pp_subscriptiondetails.h"
+#include "catalogssession.h"
+#include "catalogsbasemessage.h"
+#include "ncdnodefunctionids.h"
+#include "ncdnodeclassids.h"
+#include "catalogsconstants.h"
+#include "ncd_pp_dataentity.h"
+#include "ncd_cp_query.h"
+#include "ncd_pp_subscription.h"
+#include "catalogsutils.h"
+#include "ncdserversubscribablecontent.h"
+#include "ncdsubscriptiongroup.h"
+#include "ncdprotocolutils.h"
+
+#include "catalogsdebug.h"
+
+
+CNcdSubscription::CNcdSubscription( CNcdSubscriptionGroup& aParentGroup )
+ : CCatalogsCommunicable(),
+ iParentGroup( aParentGroup )
+ {
+ }
+
+void CNcdSubscription::ConstructL()
+ {
+ }
+
+
+CNcdSubscription* CNcdSubscription::NewL(
+ CNcdSubscriptionGroup& aParentGroup )
+ {
+ CNcdSubscription* self =
+ CNcdSubscription::NewLC( aParentGroup );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+CNcdSubscription* CNcdSubscription::NewLC(
+ CNcdSubscriptionGroup& aParentGroup )
+ {
+ CNcdSubscription* self =
+ new( ELeave ) CNcdSubscription( aParentGroup );
+ CleanupClosePushL( *self );
+ self->ConstructL();
+ return self;
+ }
+
+CNcdSubscription::~CNcdSubscription()
+ {
+ DLTRACEIN((""));
+
+ ResetMemberVariables();
+
+ DLTRACEOUT((""));
+ }
+
+const TDesC& CNcdSubscription::SubscriptionName() const
+ {
+ DLTRACEIN((""));
+ if ( iName == NULL )
+ {
+ DLTRACEOUT((""));
+ return KNullDesC;
+ }
+ else
+ {
+ DLTRACEOUT((""));
+ return *iName;
+ }
+ }
+
+void CNcdSubscription::SetSubscriptionNameL( const TDesC& aNewName )
+ {
+ delete iName;
+ iName = NULL;
+ iName = aNewName.AllocL();
+ }
+
+const TDesC& CNcdSubscription::PurchaseOptionId() const
+ {
+ DLTRACEIN((""));
+ if ( iPurchaseOptionId == NULL )
+ {
+ DLTRACEOUT((""));
+ return KNullDesC;
+ }
+ else
+ {
+ DLTRACEOUT((""));
+ return *iPurchaseOptionId;
+ }
+ }
+
+
+CNcdSubscriptionGroup& CNcdSubscription::ParentGroup() const
+ {
+ DLTRACEIN((""));
+ return iParentGroup;
+ }
+
+MNcdSubscription::TType CNcdSubscription::SubscriptionType() const
+ {
+ DLTRACEIN((""));
+ return iSubscriptionType;
+ }
+
+void CNcdSubscription::InternalizeL( const CNcdPurchaseOptionImpl& aData )
+ {
+ DLTRACEIN(("Subscriptionimpl internalizing from purchase option."));
+
+ // Current time saved in the beginning for later use.
+ // Done as soon as possible so it won't be too long
+ // after message is received from the server and delta
+ // values are hopefully still valid.
+ TTime now;
+ now.HomeTime();
+
+
+ ResetMemberVariables();
+
+ iName = aData.PurchaseOptionName().AllocL();
+ DLTRACE(( _L("Name: %S."), iName ));
+
+ // Cannot get expired on info from the purchaseoption and
+ // if this subscription is just bought as it should be, it
+ // has not expired.
+ // Expired on is left into its initial value.
+
+ // The same thing is with iCancelled. It is assumed that as the
+ // subscription is just bought, it is not unsubscribed yet.
+
+
+ // Get subscription type from the subscribable content
+ const CNcdServerSubscribableContent* subscribableContent =
+ aData.ParentSubscribableContent();
+
+ // Protocol makes it possible that although we have a node that has
+ // a purchaseoption that can be used to buy a subscription the node
+ // does not need to have a subscribable content field.
+ if ( subscribableContent != NULL )
+ {
+ iSubscriptionType = subscribableContent->SubscriptionType();
+ DLINFO(( "Subscriptionimpl internalizing, type: %d",
+ iSubscriptionType ));
+ }
+ else
+ {
+ // We use the default type of subscription
+ DLINFO(( "Subscribable content not found, have to use default type: %d",
+ iSubscriptionType ));
+ }
+
+
+ // Next we set total values if they are set in the subscription
+
+ const CNcdServerSubscription* subscriptionInfo =
+ aData.SubscriptionInfo();
+ if ( subscriptionInfo == NULL )
+ {
+ User::Leave( KErrArgument );
+ }
+
+
+ iTotalValidityDelta = subscriptionInfo->ValidityDelta();
+ DLINFO(( "Total validitydelta: %d.", iTotalValidityDelta ));
+ if ( iTotalValidityDelta >= 0 )
+ {
+ iValidityTimeSet = ETrue;
+ }
+ DLINFO(( "ValidityTimeSet: %d.", iValidityTimeSet ));
+
+ iTotalCredits = subscriptionInfo->AmountOfCredits();
+ DLINFO(( "Total credits: %f.", iTotalCredits ));
+ // Simple >0 is decided to be enough because no complicated operations
+ // are done with TReal numbers
+ if ( iTotalCredits >= 0 )
+ {
+ iCreditLimitSet = ETrue;
+ }
+
+ iTotalDownloads = subscriptionInfo->NumberOfDownloads();
+ DLINFO(( "Total downloads: %d.", iTotalDownloads ));
+ if ( iTotalDownloads >= 0 )
+ {
+ iDownloadLimitSet = ETrue;
+ }
+
+
+ // Because this function should be used just after purchase
+ // of the subscription, we set maximum values to the
+ // "left" variables
+
+ // validityDelta is in minutes so we use TTimeIntervalMinutes
+ // to reprsent the interval
+ TTimeIntervalMinutes validityInterval( iTotalValidityDelta );
+ iValidUntil = now + validityInterval;
+
+ iCreditsLeft = iTotalCredits;
+ iDownloadsLeft = iTotalDownloads;
+
+ iPurchaseOptionId = aData.Id().AllocL();
+
+ DLTRACEOUT((""));
+ }
+
+
+
+
+void CNcdSubscription::InternalizeL(
+ MNcdPreminetProtocolSubscription& aData )
+ {
+ DLTRACEIN(("Subscriptionimpl internalizing from protocol."));
+
+ // Current time saved in the beginning for later use.
+ // Done as soon as possible so it won't be too long
+ // after message is received from the server and delta
+ // values are hopefully still valid.
+ TTime now;
+ now.HomeTime();
+
+
+ // ResetMemberVariables function is not called here
+ // because it deletes all member variables and
+ // we cannot recreate all of them from the given protocol object.
+
+ // Instead ResetProtocolMemberVariables is called
+ ResetProtocolMemberVariables();
+
+
+ // Nothing is done to existing name and icon
+ // info because hopefully they are received some other way
+ // (from purchase option)
+
+
+ iExpiredOn = aData.ExpiredOn().AllocL();
+
+ iCancelled = aData.Cancelled();
+
+ TNcdSubscriptionType tmpType = aData.Type();
+ DASSERT( tmpType != ENotSubscribable );
+
+ switch( tmpType )
+ {
+ case EPeriodic:
+ iSubscriptionType = MNcdSubscription::EPeriodic;
+ break;
+
+ case EAutomaticContinous:
+ iSubscriptionType = MNcdSubscription::EAutomaticContinous;
+ break;
+
+ default:
+ DASSERT( false ); // Should not end up here
+ break;
+ }
+
+
+ // If we have a expired subscription TotalUsageRights is
+ // assumed to return usagerights of the expired subscription
+ const MNcdPreminetProtocolSubscriptionDetails* totalRights =
+ aData.TotalUsageRights();
+
+ DASSERT( totalRights != NULL );
+
+ if ( totalRights != NULL )
+ {
+ // We assume here that if any of the original limits or
+ // validity negative then that particular limit or validity
+ // is not in use.
+
+ iTotalValidityDelta = totalRights->ValidityDelta();
+ if ( iTotalValidityDelta >= 0 )
+ {
+ iValidityTimeSet = ETrue;
+ }
+
+
+ iTotalCredits = totalRights->AmountOfCredits();
+ // Also here >0 is deemed to be enough because no complicated
+ // operations are done on the TReal numbers
+ if ( iTotalCredits >= 0 )
+ {
+ iCreditLimitSet = ETrue;
+ }
+
+ iTotalDownloads = totalRights->NumberOfDownloads();
+ if ( iTotalDownloads >= 0 )
+ {
+ iDownloadLimitSet = ETrue;
+ }
+ }
+
+
+ const MNcdPreminetProtocolSubscriptionDetails* remainingRights =
+ aData.RemainingUsageRights();
+
+ TInt validityDelta( -1 );
+ if ( remainingRights != NULL )
+ {
+ validityDelta = remainingRights->ValidityDelta();
+
+ // validityDelta is in minutes so we use TTimeIntervalMinutes
+ // to reprsent the interval
+ TTimeIntervalMinutes validityInterval( validityDelta );
+ iValidUntil = now + validityInterval;
+
+ iCreditsLeft = remainingRights->AmountOfCredits();
+ iDownloadsLeft = remainingRights->NumberOfDownloads();
+ }
+
+
+ // expiredOn is set to iValidUntil so that client can receive
+ // some kind of validuntil (from proxyside interface)
+ // even if the subscription has already expired.
+ // This way iValidUntil is not necessiraly the original validUntil.
+ // For example in situation where other constraint has run out first
+ // (for example credits), iValidUntil would be this expiration
+ // point. Anyway it is close enough.
+ // NOTICE: iValidUntil of expired subscription cannot be greater
+ // than "now" because server does not return
+ // remaining usagerights of expired subscriptions
+ if ( iValidityTimeSet && validityDelta == -1 && iExpiredOn != NULL &&
+ *iExpiredOn != KNullDesC )
+ {
+ iValidUntil = NcdProtocolUtils::DesToTimeL( *iExpiredOn );
+ }
+
+ iPurchaseOptionId = aData.PurchaseOptionId().AllocL();
+
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdSubscription::SetRecentlyUpdated( TBool aNewState )
+ {
+ DLTRACEIN((""));
+ iRecentlyUpdated = aNewState;
+ DLTRACEOUT((""));
+ }
+
+TBool CNcdSubscription::RecentlyUpdated() const
+ {
+ DLTRACEIN((""));
+ DLTRACEOUT((""));
+ return iRecentlyUpdated;
+ }
+
+
+
+// Internalization from and externalization to the database
+
+void CNcdSubscription::ExternalizeL( RWriteStream& aStream )
+ {
+ DLTRACEIN((""));
+
+ ExternalizeOwnDataL( aStream );
+
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdSubscription::InternalizeL( RReadStream& aStream )
+ {
+ DLTRACEIN((""));
+
+ ResetMemberVariables();
+
+ InternalizeDesL( iName, aStream );
+ InternalizeDesL( iExpiredOn, aStream );
+
+ iCancelled = aStream.ReadInt32L();
+
+ iSubscriptionType =
+ static_cast<MNcdSubscription::TType>(aStream.ReadInt32L());
+
+ iValidityTimeSet = aStream.ReadInt32L();
+ TInt64 intValidUntil( 0 );
+ aStream >> intValidUntil;
+ iValidUntil = intValidUntil;
+ iTotalValidityDelta = aStream.ReadInt32L();
+
+ iCreditLimitSet = aStream.ReadInt32L();
+ iCreditsLeft = aStream.ReadReal32L();
+ iTotalCredits = aStream.ReadReal32L();
+
+ iDownloadLimitSet = aStream.ReadInt32L();
+ iDownloadsLeft = aStream.ReadInt32L();
+ iTotalDownloads = aStream.ReadInt32L();
+
+ InternalizeDesL( iPurchaseOptionId, aStream );
+
+ DLTRACE(( _L(" Internalized subscription, purchaseoptionid: %S"),
+ iPurchaseOptionId ));
+
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdSubscription::ReceiveMessage( MCatalogsBaseMessage* aMessage,
+ TInt aFunctionNumber )
+ {
+ DLTRACEIN((""));
+
+ DASSERT( aMessage );
+
+ // Now, we can be sure that rest of the time iMessage exists.
+ // This member variable is set for the CounterPartLost function.
+ iMessage = aMessage;
+
+ TInt trapError( KErrNone );
+
+ // Check which function is called by the proxy side object.
+ // Function number are located in ncdnodefunctinoids.h file.
+ switch( aFunctionNumber )
+ {
+ case NcdNodeFunctionIds::ENcdInternalize:
+ // Internalize the proxy side according to the data
+ // of this object.
+ TRAP( trapError, InternalizeRequestL( *aMessage ) );
+ break;
+
+ case NcdNodeFunctionIds::ENcdRelease:
+ // The proxy does not want to use this object anymore.
+ // So, release the handle from the session.
+ ReleaseRequest( *aMessage );
+ break;
+
+ default:
+ break;
+ }
+
+ if ( trapError != KErrNone )
+ {
+ // Because something went wrong, the complete has not been
+ // yet called for the message.
+ // So, inform the client about the error if the
+ // message is still available.
+ aMessage->CompleteAndRelease( trapError );
+ }
+
+ // Because the message should not be used after this, set it NULL.
+ // So, CounterPartLost function will know that no messages are
+ // waiting the response at the moment.
+ iMessage = NULL;
+
+ DLTRACEOUT((""));
+ }
+
+void CNcdSubscription::CounterPartLost( const MCatalogsSession& aSession )
+ {
+ // This function may be called whenever -- when the message is waiting
+ // response or when the message does not exist.
+ // iMessage may be NULL here, because in the end of the
+ // ReceiveMessage it is set to NULL. The life time of the message
+ // ends shortly after CompleteAndRelease is called.
+ if ( iMessage != NULL )
+ {
+ iMessage->CounterPartLost( aSession );
+ }
+ }
+
+
+void CNcdSubscription::InternalizeRequestL( MCatalogsBaseMessage& aMessage )
+ {
+ DLTRACEIN((""));
+
+ CBufBase* buf = CBufFlat::NewL( KBufExpandSize );
+ CleanupStack::PushL( buf );
+
+ RBufWriteStream stream( *buf );
+ CleanupClosePushL( stream );
+
+
+ // Include all the necessary node data to the stream
+ ExternalizeDataForRequestL( stream );
+
+
+ // Commits data to the stream when closing.
+ CleanupStack::PopAndDestroy( &stream );
+
+
+ // If this leaves, ReceiveMessage will complete the message.
+ // NOTE: that here we expect that the buffer contains at least
+ // some data. So, make sure that ExternalizeDataForRequestL inserts
+ // something to the buffer.
+ aMessage.CompleteAndReleaseL( buf->Ptr( 0 ), KErrNone );
+
+
+ DLTRACE(("Deleting the buf"));
+ CleanupStack::PopAndDestroy( buf );
+
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdSubscription::ExternalizeDataForRequestL( RWriteStream& aStream )
+ {
+ DLTRACEIN((""));
+
+ ExternalizeOwnDataL( aStream );
+
+ DLTRACEOUT((""));
+ }
+
+void CNcdSubscription::ReleaseRequest( MCatalogsBaseMessage& aMessage ) const
+ {
+ DLTRACEIN((""));
+
+ // Decrease the reference count for this object.
+ // When the reference count reaches zero, this object will be destroyed
+ // and removed from the session.
+ MCatalogsSession& requestSession( aMessage.Session() );
+ TInt handle( aMessage.Handle() );
+
+ // Send complete information back to proxy.
+ aMessage.CompleteAndRelease( KErrNone );
+
+ // Remove this object from the session.
+ requestSession.RemoveObject( handle );
+
+ DLTRACEOUT((""));
+ }
+
+
+
+
+void CNcdSubscription::UseL( const CNcdPurchaseOptionImpl& aData )
+ {
+ DLTRACEIN((""));
+ // If subscription is used, then the purchaseoption
+ // has to have a partOfSubscription component.
+
+ const CNcdServerPartOfSubscription* partOfSubscriptionInfo =
+ aData.PartOfSubscriptionInfo();
+
+ if ( partOfSubscriptionInfo == NULL )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ if ( aData.IsFree() )
+ {
+ // Free purchase from subscription
+ // Do nothing
+ return;
+ }
+
+ TReal32 creditPrice( partOfSubscriptionInfo->CreditPrice() );
+ // Only simple floating point operations are done so simple
+ // checking (>0) is also decided to be enough.
+ if ( creditPrice >= 0 )
+ {
+ //DASSERT( iCreditLimitSet );
+ iCreditsLeft = iCreditsLeft - creditPrice;
+ }
+
+ if ( iDownloadLimitSet )
+ {
+ --iDownloadsLeft;
+ }
+
+ if ( !(creditPrice >= 0) && !iDownloadLimitSet )
+ {
+ // This would be quite weird situation where purchase is not
+ // free but no cost information is provided
+ DLINFO(("Purchase with subscription is not free but it contains no cost information!"));
+ }
+
+ DLTRACEOUT((""));
+ }
+
+
+
+void CNcdSubscription::UpgradeL( const CNcdPurchaseOptionImpl& aData )
+ {
+ // If subscription is upgraded, then the purchaseoption should
+ // have upgrade component.
+
+ const CNcdServerUpgrade* upgradeInfo = aData.UpgradeInfo();
+ if ( upgradeInfo == NULL )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // All values received in upgrade are just added to the
+ // current values. They have to be added also to total values
+ // so that the info can be used for example when renewing.
+
+
+ TInt validityDelta = upgradeInfo->ValidityDelta();
+ // validityDelta is in minutes so we use TTimeIntervalMinutes
+ // to represent the interval
+ if ( validityDelta >= 0 )
+ {
+ TTimeIntervalMinutes validityInterval( validityDelta );
+ iValidUntil = iValidUntil + validityInterval;
+ iTotalValidityDelta = iTotalValidityDelta + validityDelta;
+ }
+ else
+ {
+ // This constraint is not in use anymore
+ iValidityTimeSet = EFalse;
+ iValidUntil = -1;
+ iTotalValidityDelta = -1;
+ }
+
+
+ TInt creditsLeft( upgradeInfo->AmountOfCredits() );
+ if ( iCreditsLeft >= 0 )
+ {
+ iCreditsLeft = iCreditsLeft + creditsLeft;
+ iTotalCredits = iTotalCredits + creditsLeft;
+ }
+ else
+ {
+ // This constraint is not in use anymore
+ iCreditLimitSet = EFalse;
+ iCreditsLeft = -1;
+ iTotalCredits = -1;
+ }
+
+ TInt downloadsLeft( upgradeInfo->NumberOfDownloads() );
+ if ( downloadsLeft >= 0 )
+ {
+ iDownloadsLeft = iDownloadsLeft + downloadsLeft;
+ iTotalDownloads = iTotalDownloads + downloadsLeft;
+ }
+ else
+ {
+ // This constraint is not in use anymore
+ iDownloadLimitSet = EFalse;
+ iDownloadsLeft = -1;
+ iTotalDownloads = -1;
+ }
+ }
+
+void CNcdSubscription::ExternalizeOwnDataL( RWriteStream& aStream )
+ {
+ DLTRACEIN((""));
+
+ if ( iName != NULL )
+ {
+ ExternalizeDesL( *iName, aStream );
+ DLTRACE(( _L("Externalizing subscription info, name: %S"),
+ iName ));
+ }
+ else
+ {
+ ExternalizeDesL( KNullDesC, aStream );
+ DLINFO(( "Externalizing subscription info, no name found." ));
+ }
+
+ if ( iExpiredOn != NULL )
+ {
+ ExternalizeDesL( *iExpiredOn, aStream );
+ DLTRACE(( _L("Externalizing subscription info, expired on: %S"),
+ iExpiredOn ));
+ }
+ else
+ {
+ ExternalizeDesL( KNullDesC, aStream );
+ DLINFO(( "Externalizing subscription info, no expired on info found." ));
+ }
+
+ aStream.WriteInt32L( iCancelled );
+
+ // NOTICE: This is a little bit dangerous. If the
+ // subscription type is not found, it is the default
+ // value and that is externalized.
+ aStream.WriteInt32L( iSubscriptionType );
+
+ aStream.WriteInt32L( iValidityTimeSet );
+ const TInt64& intValidUntil = iValidUntil.Int64();
+ aStream << intValidUntil;
+ aStream.WriteInt32L( iTotalValidityDelta );
+
+ aStream.WriteInt32L( iCreditLimitSet );
+ aStream.WriteReal32L( iCreditsLeft );
+ aStream.WriteReal32L( iTotalCredits );
+
+ aStream.WriteInt32L( iDownloadLimitSet );
+ aStream.WriteInt32L( iDownloadsLeft );
+ aStream.WriteInt32L( iTotalDownloads );
+
+ DASSERT( iPurchaseOptionId != NULL );
+ ExternalizeDesL( *iPurchaseOptionId, aStream );
+
+ DLTRACE(( _L(" Externalized subscription, purchaseoptionid: %S"),
+ iPurchaseOptionId ));
+
+ DLTRACEOUT((""));
+ }
+
+
+void CNcdSubscription::ResetProtocolMemberVariables()
+ {
+ // In all cases this state variable is in the beginning false
+ // This has to be set especially by the user.
+ iRecentlyUpdated = EFalse;
+
+ delete iPurchaseOptionId;
+ iPurchaseOptionId = NULL;
+
+ // Name
+ // cannot be deleted as they are not received
+ // from the subscription protocol element.
+
+ delete iExpiredOn;
+ iExpiredOn = NULL;
+
+ iCancelled = EFalse;
+
+ iSubscriptionType = MNcdSubscription::EPeriodic;
+
+ iValidityTimeSet = EFalse;
+ iValidUntil = -1;
+ iTotalValidityDelta = -1;
+
+ iCreditLimitSet = EFalse;
+ iCreditsLeft = -1;
+ iTotalCredits = -1;
+
+ iDownloadLimitSet = EFalse;
+ iDownloadsLeft = -1;
+ iTotalDownloads = -1;
+ }
+
+void CNcdSubscription::ResetMemberVariables()
+ {
+ delete iName;
+ iName = NULL;
+
+ ResetProtocolMemberVariables();
+ }